Skip to content
Snippets Groups Projects
Commit c910a244 authored by Sergey Linev's avatar Sergey Linev
Browse files

[webwindow] support channels in RWebWindow

Same connection can be reused to transfer data over several channels.
Special RWebWindow::ShowWindow() method should be used.
Probably can be avoided in the future
parent 25567057
No related branches found
No related tags found
No related merge requests found
......@@ -17,14 +17,19 @@
#define ROOT7_RWebDisplayArgs
#include <string>
#include <memory>
class THttpServer;
namespace ROOT {
namespace Experimental {
class RWebWindow;
class RWebDisplayArgs {
friend class RWebWindow;
public:
enum EBrowserKind {
kChrome, ///< Google Chrome browser
......@@ -34,7 +39,7 @@ public:
kQt5, ///< QWebEngine libraries - Chrome code packed in qt5
kLocal, ///< either CEF or Qt5 - both runs on local display without real http server
kStandard, ///< standard system web browser, not recognized by ROOT, without batch mode
kEmbedded, ///< window will be embedded into other, no extra browser need to be started
kEmbedded, ///< window will be embedded into other, no extra browser need to be started
kCustom ///< custom web browser, execution string should be provided
};
......@@ -52,6 +57,9 @@ protected:
std::string fExec; ///<! string to run browser, used with kCustom type
void *fDriverData{nullptr}; ///<! special data delivered to driver, can be used for QWebEngine
std::shared_ptr<RWebWindow> fMaster; ///<! master window
int fMasterChannel{-1}; ///<! used master channel
public:
RWebDisplayArgs();
......@@ -61,6 +69,10 @@ public:
RWebDisplayArgs(int width, int height, int x = -1, int y = -1, const std::string &browser = "");
RWebDisplayArgs(std::shared_ptr<RWebWindow> master, int channel = -1);
virtual ~RWebDisplayArgs();
RWebDisplayArgs &SetBrowserKind(const std::string &kind);
/// set browser kind, see EBrowserKind for allowed values
RWebDisplayArgs &SetBrowserKind(EBrowserKind kind) { fKind = kind; return *this; }
......@@ -68,6 +80,8 @@ public:
EBrowserKind GetBrowserKind() const { return fKind; }
std::string GetBrowserName() const;
void SetMasterWindow(std::shared_ptr<RWebWindow> master, int channel = -1);
/// returns true if local display like CEF or Qt5 QWebEngine should be used
bool IsLocalDisplay() const
{
......
......@@ -86,6 +86,7 @@ private:
int fClientCredits{0}; ///<! number of credits received from client
bool fDoingSend{false}; ///<! true when performing send operation
std::queue<QueueItem> fQueue; ///<! output queue
std::map<int,std::shared_ptr<RWebWindow>> fEmbed; ///<! map of embed window for that connection, key value is channel id
WebConn() = default;
WebConn(unsigned connid) : fConnId(connid) {}
WebConn(unsigned connid, unsigned wsid) : fConnId(connid), fActive(true), fWSId(wsid) {}
......@@ -112,6 +113,9 @@ private:
typedef std::vector<std::shared_ptr<WebConn>> ConnectionsList;
std::shared_ptr<RWebWindowsManager> fMgr; ///<! display manager
std::shared_ptr<RWebWindow> fMaster; ///<! master window where this window is embeded
unsigned fMasterConnId{0}; ///<! master connection id
int fMasterChannel{-1}; ///<! channel id in the master window
std::string fDefaultPage; ///<! HTML page (or file name) returned when window URL is opened
std::string fPanelName; ///<! panel name which should be shown in the window
unsigned fId{0}; ///<! unique identifier
......@@ -177,6 +181,8 @@ private:
unsigned AddDisplayHandle(bool batch_mode, const std::string &key, std::unique_ptr<RWebDisplayHandle> &handle);
unsigned AddEmbedWindow(std::shared_ptr<RWebWindow> window, int channel);
bool ProcessBatchHolder(std::shared_ptr<THttpCallArg> &arg);
void AssignCallbackThreadId();
......@@ -316,6 +322,9 @@ public:
void TerminateROOT();
static std::shared_ptr<RWebWindow> Create();
static unsigned ShowWindow(std::shared_ptr<RWebWindow> window, const RWebDisplayArgs &args = "");
};
} // namespace Experimental
......
......@@ -14,6 +14,7 @@
*************************************************************************/
#include <ROOT/RWebDisplayArgs.hxx>
#include <ROOT/RWebWindow.hxx>
#include <ROOT/RConfig.hxx>
#include "TROOT.h"
......@@ -60,6 +61,24 @@ ROOT::Experimental::RWebDisplayArgs::RWebDisplayArgs(int width, int height, int
SetBrowserKind(browser);
}
///////////////////////////////////////////////////////////////////////////////////////////
/// Constructor - specify master window and channel (if reserved already)
ROOT::Experimental::RWebDisplayArgs::RWebDisplayArgs(std::shared_ptr<RWebWindow> master, int channel)
{
SetMasterWindow(master, channel);
}
///////////////////////////////////////////////////////////////////////////////////////////
/// Destructor
ROOT::Experimental::RWebDisplayArgs::~RWebDisplayArgs()
{
// must be defined here to correctly call RWebWindow destructor
}
///////////////////////////////////////////////////////////////////////////////////////////
/// Set browser kind as string argument
/// Recognized values:
......@@ -128,9 +147,19 @@ std::string ROOT::Experimental::RWebDisplayArgs::GetBrowserName() const
return "";
}
///////////////////////////////////////////////////////////////////////////////////////////
/// Assign window and channel id where other window will be embed
void ROOT::Experimental::RWebDisplayArgs::SetMasterWindow(std::shared_ptr<RWebWindow> master, int channel)
{
SetBrowserKind(kEmbedded);
fMaster = master;
fMasterChannel = channel;
}
///////////////////////////////////////////////////////////////////////////////////////////
/// Append string to url options
/// Add "&" as separator if any options already exsists
/// Add "&" as separator if any options already exists
void ROOT::Experimental::RWebDisplayArgs::AppendUrlOpt(const std::string &opt)
{
......
......@@ -177,7 +177,6 @@ unsigned ROOT::Experimental::RWebWindow::MakeBatch(bool create_new, const RWebDi
return connid;
}
//////////////////////////////////////////////////////////////////////////////////////////
/// Returns connection id of batch job
/// Connection to that job may not be initialized yet
......@@ -659,8 +658,10 @@ bool ROOT::Experimental::RWebWindow::ProcessWS(THttpCallArg &arg)
} else if (nchannel == 1) {
ProvideQueueEntry(conn->fConnId, kind_Data, std::move(cdata));
} else if (nchannel > 1) {
// add processing of extra channels later
// conn->fCallBack(conn->fConnId, cdata);
// process embed window
auto embed_window = conn->fEmbed[nchannel];
if (embed_window)
embed_window->ProvideQueueEntry(conn->fConnId, kind_Data, std::move(cdata));
}
CheckDataToSend();
......@@ -1041,6 +1042,9 @@ int ROOT::Experimental::RWebWindow::GetSendQueueLength(unsigned connid) const
void ROOT::Experimental::RWebWindow::SubmitData(unsigned connid, bool txt, std::string &&data, int chid)
{
if (fMaster)
return fMaster->SubmitData(fMasterConnId, txt, std::move(data), fMasterChannel);
auto arr = GetConnections(connid);
auto cnt = arr.size();
auto maxqlen = GetMaxQueueLength();
......@@ -1249,6 +1253,29 @@ void ROOT::Experimental::RWebWindow::Run(double tm)
}
}
/////////////////////////////////////////////////////////////////////////////////
/// Add embed window
unsigned ROOT::Experimental::RWebWindow::AddEmbedWindow(std::shared_ptr<RWebWindow> window, int channel)
{
if (channel < 2)
return 0;
auto arr = GetConnections(0, true);
if (arr.size() == 0)
return 0;
// check if channel already occupied
if (arr[0]->fEmbed.find(channel) != arr[0]->fEmbed.end())
return 0;
arr[0]->fEmbed[channel] = window;
return arr[0]->fConnId;
}
/////////////////////////////////////////////////////////////////////////////////
/// Create new RWebWindow
/// Using default RWebWindowsManager
......@@ -1268,3 +1295,34 @@ void ROOT::Experimental::RWebWindow::TerminateROOT()
fMgr->Terminate();
}
/////////////////////////////////////////////////////////////////////////////////
/// Static method to show web window
/// Has to be used instead of RWebWindow::Show() when window potentially can be embed into other windows
/// Soon RWebWindow::Show() method will be done protected
unsigned ROOT::Experimental::RWebWindow::ShowWindow(std::shared_ptr<RWebWindow> window, const RWebDisplayArgs &args)
{
if (!window)
return 0;
if (args.GetBrowserKind() == RWebDisplayArgs::kEmbedded) {
unsigned connid = args.fMaster ? args.fMaster->AddEmbedWindow(window, args.fMasterChannel) : 0;
if (connid > 0) {
window->fMaster = args.fMaster;
window->fMasterConnId = connid;
window->fMasterChannel = args.fMasterChannel;
// inform client that connection is established and window initialized
args.fMaster->SubmitData(connid, true, "EMBED_DONE"s, args.fMasterChannel);
// provide call back for window itself that connection is ready
window->ProvideQueueEntry(connid, kind_Connect, ""s);
}
return connid;
}
return window->Show(args);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment