QDrag destroyed while dragging - c++

I have a Windows/Linux Qt 4.3 application that uses drag and drop in a QTreeView. I have two very similar applications which use the same set of Qt libraries. Drag and drop works in both on Linux but in only in one on Windows.
In the application that does not work the QDrag object gets deleted as soon as the mouse is moved. It is deleted by a DeferredDelete event from the event queue which is still processed in Qt during a drag. I do not know how to see what is causing the QDrag object to get deleted prematurely.
I can not figure out a good way to debug this problem. I have compared the source and cannot find anything obvious. I have tried using the code from one of the applications in the other application.
Any suggestions?
Update:
The reason the QDrag operation failed is because COM was not initialized successfully so the call to DoDragDrop in QDrag::exec returned immediately. QApplication tried to initialize COM by calling OleInitialize in qt_init but it failed with the error "Cannot change thread mode after it is set".
The interesting thing is that this happens even when OleInitialize is the first thing done in main so the thread mode is getting set initially by some external dependency. One of the differences between the applications that work on Windows is that the one that fails also contains .NET code so maybe that is the problem.
Solved:
This problem is a COM/CLR interop issue. The CLR sets the apartment state to MTA when it initializes and then when Qt attempts to initialize COM it fails. This problem and an old solution are discussed by Adam Nathan in Gotcha with STAThreadAttribute and Managed C++. In Visual Studio 2005 you can set the /CLRTHREADATTRIBUTE:STA compiler option in Configuration Properties > Linker > Advanced to set the threading attribute to STA without needing to create a new entry point.

