// Author: Sergey Linev // Date: 2017-10-16 // Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome! /************************************************************************* * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT7_RWebWindow #define ROOT7_RWebWindow #include #include #include #include #include #include #include #include #include #include class THttpCallArg; class THttpServer; namespace ROOT { /// function signature for connect/disconnect call-backs /// argument is connection id using WebWindowConnectCallback_t = std::function; /// function signature for call-backs from the window clients /// first argument is connection id, second is received data using WebWindowDataCallback_t = std::function; /// function signature for waiting call-backs /// Such callback used when calling thread need to waits for some special data, /// but wants to run application event loop /// As argument, spent time in second will be provided /// Waiting will be performed until function returns non-zero value using WebWindowWaitFunc_t = std::function; class RFileDialog; class RWebWindowsManager; class RWebWindowWSHandler; class RWebWindow { friend class RWebWindowsManager; friend class RWebWindowWSHandler; friend class RWebDisplayHandle; friend class RFileDialog; private: using timestamp_t = std::chrono::time_point; struct QueueItem { int fChID{1}; /// fDisplayHandle; /// fHold; /// fQueue; ///> fEmbed; ///>; std::shared_ptr fMgr; /// fMaster; /// fMasterConns; /// fWSHandler; /// fInputQueue; /// fClearOnClose; /// CreateWSHandler(std::shared_ptr mgr, unsigned id, double tmout); bool ProcessWS(THttpCallArg &arg); void CompleteWSSend(unsigned wsid); ConnectionsList_t GetWindowConnections(unsigned connid = 0, bool only_active = false) const; std::shared_ptr FindOrCreateConnection(unsigned wsid, bool make_new, const char *query); /// Find connection with specified websocket id std::shared_ptr FindConnection(unsigned wsid) { return FindOrCreateConnection(wsid, false, nullptr); } std::shared_ptr RemoveConnection(unsigned wsid); std::shared_ptr _FindConnWithKey(const std::string &key) const; std::string _MakeSendHeader(std::shared_ptr &conn, bool txt, const std::string &data, int chid); void ProvideQueueEntry(unsigned connid, EQueueEntryKind kind, std::string &&arg); void InvokeCallbacks(bool force = false); void SubmitData(unsigned connid, bool txt, std::string &&data, int chid = 1); bool CheckDataToSend(std::shared_ptr &conn); void CheckDataToSend(bool only_once = false); bool HasKey(const std::string &key) const; std::string GenerateKey() const; void CheckPendingConnections(); void CheckInactiveConnections(); unsigned AddDisplayHandle(bool headless_mode, const std::string &key, std::unique_ptr &handle); unsigned AddEmbedWindow(std::shared_ptr window, unsigned connid, int channel); void RemoveEmbedWindow(unsigned connid, int channel); void AddMasterConnection(std::shared_ptr window, unsigned connid, int channel); std::vector GetMasterConnections(unsigned connid = 0) const; void RemoveMasterConnection(unsigned connid = 0); bool ProcessBatchHolder(std::shared_ptr &arg); std::string GetConnToken() const; unsigned MakeHeadless(bool create_new = false); unsigned FindHeadlessConnection(); static std::function &, unsigned, const std::string &)> gStartDialogFunc; static void SetStartDialogFunc(std::function &, unsigned, const std::string &)>); public: RWebWindow(); ~RWebWindow(); /// Returns ID for the window - unique inside window manager unsigned GetId() const { return fId; } /// Returns window manager std::shared_ptr GetManager() const { return fMgr; } /// Set content of default window HTML page /// This page returns when URL address of the window will be requested /// Either HTML code or file name in the form "file:/home/user/data/file.htm" /// One also can using default locations like "file:rootui5sys/canv/canvas.html" void SetDefaultPage(const std::string &page) { fDefaultPage = page; } void SetPanelName(const std::string &name); /// Set window geometry. Will be applied if supported by used web display (like CEF or Chromium) void SetGeometry(unsigned width, unsigned height) { fWidth = width; fHeight = height; } /// Set window position. Will be applied if supported by used web display (like CEF or Chromium) void SetPosition(unsigned x, unsigned y) { fX = x; fY = y; } ///////////////////////////////////////////////////////////////////////// /// returns configured window width (0 - default) /// actual window width can be different unsigned GetWidth() const { return fWidth; } ///////////////////////////////////////////////////////////////////////// /// returns configured window height (0 - default) unsigned GetHeight() const { return fHeight; } ///////////////////////////////////////////////////////////////////////// /// returns configured window X position (-1 - default) int GetX() const { return fX; } ///////////////////////////////////////////////////////////////////////// /// returns configured window Y position (-1 - default) int GetY() const { return fY; } void SetConnLimit(unsigned lmt = 0); unsigned GetConnLimit() const; void SetConnToken(const std::string &token = ""); ///////////////////////////////////////////////////////////////////////// /// configures maximal queue length of data which can be held by window void SetMaxQueueLength(unsigned len = 10) { fMaxQueueLength = len; } ///////////////////////////////////////////////////////////////////////// /// Return maximal queue length of data which can be held by window unsigned GetMaxQueueLength() const { return fMaxQueueLength; } ///////////////////////////////////////////////////////////////////////// /// configures that only native (own-created) connections are allowed void SetNativeOnlyConn(bool on = true) { fNativeOnlyConn = on; } ///////////////////////////////////////////////////////////////////////// /// returns true if only native (own-created) connections are allowed bool IsNativeOnlyConn() const { return fNativeOnlyConn; } void SetClientVersion(const std::string &vers); std::string GetClientVersion() const; void SetUserArgs(const std::string &args); std::string GetUserArgs() const; int NumConnections(bool with_pending = false) const; unsigned GetConnectionId(int num = 0) const; std::vector GetConnections(unsigned excludeid = 0) const; bool HasConnection(unsigned connid = 0, bool only_active = true) const; void CloseConnections(); void CloseConnection(unsigned connid); /// Returns timeout for synchronous WebWindow operations float GetOperationTmout() const { return fOperationTmout; } /// Set timeout for synchronous WebWindow operations void SetOperationTmout(float tm = 50.) { fOperationTmout = tm; } std::string GetUrl(bool remote = true); THttpServer *GetServer(); void Sync(); void Run(double tm = 0.); unsigned Show(const RWebDisplayArgs &args = ""); unsigned GetDisplayConnection() const; /// Returns true when window was shown at least once bool IsShown() const { return GetDisplayConnection() != 0; } bool CanSend(unsigned connid, bool direct = true) const; int GetSendQueueLength(unsigned connid) const; void Send(unsigned connid, const std::string &data); void SendBinary(unsigned connid, const void *data, std::size_t len); void SendBinary(unsigned connid, std::string &&data); void RecordData(const std::string &fname = "protocol.json", const std::string &fprefix = ""); std::string GetAddr() const; std::string GetRelativeAddr(const std::shared_ptr &win) const; std::string GetRelativeAddr(const RWebWindow &win) const; void SetCallBacks(WebWindowConnectCallback_t conn, WebWindowDataCallback_t data, WebWindowConnectCallback_t disconn = nullptr); void SetConnectCallBack(WebWindowConnectCallback_t func); void SetDataCallBack(WebWindowDataCallback_t func); void SetDisconnectCallBack(WebWindowConnectCallback_t func); void SetClearOnClose(const std::shared_ptr &handle = nullptr); void AssignThreadId(); void UseServerThreads(); int WaitFor(WebWindowWaitFunc_t check); int WaitForTimed(WebWindowWaitFunc_t check); int WaitForTimed(WebWindowWaitFunc_t check, double duration); void StartThread(); void StopThread(); void TerminateROOT(); static std::shared_ptr Create(); static unsigned ShowWindow(std::shared_ptr window, const RWebDisplayArgs &args = ""); static bool IsFileDialogMessage(const std::string &msg); static bool EmbedFileDialog(const std::shared_ptr &window, unsigned connid, const std::string &args); }; } // namespace ROOT #endif