Setting VLC drawable-hwnd still create a new window - c++

Here I read:
Embedded window video
--drawable-hwnd=<integer [-2147483648 .. 2147483647]>
Window handle (HWND)
Video will be embedded in this pre-existing window. If zero, a new window will be created.
I get the window handle of my Qt5 QML application in this way:
QObject* m_rootObject = engine.rootObjects().first();
if(m_rootObject) {
QWindow *window = qobject_cast<QWindow *>(m_rootObject);
if(window) {
WId wid = window->winId();
qDebug() << wid;
}
}
and then I launch vlc:
vlc --drawable-hwnd=395302 udp://#:1235
but it still creates a new window. I'm working on Windows 7.
Perhaps I'm not understanding what the documentation says?

I had the same problem with an RTSP stream.
Setting
--drawable-hwnd=windowhandle
seems not to be sufficient.
It only worked after I also set
--no-embedded-video
My complete command line looks like
--no-embedded-video --qt-notification=0 --qt-auto-raise=0 --qt-start-minimized --no-qt-name-in-title --no-video-title-show rtsp://127.0.0.1:8554/

Related

how do I call primary window using pushbutton c++

I'm trying to create a C++ Widget Application in QT with multiple windows where you can return to the mainwindow by clicking a Pushbutton.
I'm a complete noobie so I try to follow YouTube tutorial and for opening windows by pushbuttons I watched this one (minute 8:00): https://youtu.be/tP70B-pdTH0
It works when opening secondary windows from the main one but if I try to do the same from a secondary windows to the mainwindow it doesn't. It appears an error "cannot initialize object parameter of type 'Widget' with an expression of type 'MainWindow'"
in the source file I wrote:
void Crediti::on_pushButton_clicked()
{
close();
mainwindow = new MainWindow(this);
mainwindow->show();
}
mainwindow->show(); is the incriminated part
I also included mainwindow in the header of the secondary window and specified the class
MainWindow *mainwindow
in the header so It recognizes mainwindow initially in the source.
I'm doubting if doing this thing is possible at all, and if not so how can I make a pushbutton that, when clicked, can redirect me to the mainwindow?
Please I need this for a school application, thanks
So here you're creating a new main window each time you click on the button. From your description that's not the behaviour you want. I understand you have an application with a main window and other secondary windows and want to bring up the main window when clicking on the button, assuming the main window still exists somewhere and hasn't been deleted.
What I would try is to find the main window when hitting the push button and show / raise it, something along the line of:
#include <QApplication>
#include "MainWindow.h" // Adapt that one to you main window header
// ... some code of your secondary window
void SecondaryWindow::on_pushButton_clicked()
{
for(auto widget : QApplication::topLevelWidgets())
{
// This will return a nullptr if the widget is not the main window
auto mainWindow = dynamic_cast<MainWindow*>(widget);
// skip if not the main window
if(!mainWindow)
continue;
// Show it if hidden
if(mainWindow->isHidden())
mainWindow->show();
// raise it, as in bring it forward, over all other windows
mainWindow->raise();
}
// eventually close the current window if that's what you want
close();
// if you close it and don't need it any more you might also want to delete it
deleteLater();
}
Note that this function won't do anything if the main window has been deleted in the meantime, which might be the case if you closed it and the Qt::WA_DeleteOnClose attribute is set.
Hope that helps.

C++ Set window below (or above) the icons on the desktop

