Global hotkeys in a cross-platform Qt application - c++

I'm creating a cross platform utility, in C++ using Qt, for which I need to have shortcut keys (or hotkeys, not really sure about the difference). Essentially the application will run and only be visible as an icon in the system tray, and do stuff when you press certain shortcut keys (eg, Ctrl-Shift-f4 or something).
I am under the impression that Qt doesn't provide a way to handle shortcut keys unless the application is in focus, which, in my case it won't be. So, that's out (if however that is a viable option, please clue me in).
I've found plenty of examples/documentation explaining how to do this using Xlib/Xcb for linux, win32 api for windows, and carbon for osx, but I'm having a hard time finding a way to do this that would be applicable within the scope of a Qt application.
What would be a way to accomplish what I need?

I'm digging up this old non-answered question because, using QML, I encountered the same issue. The Shortcut QML type allow you to specify a context property but you still need a focused application or window.
However, I found a library resolving this issue : QHotkey. Describing itself on Github as :
A global shortcut/hotkey for Desktop Qt-Applications.
The QHotkey is a class that can be used to create hotkeys/global shortcuts, aka shortcuts that work everywhere, independent of the application state. This means your application can be active, inactive, minimized or not visible at all and still receive the shortcuts.
QHockey is available as a package through qpm and can be used directly from C++.

Related

Detect dark application style/theme of currently used desktop in Qt

