[SOLVED] X error in 2623 when trying to set Qt win as parent

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Re: X error in 2623 when trying to set Qt window as parent

Postby romariorios » Thu Mar 10, 2016 7:09 pm

I just found out that, unlike QX11EmbedContainer, where you pass the Qt Window id to cefsimple and set it as its parent (with SetAsChild), in Qt 5, it's the other way around: the Qt application gets the window id and embeds it inside it:

Code: Select all
#include <QApplication>

#include <QDebug>

#include <QWidget>
#include <QWindow>

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  auto wId = 0x2400001;  // cefsimple window id
  auto subW = QWindow::fromWinId(wId);
  auto container = QWidget::createWindowContainer(subW);

  container->show();

  return a.exec();
}


Is there a way I can get the CefWindowHandle of the window from libcef? EDIT: CefWindowInfo has a window field, which is a cef_window_handle, but I don't know how to use it.
romariorios
Mentor
 
Posts: 50
Joined: Thu Apr 30, 2015 6:13 am
Location: Brazil

Re: X error in 2623 when trying to set Qt window as parent

Postby romariorios » Thu Mar 10, 2016 8:09 pm

romariorios wrote:Is there a way I can get the CefWindowHandle of the window from libcef? EDIT: CefWindowInfo has a window field, which is a cef_window_handle, but I don't know how to use it.

CefBrowserHost::GetWindowHandle() does exactly that.

So, problem solved, it seems. I just need to stop using SetAsChild, get cefsimple's window handle and pass it to the Qt application. I'll edit this post to report any progress.

Thanks Czarek and magreenblatt :D

(And sorry about jumping into assumptions earlier :oops: )
romariorios
Mentor
 
Posts: 50
Joined: Thu Apr 30, 2015 6:13 am
Location: Brazil

Re: X error in 2623 when trying to set Qt window as parent

Postby Czarek » Fri Mar 11, 2016 12:52 am

I'm glad you worked it out.

What you did now is basically QX11EmbedWidget from Qt4. It embeds external control by providing its window handle. QX11EmbedContainer from Qt4 works the reverse way, you provide Qt's window handle to the external process that embeds the control. It should still be possible to do the embed container thing in Qt5, however I think this is out of the scope for this forum to debug this further.

Regarding your embedding working in branch 2526 with QWidget - looks like this was luck. Qt library uses GTK library internally (on Linux), but it wraps it with its own magic. You don't know what it does inside, you can't expect the same behavior as from CEF GTK examples.
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

Re: X error in 2623 when trying to set Qt window as parent

Postby romariorios » Fri Mar 11, 2016 9:30 pm

Well, here's how things are going for me so far: I managed to embed cefsimple's window inside my Qt application, but I hit QTBUG-40320 -- specifically, Part 2, "Quirks with initial geometry". I managed to come up with a workaround:

Code: Select all
  QTimer::singleShot(1, [this]()
  {
    auto mainWindow = qobject_cast<QWidget *>(parent());
    auto size = mainWindow->size();
    mainWindow->resize(size + QSize(1, 1));
    mainWindow->resize(size - QSize(1, 1));
  });

Rather ugly, but it does the job.

My other problem, though, is that I have to create a cefsimple window, then embed it into my Qt Window, making the window briefly flash before it's embedded. This is a kinda serious regression from before, since, by setting the id with SetAsChild, the cefsimple window is created inside its parent right away. Here's my step-to-step:

  1. Create the window with CefBrowserHost::CreateBrowser (or CreateBrowserSync)
  2. Get the window handle at CefLifeSpanHandler::OnAfterCreated (or from the CefBrowser returned by CreateBrowserSync)
  3. Send the window handle to the qt application
  4. Get the window using QWindow::fromWinId and embed it using QWidget::createWindowContainer
  5. Do the aforementioned workaround
Any possible steps to put between the ones above to prevent the flashing window? It doesn't happen all the time, but it's kinda disruptive when it does.

Thanks again.

EDIT: A late update about this to anyone who might find this thread on Google. From the QTBUG mentioned above:

(Win) The embedded window stops receiving key press and mouse wheel events (although mouse click events are still fine).

So, yeah. You can find a way to work around the issues described in that bug on Linux, but this specific problem makes this embedding approach impractical on Windows -- and there's definitely NO way around this, from what I've talked to Qt devs. So, Windows users should stick to CefWindowInfo::SetAsChild(), which still works (even with CEF 2623).

Good luck!
romariorios
Mentor
 
Posts: 50
Joined: Thu Apr 30, 2015 6:13 am
Location: Brazil

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby romariorios » Sun May 22, 2016 9:38 am

The approach above was troublesome even in Linux, so I found a way to properly embed CEF inside a Qt window: embedding it inside an empty QWindow instead of a QWidget. There are some caveats, though:

  1. To add the CEF window into a QWidget layout, you will need to use QWidget::createWindowContainer()
  2. An empty QWindow doesn't render anything -- not even a background. So, you might need to use a QBackingStore to make it render something when CEF isn't embedded -- see the Raster Window example for some reference.
  3. You might need to use the winId from before you add the QWindow into your widget's layout.

That's it. Problem truly solved now.
romariorios
Mentor
 
Posts: 50
Joined: Thu Apr 30, 2015 6:13 am
Location: Brazil

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby magreenblatt » Sun May 22, 2016 4:46 pm