I'm trying to place a window either above or below the icons on the desktop. I mostly just want it to stay attached to the desktop at all times. Similar to Rainmeter or Wallpaper engine. So far, everything I tried either disables interaction, or gets minimized when you use the "Show Desktop" button. Any ideas on how to achieve this? I'm using electron and a native module in node to do this.
It's an old subject, but I'll find out how to do it recently and answer it.
The method is to find the handle of SHELLDLL_DefView, the parent of the desktop window, and then make the SHELLDLL_DefView handle the parent of my window to fix it to the desktop.
The method is to find the handle of SHELLDLL_DefView, the owner of the desktop window, and then make the SHELLDLL_DefView handle the owner of my window to fix it to the desktop.
SHELLDLL_DefView is located under the Progma or WorkerW handle. This is a code to prevent ShowDesktop from being used in the Electget package created by ffi-napi to attach the Electron browserWindow to the desktop.
const GWLP_HWNDPARENT = -8;
// find SHELLDLL_DefView in Progma
const progman = user32.FindWindowExA(ref.NULL, ref.NULL, 'Progman', ref.NULL);
let defView = user32.FindWindowExA(progman, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
// find SHELLDLL_DefView in WorkerW
if (!defView) {
const desktopHWnd = user32.GetDesktopWindow();
let workerW = 0;
do {
workerW = user32.FindWindowExA(desktopHWnd, workerW, 'WorkerW', ref.NULL);
defView = user32.FindWindowExA(workerW, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
} while (!defView && workerW);
}
if (!defView) return false;
// make the SHELLDLL_DefView handle the parent of my window
user32.SetWindowLongPtrA(hWnd, GWLP_HWNDPARENT, defView);
This allows you to create a window where you can click and interact without being hidden by ShowDesktop.
2022-03-29
There was a wrong word, so I corrected it. According to doc, it is not a parent window, but an owner window. In the doc, it is strange that the GWLP_HWNDPARENT constant is related to the parent window. However, when tested with Spy++, the corresponding constant changes the owner window.

Using CEF3 with wxWidgets (and GTK) on Linux

I started with this branch of wxWidgets from GitHub user hokein since it seems to do what I'm looking for with older versions of CEF. Basically, I'm trying to implement wxWebViewChromium (a wxWebView using CEF as a back-end) using cef_3.2526.1354 since this is the version we want to use in our application. I'm running CentOS 7 with GNOME in a VM using Hyper-V.
Original code from the repository linked above (part of webview_chromium.cpp)
#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
view_port );
info.SetAsChild( view_port );
m_parent->DoAddChild( this );
PostCreation( size );
gtk_widget_show( view_port );
#endif
When I tried to compile and link this with cef_3.2526.1354, I was getting errors related to the info.SetAsChild(viewport); line. I was passing it a GtkWidget* and it was expecting cef_window_handle_t, CefRect.
What I've tried so far
I created the CefRect like this based on the GtkWidget* view_port:
GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
(int)gtk_alloc.x,
(int)gtk_alloc.y,
(int)gtk_alloc.width,
(int)gtk_alloc.height
);
The typedef from the CEF library code indicates that cef_window_handle_t is an unsigned long, but the CEF documentation says it's a GtkWidget*... Which I guess are the same thing, but this led to some initial confusion. At first I thought that I needed to pass the X11 window id (XID) from the underlying X11 window, but this produced a runtime error:
Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window
Simply casting the GtkWidget* as an unsigned long instead of using the underlying X11 window ID removed this error, so I think that this is what the function was expecting.
My code currently (part of webview_chromium.cpp)
#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
view_port );
GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
(int)gtk_alloc.x,
(int)gtk_alloc.y,
(int)gtk_alloc.width,
(int)gtk_alloc.height
);
info.SetAsChild(
(unsigned long) view_port,
cef_rect
);
m_parent->DoAddChild( this );
PostCreation( size );
// gtk_widget_show(view_port);
gtk_widget_show_all(m_widget);
gtk_widget_show_all(view_port);
#endif
What's happening
I am able to compile, link, and run the application. I can see the wxWidgets window, and I can minimize, maximize, resize, and close the window just like any normal window. There is nothing in the window - it is just a plain, grey, empty window. I am expecting (or hoping) to see the CEF browser. In the terminal that I used to launch the application, I get the following message:
[0727/132200:ERROR:browser_main_loop.cc(203)] Running without SUID sandbox! See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for more information on developing with sandbox on.
This URL no longer seems to be of any use. If I launch ./cefclient --no-sandbox from the command line I get the same error message, but the CEF client works as expected. If I launch ./cefclient from the command line (without disabling sandbox), I get this same message except instead of ERROR it says FATAL and the CEF client does not work (crashes outright).
My questions
Have I done anything wrong with my modifications to the webview_chromium.cpp file? Is there anywhere else in this file that I should look for things that I might need to update to get this working with cef_3.2526.1354? How can I troubleshoot this empty window that I'm seeing?
Thanks!
UPDATE
Czarek Tomczak informed me that this version of CEF is expecting an X11 window handle, so I have modified my code as follows.
#ifdef __WXGTK__
m_widget = gtk_scrolled_window_new( NULL, NULL );
g_object_ref( m_widget );
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW( m_widget );
// Hide the scroll bar.
gtk_scrolled_window_set_policy( scrolled_window, GTK_POLICY_NEVER, GTK_POLICY_NEVER);
GtkWidget* view_port = gtk_viewport_new( NULL, NULL );
gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
view_port );
gtk_widget_show_all(m_widget);
gtk_widget_show_all(view_port);
GtkAllocation gtk_alloc;
gtk_widget_get_allocation(view_port, &gtk_alloc);
CefRect cef_rect (
(int)gtk_alloc.x,
(int)gtk_alloc.y,
(int)gtk_alloc.width,
(int)gtk_alloc.height
);
info.SetAsChild(
gdk_x11_drawable_get_xid(gtk_widget_get_window(view_port)),
cef_rect
);
m_parent->DoAddChild( this );
PostCreation( size );
#endif
But this is still leading to the run-time error below, with the same blank window output as before.
Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window
Any help pointing me in the right direction would be much appreciated. I have also tried creating an actual GtkWindow here instead of a scrolled window with a viewport inside it. This gets rid of the above run-time error, but it opens a second window, both of which are blank. I need all of this to work within one window.
UPDATE 2
With some help from Czarek Tomczak, the links he posted, and this FAQ I have gotten to a point where I am able to embed the CEF browser into a GtkWidget, but I am only able to make this work if I create the widget as a top-level GTK window like this:
m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
Where m_widget is the main widget of the wxWebView I'm trying to create. The issue with this is that now the CEF browser is coming up in its own GTK window, but what I really need is for the CEF browser to fit into the wxBoxSizer that I am adding my wxWebViewChromium widget to. To get this working to this point I split out some of the code from the Create method into the OnSize method so that I could get the XID of the GtkWidget after the GtkWidget was realized, and create the CEF browser after this happened. The OnSize method is connected to wxEVT_SIZE. My code is now as follows.
Updated portion of Create Method
// Actual creation of CEF browser moved to OnSize function so we
// can guarantee the widgets have been realized
this->Bind(wxEVT_SIZE, &wxWebViewChromium::OnSize, this);
// Works but as a top-level GTK window only
m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
// None of these work
//m_widget = gtk_drawing_area_new();
//m_widget = gtk_vbox_new(false, 0);
g_object_ref( m_widget );
Updated portion of OnSize Method
if (!cef_browser_created)
{
cef_browser_created = true;
CefBrowserSettings browsersettings;
CefWindowInfo info;
XSetErrorHandler(XErrorHandlerImpl);
XSetIOErrorHandler(XIOErrorHandlerImpl);
gtk_widget_realize(m_widget);
::Window xwindow = GTK_WINDOW_XID(gtk_widget_get_window(m_widget));
DCHECK(xwindow);
GtkAllocation gtk_alloc;
gtk_widget_get_allocation(m_widget, &gtk_alloc);
CefRect cef_rect (
(int)gtk_alloc.x,
(int)gtk_alloc.y,
(int)gtk_alloc.width,
(int)gtk_alloc.height
);
info.SetAsChild(xwindow, cef_rect);
m_parent->DoAddChild( this );
PostCreation( size );
CefBrowserHost::CreateBrowserSync(
info,
static_cast<CefRefPtr<CefClient> >(m_clientHandler),
create_url.ToStdString(),
browsersettings,
NULL
);
}
When I try to make m_widget something other than a top-level GTK widget (as shown in the commented-out portions of the code for the Create method above), I get the following error at run-time.
Gtk: IA__gtk_widget_realize: assertion 'GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
Gdk: gdkdrawable-x11.c:952 drawable is not a pixmap or window
Check failed: xwindow.
How can I make this window appear inside my wxBoxSizer instead of as its own GTK top-level window?
CEF expects X11 window handle. GtkWidget handle was required in previous versions of CEF. The documentation on that wiki page seems to be outdated. Make sure the X11 handle is valid (show the window) before passing it to CEF.
I can only suggest to take a look at how GTK window is created in cefclient sample application:
https://bitbucket.org/chromiumembedded/cef/src/98f59f47fd395c170f389eba36f2ef2e06a500a8/tests/cefclient/browser/root_window_gtk.cc?at=master&fileviewer=file-view-default#root_window_gtk.cc-233
Also take a look at CreateBrowser() - it uses GetXWindowForWidget():
https://bitbucket.org/chromiumembedded/cef/src/98f59f47fd395c170f389eba36f2ef2e06a500a8/tests/cefclient/browser/browser_window_std_gtk.cc?at=master&fileviewer=file-view-default#browser_window_std_gtk.cc-91