The bounty expires in 7 days. Answers to this question are eligible for a +50 reputation bounty.
codeling wants to draw more attention to this question:
Give concise information (and ideally code) on how to detect dark theme on KDE and Gnome desktop environments using Qt, or if there is no direct way with Qt, using plain C++ (or at least as little additional libraries as possible).
In our Qt-based C++ application, I'm trying to automatically switch application styles based on whether the user has configured dark or bright theme.
I have figured out the notification of when a change happens (see below, for other's reference).
My main problem is the reliable detection of whether currently a dark or bright theme is used on linux (for windows see below); on XFCE, the check for QPalette color roles as mentioned in this answer works, but this does not work on Gnome and KDE Plasma for me (tested under both Ubuntu 22.04 and Fedora 36, my app built against Qt versions 6.5beta2 and 6.4.2, respectively); there the colors still seem to be taken from what I've set as XFCE theme on the same machine (and when starting xfce4-appearance-settings and changing the theme there, my app picks up the change). I would however like to adapt to the current desktop's dark mode setting.
So, my question is: How do I reliably detect application dark mode of the currently used desktop on Qt? I'm not averse to implementing a little custom platform-specific code if nothing is available directly in Qt, but it would be great if it would work without using additional libraries.
A note I saw for QApplication::setPalette I thought might be relevant here, namely "Some styles do not use the palette for all drawing, for instance, if they make use of native theme engines.", what are these all about? I did not see a link to a documentation for this feature, and a quick search for the term "qt native theme engine" also didn't seem to yield any useful results.
Since on Linux, some events are reliably triggered whenever a system theme change happens (see below), I suppose Qt can detect the theme change, it just doesn't expose data about it publicly?
Getting notified of theme changes
On Linux: via listening for QEvent::StyleChange events of the application's QMainWindow; two caveats and one side note:
That event does, despite QWidget::changeEvent documentation explicitly mentioning it, not trigger a changeEvent (for me), but has to be caught via the more generic QWidget::event
StyleChange only seems to be triggered since some Qt 6.4 version (in my tests, it was not triggered by 5.15.2 and 6.3.1, but triggered for 6.4.2 and 6.5.0beta2).
I've also noticed that there's a ThemeChange event that is also triggered (at the same time as the StyleChange; not sure what the difference is between these two though, and in what case one would be triggered but not the other... I suppose StyleChange is used for any change to the style of a widget, so that it's also called when applying some style sheet settings, while ThemeChange really indicates a change of the system theme? Though ThemeChange seems to be considered a non-public Event type, at least it doesn't appear in the documentation (marked \omitvalue)
On Windows, via checking for changes to the registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize (the StyleChange unfortunately isn't triggered there at all - a Qt bug?). .
Detecting dark theme on Windows
Application bright/dark mode determined by registry key HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme (1 for bright, 0 for dark). This check is also done in Qt's plugins/platforms/windows/qwindowstheme (queryDarkMode`), but I think this is not exposed publicly as generic interface anywhere?

Embedd an external application in a widget under Qt

I was wondering either it is possible to run an external application inside a QT widget under windows operating system. For example, if I were to write a Qt gui application, where in one of the dialogs user could write some text, I could use a textbox there or something similar. But instead, would it be possible to run Notepad++ or windows notepad application in that dialog?
I would appreciate all help.
It is not really practical to do what you describe at the application level, embedding an entire process into a window of another. (It would be technically difficult and the user experience would likely be pretty bad if you could pull it off.)
Fortunately, this very problem of application components has already been solved!
So it is possible to get the end result you describe via a slightly different mechanism. Many applications expose COM interfaces for automation and embedding, and it is possible to embed COM objects within a Qt application.
(Older technologies such as DDE, OLE and ActiveX provided various aspects of this but are all basically deprecated in favour of COM AFAIK.)
Hopefully you can find a COM object from a third party, or find an app that exposes its components via COM and assemble your app that way.
Have a look at the Qt documentation:
Active Qt - ActiveX and COM support for Qt

Managing Windows Though QT Application in Linux (C++)

I've been making a simple application which is able to launch a variety of other applications through QT5 (using QProcess class) but I've been running into a few key issues with the design. Specifically, it seems that Qprocess cannot set focus to windows that have been created via QProcess' start() function. This means that once a user opens more than one window, it can never return to the previous window that has been opened. After looking further into this dilemma, it has become clear that my program will need to be able to handle basic window management in order to fulfill my specifications.
I've decided that the best example to study for my program is Docky, which is capable of opening, closing and switching windows. Looking at the source code for that project was helpful, but there were many C# system calls that were used for fetching the list of client-windows which aren't available for my C++ program.
How can I get a list of all the X11 Windows that the client is running and provide basic window management (Switch To/ Open / Close Window) using C++? Is there a cross platform way of doing this through QT? Can I get this information directly using XServer?

How to shell to another app and have it appear in a Borland VCL form (c++)

I'm actually in charge of a FIP networking c++ application, working for the first time with Embarcadero C++ Builder XE5.
The app is nearly finished, but I can't find how to implement the last feature...
I wanted to open an external Windows HyperTerminal in order to see what happen on a given COM port, for this purpose I'm using ShellExecute() to launch it from my application but it's a bit ugly since there is 2 different windows.
I was wondering if it was possible to integrate this newly opened HyperTerminal into an existing form (Panel for instance). I couldn't find nothing related excepted this =>
Delphi style, but i don't understand a byte of #mghie answer since it's delphi.
If anyone have a clue I'm really interested, even the most basic clue!
For almost all of my projects where COM port interaction is needed I use AsyncPro. The project is very well documented with a ~1000 page reference manual.
Reference Manual
Developer's Guide
For this case, the package provides a VCL terminal that simply drops onto a form. It's quite flexible with a lot of options to configure its behaviour.
I wanted something similar in past but with no success.
1.The only thing I was able to do is the exact opposite.
dock my VCL window inside another (not VCL app) but that solved my problems
If you terminal is console window then I doubt even this can be done.
anyway find handle of desired window
find handle to a dockable subcomponent
set the parent of your subwindow to it / or use manual dock
2.maybe you can do some funny stuff
like hide terminal somewhere
and continuoslly copy its graphics to your window
newer done that hide thing
but copy the contents is doable (although on windows a little unstable sometimes)
done it once to feed my App with IR-camera feed from different App
while 'focus' stays on hidden terminal it should work
also you can try to post messages to it somehow if you need the focus ...
Sorry for a vague answer but at least you see some approaches of mine
maybe someone has a better way to do this

ctrl+alt+del disable using c in window OS

How to disable ctrl+alt+del using C in Window OS? I tried
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, true, &bOldState, 0);
but it doesn't working for me. Can you kindly guide me, so that I can make it possible.
The SPI_SETSCREENSAVERRUNNING parameter you are using is designed for screensavers on Windows 95. It works on Windows 95/98/ME and earlier. It does not work on Windows NT/2000/XP/Vista.
The Ctrl-Alt-Del Hotkey combo can be disabled on Windows NT/2000/XP/Vista, but not usually from an application (user mode). Here are the mechanisms I'm familiar with.
I haven't tried it on Windows 7, but I'm sure some or all of these techniques still work there.
A GINA DLL can intercept the CAD sequence, but that may be overkill. It works because Windows registers the CAD Hotkey and sends a callback to GINA DLL to handle the action when you press it. A replacement GINA DLL can handle the callback differently (ignoring it), but it may be tricky to do this and remain compatible with other login mechanisms using other custom GINA DLLs.
You can write a keyboard driver to intercept it. There is pretty good free source code on the net for it if you search for it. Look for the Ctrl2Cap driver and similar things. (This driver remaps the Caps Lock key and Ctrl keys to mimic old keyboard layouts.)
You may also be able to "remap" keys in the registry to achieve your goal using the Scan Code Mapper. They added this in Windows 2000. It's limited, but workable in some situations. See this MSDN page for details. Pay attention to the limitations, though. For example, it requires a reboot for the change to take effect.
Finally, you can disable the Task Manager and other features through an administrative setting using the Windows Admin Toolkit. It still interrupts everything to show you a "You can't do that" dialog. But at least it works to limit users' access to the machine.
I wrote a device driver (option 2 on my list above) to block Ctrl-Alt-Del for Windows 95/98 (13 years ago), and later for Windows NT/2000/XP. I sold a lot of those. They're still around if you look.
Are you attempting to disable the requirement of ctrlaltdelete for login, or are you trying to disable the hotkey entirely? I don't believe the latter is even possible; it's a built-in OS-level override designed to circumvent any user-level program.
With Windows XP you can write a GINA DLL to do this. Windows 7 doesn't seem to have a GINA DLL anymore though. There may be some sort of policy setting to accomplish the same, but if so I haven't seen it documented.
Ctrl-Alt-Del is the Secure Attention Sequence. The goal is to let the user communicate securely with the OS. It can't be disabled by programs, by design - it would no longer be secure in that case.