romariorios wrote:The approach above was troublesome even in Linux, so I found a way to properly embed CEF inside a Qt window: embedding it inside an empty QWindow instead of a QWidget. There are some caveats, though:

  1. To add the CEF window into a QWidget layout, you will need to use QWidget::createWindowContainer()
  2. An empty QWindow doesn't render anything -- not even a background. So, you might need to use a QBackingStore to make it render something when CEF isn't embedded -- see the Raster Window example for some reference.
  3. You might need to use the winId from before you add the QWindow into your widget's layout.

That's it. Problem truly solved now.

Can you share your code? It would be cool to have a working example of this approach.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby romariorios » Sun May 29, 2016 9:25 am

magreenblatt wrote:Can you share your code? It would be cool to have a working example of this approach.


Not exactly a working example, but it shows at least how to successfully embed the CEF window into a QWidget:

Code: Select all
// main.cpp
#include <QApplication>

#include <QDebug>

#include <QDockWidget>
#include <QMainWindow>
#include <QWidget>
#include <QWindow>

using namespace std;

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  auto dw = new QDockWidget;
  dw->resize(200, 200);

  QMainWindow mw;
  mw.addDockWidget(Qt::TopDockWidgetArea, dw);

  QWindow win;

  mw.show();
  mw.resize(800, 600);

  mw.setCentralWidget(QWidget::createWindowContainer(&win));

  qDebug() << win.winId();

  return a.exec();
}

This program will print the window identifier in the console; to use it, set it as an argument of CefWindowInfo::SetAsChild() when creating a new browser -- for example:

Code: Select all
void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  // Information used when creating the native window.
  CefWindowInfo window_info;

#if defined(OS_WIN)
  // On Windows we need to specify certain flags that will be passed to
  // CreateWindowEx().
  window_info.SetAsPopup(NULL, "cefsimple");
#endif
  window_info.SetAsChild(10485772, CefRect(0, 0, 800, 600));  // 10485772 is the identifier of the QWindow of the previous app

  // ...

  // Create the first browser window.
  CefBrowserHost::CreateBrowserSync(
        window_info, handler.get(), url,
        browser_settings, NULL);
}


In this example, I create the CEF browser outside of the process of the Qt application, but the same approach would work for an in-process call.
romariorios
Mentor
 
Posts: 50
Joined: Thu Apr 30, 2015 6:13 am
Location: Brazil

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby Czarek » Thu Apr 20, 2017 8:45 am

magreenblatt wrote:
romariorios wrote:The approach above was troublesome even in Linux, so I found a way to properly embed CEF inside a Qt window: embedding it inside an empty QWindow instead of a QWidget. There are some caveats, though:

  1. To add the CEF window into a QWidget layout, you will need to use QWidget::createWindowContainer()
  2. An empty QWindow doesn't render anything -- not even a background. So, you might need to use a QBackingStore to make it render something when CEF isn't embedded -- see the Raster Window example for some reference.
  3. You might need to use the winId from before you add the QWindow into your widget's layout.

That's it. Problem truly solved now.

Can you share your code? It would be cool to have a working example of this approach.


I have successfully embedded CEF with Qt5 (PyQt5). Python code is available, link below. Here are the steps required for embedding CEF browser in Qt 5 on Linux:

1. Setup CefWidget as usual inside layout
2. Create a hidden window with QWindow() and pass its window handle to CEF when creating browser
3. After browser is embedded in the hidden window, create container with a call to QWidget.createWindowContainer(window=hidden_window, parent=cef_widget)
4. Replace cef_widget in the layout with the container

Complete code in the qt.py example: https://github.com/cztomczak/cefpython/ ... ples/qt.py
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby cretz » Fri Jun 30, 2017 1:14 pm

I am trying to do this same thing in C++ and running into the following error:

Code: Select all
[0630/190201.810126:FATAL:window_x11.cc(48)] Check failed: 1U == nchildren (1 vs. 0)


Here is the snippet of code:

Code: Select all
QPointer<QWidget> CefWidget::EmbedBrowser(QMainWindow *main_win,
                                          QLineEdit *url_line_edit) {
  CefWindowInfo win_info;
  auto win = new QWindow;
  win_info.SetAsChild((CefWindowHandle) win->winId(),
                      CefRect(0, 0, width(), height()));
  CefBrowserSettings settings;
  CefRefPtr<CefHandler> handler(new CefHandler(main_win,
                                               url_line_edit,
                                               this));
  browser_ = CefBrowserHost::CreateBrowserSync(win_info,
                                               handler,
                                               CefString("http://example.com"),
                                               settings,
                                               nullptr);
  return QWidget::createWindowContainer(win, main_win);
}


(the full code is here). It breaks on CreateBrowserSync. Because my window doesn't have a child? Is there something I am obviously doing wrong w/ my Qt window creation or what I'm passing to any CEF functions?
cretz
Techie
 
Posts: 34
Joined: Mon Jun 26, 2017 11:41 am

Re: [SOLVED] X error in 2623 when trying to set Qt win as pa

Postby Czarek » Fri Jun 30, 2017 2:03 pm

Try calling self.show() and/or main_win.show() before embedding.
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

PreviousNext

Return to Support Forum

Who is online

Users browsing this forum: Majestic-12 [Bot] and 96 guests