Qt Creator: AlwaysStaysOnTop blocks open file prompt

I have a push button on my main window that allows the user to select a file to open.
std::fstream infile;
std::string filename = QFileDialog::getOpenFileName(this, tr("TXT file"), qApp->applicationDirPath (),tr("TXT File (*.txt)")).toStdString();
if (filename.empty())
return;
infile.open(filename, std::fstream:: in | std::fstream::out | std::fstream::app);
if (true) {
//Does stuff with the data
}
infile.close();
This normally works fine, and I've used it in previous gui qt applications. However, for this application the mainwindow (upon its setup) sets its windowsflags as follows:
setWindowFlags(Qt::FramelessWindowHint| Qt::WindowStaysOnTopHint);
This creates a problem as the main window attempts to always stay on top (and thus prevents the open file window from appearing). Without the staysontop flag the file dialog works correctly.
Is there a way to temporarily disable this flag (so I can disable when the push button is clicked and then reenable when the file dialog is complete)?
setWindowFlags(Qt::FramelessWindowHint| ~Qt::WindowStaysOnTopHint);
This seems to be the most common suggested solution, but doesn't work for me. I believe this is because the window has to be recreated for the changes to the window flag to be registered -- however, I believe that if I killed the main window the file dialog would go out of scope too?
In summary, I am trying to find a work around to have the main window always on top except for when I am trying to select a file to open (the file dialog being triggered by a push button).
The problem was not the flags but rather a timer emitting signals which updated the window position:
QTimer* timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update_pos()));
timer->start(50);
Where the update_pos function is as follows:
void MainWindow::update_pos(){
RECT rect;
if (GetWindowRect(target_window, &rect)) {
SetWindowPos((HWND)this->winId(), HWND_TOPMOST, rect.left, rect.top, 0, 0, SWP_NOSIZE);
} else {
//maybe window was closed
qDebug() << "GetWindowRect failed";
QApplication::quit();
}
}
Whenever the update_pos function was called it would push the main window to the top (and thus above the open file dialog).