I have no idea what can cause this, but I would try to find out by subclassing QDrag, overwrite deleteLater() (well, reimplement it, but as it's a slot, it will get called anyway), use this instead of a QDrag and put a breakpoint in deleteLater().

Related

Propper way to deinitialize GTK

I'm writing a c++ application that creates a GTK3 window at some point, while also running X11 code in other places.
For the pure X11 part i'm using XOpenDisplay() to open a display.
Running the X11 part and opening a GTK window afterwards works fine. Also running the X11 part multiple times is no problem as i release the display there using XCloseDisplay.
The problem i'm facing occurs when i try to run the X11 code after gtk has been initialized (to be more specific, calling XOpenDisplay() after the gtk initialization).
I'm suspecting that after running gtk_init() the display is never being released, even after gtk_main_quit().
I didn't find anything about deinitialization in the gtk3 documentation. Is there any way to propperly deinitialize gtk or free the display in another way?
The solution was completely unrelated. I was setting the DISPLAY environment variable twice by accident. Apparently gtk can handle this but XOpenDisplay crashes.
I have added a test to only set it once, now everything works. Perhaps gtk does propperly deinitialize after gtk_main_quit()

CRichEditCtrl from resource loads 1.0 instead of 2.0

I'm trying to update my application to use RichEdit 2.0; it's been using 1.0 since forever. Per the Microsoft documentation, I've changed AfxInitRichEdit() to AfxInitRichEdit2(), and I changed the class in the resource file from RICHEDIT to RichEdit20A (which is correct for this application). There is only one richedit in the resource file.
The application fails when I try to do anything with the window that includes this richedit. The dialog creation fails somewhere inside of ::CreateDialogIndirect(), and although I put breakpoints in CRichEditCtrl::Create and also on the class I derive from it, those breakpoints do not trip.
Out of frustration I tried calling AfxInitRichEdit() again and also calling AfxInitRichEdit2(). The application works! The breakpoints I put in do trip--but only on controls I create dynamically, not the one from the resource file. And when I run Active Window Spy, I see that the richedit created from the resource file somehow has a class of RICHEDIT even though I explicitly said RichEdit20A, and yet the dynamic ones are RichEdit20A as intended.
_RICHEDIT_VER is 0x210, and I'm using Visual Studio 2013.
I just can't figure out why CreateDialogIndirect() is making a RICHEDIT control--or trying to make one and failing, if I don't call AfxInitRichEdit()--instead of a RichEdit20A in spite of explicit instructions to the contrary. Any ideas?
Well, I feel stupid. There's a script that runs as part of the build process to update some resources, and for some reason that script has sometimes gotten confused between the debug and release versions, and copied resources from the release build into the debug build. I don't know why that happens and it's an issue for another day, but the upshot is the .rc file I had changed was getting replaced with another one.
Building the release version with the changes, and then building the debug version again, solved the problem.

How to obtain and interact with QWidgets from QProcess

I have Application A which is a third party Windows application (with GUI) that uses the Qt library.
I want to write Application B which will be responsible for starting Application A. I want Application B to also find buttons on Application B (QWidgets) and send them mouse inputs (click, double click etc).
I can run Application A through using the start function on a QProcess.
How do I do the following from my instance of the QProcess:
Get the top level window(s) for the process
Get a widget by name or (other identifiable attribute)
Get the widgets caption, colour and coordinates (and maybe some other data)
Send mouse move and click events to specific coordinates
Give a widget keyboard focus
Send keyboard key presses
Note - I know how to do this with the Windows API, but asking for a way via Qt. The specific Application A in question does not use the native windowing system, therefore window handles will not show up in Spy++ or Windows API functions.
Update 1 - Cannot seem to get any meaningful objects through the process's children
My attempt at getting child widgets for the process:
QProcess* process = new QProcess();
QString program = "\"C:\\Program Files (x86)\\foo\\bar.exe\"";
process->start(program);
auto widgets = process->findChildren<QWidget*>("", Qt::FindChildrenRecursively);
auto i = widgets.count();
// i = 0
If I find children of type <QObject*> I get 4 results. I used metaObject()->className() to see that I have two pairs of QWindowsPipeReader and QWinOverlappedIoNotifier objects.
Update 2 - Cannot create/inject window from another process
I noticed that when I run the QProcess I can use Windows API functions to get the top level window (top level only). I read in the Qt documentation that you can create a QWindow from the handle of a window in another process using QWindow::fromWinId.
Using this function will throw an 0xC0000005: Access violation reading location 0x00000000. error. I am not passing in a null handle. I am using reinterpret_cast to get the HWND to a WId type. It creates a QWindow only when I create a QApplication beforehand.
The new QWindow will have no children (using window->findChildren<QObject*>("", Qt::FindChildrenRecursively); I assume that the creation of the QWindow does not bring across associated child widgets.
Update 3 - I am currently reading into whether inter-process communication can be used
I have come across various threads, questions and code snippets regarding ICP in Qt. I don't see anything so far that specifically shows that ICP is possible when one of the processes is third party.
I have seen that the Squish Gui test tool lets you interrogate QWidget properties.
This will never work the way you intend it to.
If you really wish to take direct control over the other application, you must inject your code into that application. Let's assume that the application uses a dynamically linked Qt. Then:
Build a binary-compatible version of Qt, using the same compiler that was used to build the application you intend to tweak.
Replace the application's Qt with yours. Everything should still work fine, given that yours should be binary compatible. If not, the binary compatibility isn't there, and you must tweak things until they work.
Edit your Qt to add a hook to initialize your code at the end of QApplication constructor. This makes the Qt module that provides QApplication dependent on your code.
Put your code into a dll that the widgets (for Qt 5) or gui (for Qt 4) module is now dependent on.
Again replace the app's Qt with yours, with hooks that start your code.
Your code will of course need to be asynchronous, and will be monitoring the application's progress by inspecting the qApp->activeWindow(), qApp->allWidgets(), etc.
That's pretty much the only way to do it. You can of course inject your code in any other way you desire, but you will need to work with a binary-compatible version of Qt just to compile your code. Note that binary compatibility encompasses more than merely using the same compiler version and Qt version. Many of the configure switches must be the same, too.

How can I integrate new Qt windows with an existing X application?

I have an existing (large) X application based on raw XLib. I would like to add additional windows to this application using Qt 4. What is the best way to do this?
Research so far:
(If it matters for the details, I'm looking at Qt 4.7.4 right now.)
My existing application calls XtAppNextEvent in a loop to handle its events. What I am hoping to do is replace this event loop with a Qt-based event loop, let Qt handle its own events, and make calls to XtDispatchEvent for non-Qt events.
I have located the part of Qt that processes X events (in src/gui/kernel/qapplication_x11.cpp, QApplication::x11ProcessEvent). I believe the key part of this function is:
QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
which determines whether the event refers to a window that Qt knows about. For non-Qt windows, this returns NULL. There are a couple of processing exceptions after this, then a block like:
if (!widget) { // don't know this windows
QWidget *popup = QApplication::activePopupWidget();
if (popup) {
// ... bunch of stuff not involving widget ...
}
return -1;
}
What I was hoping was there would be an event callback at this point that was called for non-Qt related window events, so I could simply implement a virtual function in my derived QApplication and proceed with the application's existing event processing. I can add such a function and rebuild Qt, but I would rather avoid that if possible.
Am I on the right track with this, or might there be a better way?
I have found existing questions similar to this, but they're all for Windows (MFC or .NET). This is specific to X.
The solution I ended up with was to find a copy of the Qt Motif Extension (it's no longer available from Digia directly as it is now unsupported, but you can still find copies of qtmotifextension-2.7-opensource.zip). In there, the qtmotif.h and qtmotif.cpp modules show how to create a QAbstractEventDispatcher that handles X events for both Xt/Motif and Qt components.

Windows RT Component, Getting the app's core window

I just have a simple question, with a Windows Runtime Component (as in a library) that I am making how do I get the window object for the app? CoreWindow::GetForCurrentThread() throws an exception as it seems that the library runs in a different thread then the app. Any one know how to get the app window?
EDIT: GetForCurrentThread is not the problem, it seems that that it only works on the UI thread not a background thread, I would like a way to get at it from a background thread. Is it possible?
I think Window.Current is what you are looking for.