Writing a screensaver with Qt creator - showing a preview in Screen Saver Settings

At the beginning I want to apologise for my English. Now let's go to my problem.
I try to write a screen saver using Qt Creator (v5.0.1). Now I have a configuration window (running application with "/c" parameter), full screen window (running application with "/s" parameter), and I don't have a preview window (running application with "/p" and "1234567" parameters, where 1234567 is a handle and it can be any number. I have a problem with correct use this handle. There are few examples that I found, but all of them don't work. Here is an example:
Creating a Screen Saver for Windows. I was trying to copy this code and make it work on my machine, but there was a few problems. Some of them I solved, but one I can't. Here is a part of the code:
QApplication app(argc, argv);
QStringList arguments = app.arguments();
/* parse the commandline:
* "[-/][Cc]" or no arguments for configuration mode
* "[-/][Ss]", for fullscreen mode
* "[-/][Pp][ :][0-9]+" for preview mode
*/
Mode mode = ConfigurationMode;
WId parent = 0;
bool OK = arguments.size()<=1;
for(int i=1;i<arguments.size();i++)
{
if(arguments[i].size()<2)
break;
switch(arguments[i][1].toLatin1())
{
case 'c': case 'C':
mode = ConfigurationMode;
OK = true;
break;
case 's': case 'S':
mode = FullScreenMode;
OK = true;
break;
case 'p': case 'P':
if(arguments[i].size()>=4 && arguments[i][2]==':')
parent = (WId)arguments[i].mid(3).toUInt(&OK);
else if(arguments.size()>i)
parent = (WId)arguments[i+1].toUInt(&OK);
mode = PreviewMode;
break;
}
}
And next is the second part of the code:
ScreenSaverWidget* widget = new ScreenSaverWidget;
widget->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(widget, SIGNAL(destroyed()), &app, SLOT(quit()));
switch(mode)
{
case ConfigurationMode:
{
QSettings settings("QT", "Screen Saver");
int animationSpeed = settings.value("animationSpeed", 10).toInt();
//animationSpeed = QInputDialog::getInteger(0, "Configure Screen Saver", "Set Animation speed (0-100%)", animationSpeed, 0, 100);
animationSpeed = QInputDialog::getInt(0, "configure Screen Saver", "Set Animation speed (0-100%)",animationSpeed, 0, 100);
settings.setValue("animationSpeed", animationSpeed);
}
return 0;
case FullScreenMode:
new ScreenSaverEventFilter(widget);
widget->showFullScreen();
break;
case PreviewMode:
{
widget->setWindowFlags(Qt::FramelessWindowHint|Qt::SubWindow);
::SetParent(widget->winId(), parent);// <---
RECT parentRect;
::GetClientRect(parent, &parentRect);// <---
widget->move(0,0);
widget->resize(parentRect.right, parentRect.bottom);
widget->show();
}
}
return app.exec();
I have three errors:
invalid conversion from 'WId {aka unsigned int}' to 'HWND' [-fpermissive]
in two lines which are marked in second part of the code.
Is there anyone who know how to make it work? Is there a possibility to do it with Qt? (handle is generating by window from window.h and I want to set it as a parent of Qt widget, is it possible?)
And one more think to do is to make my screensaver (in preview mode) to react to input events, for example close event (from Screen Saver Settings window), how to do it?
EDIT 2015.06.14 -------------------------
Ok, I solved the first problem, I added explicit conversion:
(...)
::SetParent((HWND)widget->winId(), (HWND)parent);// <---
RECT parentRect;
::GetClientRect((HWND)parent, &parentRect);// <---
(...)
but now the problem is that my application doesn't respond to any signals from Screen Saver Settings window, for example (and this is the most important) it doesn't close when it should - when I choose another screensaver, or when I close Screen Saver Settings window (I must kill the process with Task Manager). Is there anyone who know and can write here how to make my application picking up the closing signal from Screen Saver Settings window?
The legal call to set one widget as parent for another:
void QWidget::setParent(QWidget * parent)
Of course that is needed to ensure proper signal/slot processing for such nested widget, etc. I myself would rather not use setParent at all but create the QMainWindow parent widget with nested child widget that takes entire parent using setCentralWidget call and you then don't need to do many unnecessary things with size, etc. But I am unaware of all details in your program.
Sets the parent of the widget to parent, and resets the window flags. The widget is moved to position (0, 0) in its new parent.
...
Note: The widget becomes invisible as part of changing its parent, even if it was previously visible. You must call show() to make the widget visible again.
As for resize and window flags. Try and if resize is needed you can probably do widget->resize(parent->size()). As for the flags, first try without specifying them. There is some doubt if this combination applicable to the child widget inside parent.
In our Windows app port I frequently pass winId() for HWND and it works but mind that that may avoid necessary Qt framework actions and always try to find the proper Qt way first. As for compiler warning for that, you can use reinterpret_cast(widget->winId()) if so.