set qt c++ mainwindow always on bottom mac osx - c++

So I am trying to set this window/ mainwindow / application in qt to always be on the bottom (like always bottom window) (so rainmeter somehow does this with their widgets), but I can't even get mac osx to do such things.
I've tried the whole
this->setWindowFlags(Qt::WindowStaysOnBottomHint);
but without any luck. Any hints? Example code is amazing.

Got bad news and good news. The bad news is it's simply not implemented.
The good news is: as Qt is open source, you can crack it open and take a look to know that. And if there's a bug you can submit a fix. Here's the deal, in the generic code for QWidget::setWindowFlags in
qwidget.cpp:9144 you have this:
void QWidget::setWindowFlags(Qt::WindowFlags flags)
{
if (data->window_flags == flags)
return;
Q_D(QWidget);
if ((data->window_flags | flags) & Qt::Window) {
// the old type was a window and/or the new type is a window
QPoint oldPos = pos();
bool visible = isVisible();
setParent(parentWidget(), flags);
// if both types are windows or neither of them are, we restore
// the old position
if (!((data->window_flags ^ flags) & Qt::Window)
&& (visible || testAttribute(Qt::WA_Moved))) {
move(oldPos);
}
// for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
d->adjustQuitOnCloseAttribute();
} else {
data->window_flags = flags;
}
}
So essentially it just sets window_flags. The mac behavior of QWidget is in qwidget_mac.mm.
And you will find no reference to Qt::WindowStaysOnBottomHint in that file. (You'll find Qt::WindowStaysOnTopHint though...)
I'll stop at saying "not possible unless you either patch Qt, or otherwise go beneath Qt".
Patching qwidget_mac.mm is left as an exercise to the reader. :-)

Related

Problem with Keypress simulation on Linux (Ubuntu 18)

I'm making a hobby project that is basically a bot for a very old flash game, the mouse move and click works fine, but all key presses make the operating system lag/stutter and sometimes stop listening to all keyboard inputs, real or fake.
I started using just XLib with XTests but didn't work, so I tried XSendEvent instead of XTests, but all symptoms stayed the same, so the last attempt was with XDO, which gave better results, but still freezes the OS.
this is the current snippet that I'm trying to use to simulate a keypress:
//Constructor
CheatCore::CheatCore() {
xdo_t x = xdo_new(NULL);
Window *list;
xdo_search_t search;
unsigned int nwindows;
memset(&search, 0, sizeof(xdo_search_t));
search.max_depth = -1;
search.require = xdo_search::SEARCH_ANY;
search.searchmask = SEARCH_CLASS | SEARCH_ONLYVISIBLE;
search.winclass = "Chrome";
int id = xdo_search_windows(x, &search, &list, &nwindows);
qDebug() << nwindows;
if(!nwindows){
qDebug() << "Chrome not found";
return;
}
w = list[0];
//I have to call activate twice to really bring it forward, I suspect that its
//because I use a transparent "overlay" that show stats for the cheat and it is set as Aways on top
//(i used Qt to set it to not get any Events)
xdo_activate_window(x,w);
xdo_activate_window(x,w);
}
//there is a function that executes every second to check if a pixel color has changed,
//if so, then the SendKey is called to Reload weapon magazine pressing the "space" key
void CheatCore::SendKey(){
xdo_activate_window(x,w);
xdo_activate_window(x,w);
xdo_send_keysequence_window(x, w, "space", 500);
}
I'm using a transparent overlay to show the bot status, with just some numbers appearing, it is a widget created using Qt that is AlwaysOnTop and the paint event draws the desired information's, it is another object and don't have direct impact in the CheatCore, but this is the window flags used to draw over a transparent window and ignore events.
setWindowFlags(Qt::WindowTransparentForInput | Qt::FramelessWindowHint |
Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
I didn't manage to understand what could be provoking this weird behavior, could it be the windowing system?
Also, I tried to find a Qt way of simulating mouse/keyboard inputs, but i didn't manage to find any solution to send events to other windows if there is a way possible of achieving this would be great!
The game i'm trying to automate is called "Storm the House"
If interested this is the link to the online repo : link
Can you help me make this work? Thank you!
Context about the setup:
Ubuntu 18.10 using VGA and Nvidia drivers (if it may influence the xserver)
Did you ever try to use xdotool from command line. To use xdotool you need to install package first.
To simualte a key press, you can use.
xdotool key <key>
For example if you want to simulate key press for X you can use this code
xdotool key x
Or any other combination like
xdotool key ctrl+f
Also you can replace key press with another one, for example if you want to replace pressing D with Backspace you can try this one
xdotool key D BackSpace
You can read complete guid online, also you can write script with this tool and use it in many different situations.
Also you can use it for remote connection too.
I hope this helps you with your little problem.
Using evdev is a linux specific option.
It's a simpler solution as you just need to open the correct file and write to it.
Take a look at this similar question to see how to get started.

NVDA screen reader requests wrong QAccessible::InterfaceType

I'm on Qt 5.9.1.
I'm trying to make an application accessible through screen readers. I have a custom widget (let's call it MyWidget) that contains text (a lot of it.) The text is drawn using QPainter, which is why a custom widget is used rather than something like QTextBrowser.
I implemented the QAccessibleTextInterface for the widget in a AccessibleMyWidget class that derives from QAccessibleWidget and QAccessibleTextInterface. It works fine with Orca under Linux, but when used in Windows 7 with NVDA, QAccessibleInterface::interface_cast() requests the wrong interface type. With Orca, I get requests for a QAccessible::TextInterface. In NVDA, it's always QAccessible::ValueInterface.
AccessibleMyWidget is defined as:
class AccessibleMyWidget:
public QAccessibleWidget, public QAccessibleTextInterface {
public:
explicit AccessibleMyWidget(QWidget* w)
: QAccessibleWidget(w, QAccessible::EditableText)
{
Q_ASSERT(isValid());
}
void* interface_cast(QAccessible::InterfaceType t) override
{
if (t == QAccessible::TextInterface) {
// !!! This is never requested with NVDA !!!
return static_cast<QAccessibleTextInterface*>(this);
}
return QAccessibleWidget::interface_cast(t);
}
/*
* QAccessibleTextInterface implementation below this point.
*/
void addSelection(int startOffset, int endOffset) override;
QString attributes(int offset, int* startOffset,
int* endOffset) const override;
// etc.
};
With Orca under Linux, everything seems to work as intended. I get calls to interface_cast() for a TextInterface, and after that, the various functions of QAccessibleTextInterface are called. With NVDA under Linux, I just get interface_cast() calls for ValueInterface, and none of the QAccessibleTextInterface functions are called. Which means MyWidget is completely inaccessible, unless I override QAccessibleWidget::text() and just return all text as a single string, which means no cursor navigation, no selection support... It basically becomes just a QLabel at this point, but with a ton of text and thus very hard to use.
What am I missing here?
Well, an NVDA developer helped me track down the issue. It's because the MinGW version of Qt has IAccessible2 disabled and uses MSAA (Microsoft Active Accessibility) instead, which doesn't support any of these interfaces. IA2 needs COM, and MinGW doesn't support that.
So I would have to switch from GCC/MinGW to MSVC to make this work on Windows. Too bad that's not actually an option in the foreseeable future :-/
2020 update:
This has been fixed since. Not sure when exactly, but the current mingw Qt builds now support this.

C++ Global Hotkeys with platform APIs

I'm working on an application for taking screenshots on Windows, OSX and Linux in C++/Qt. Now I need to set global hotkeys, so the user can take screenshots when the application is running in the background. I tried with Qxt and UGlobalHotkey, which are both Qt libraries, but neither of them seemed to work.
I tried to implement it for OSX with Carbon (tutorial), but I need to call a class member function, which just doesn't work. Could someone provide me with an example? You can find my code here. The function i need to call is new_screenshot().
Or is there any other way to achieve something like this? I really need my application to take a screenshot from the background, otherwise it's pretty useless (yes, I should probably have implemented it at the very beginning to see if it even works). Would it maybe be better to have a separate client for every platform (Cocoa Swift for OSX, GTK for Linux, C# client for Windows)? I have often thought about this the past few days.
Do I understand correctly that you want to call new_screenshot from the hot key event handler? If so, InstallApplicationEventHandler lets you pass a pointer to user data in 4th argument. Pass a pointer to your MainWindow instance (based on code from the tutorial):
MainWindow *mainWindow = ... // get main window somehow
InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,mainWindow,NULL);
Then you can use it in the event handler.
OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
//Do something once the key is pressed
static_cast<MainWindow*>(userData)->new_screenshot();
return noErr;
}
I did something in the past with MFC and WIN32 API....so it only works on Windows...but pressing ALT+F10 was able to hide/show a window...
void CWinHideDlg::OnButtonActive()
{
CString tmp;
GetDlgItemText(IDC_BUTTON_ACTIVE,tmp);
if(0 == strcmp(tmp.GetBuffer(tmp.GetLength()),"Activate"))
{
m_myAtom=GlobalAddAtom("MY_GLOBAL_HOT_HIDE_KEY");
int err=RegisterHotKey(this->GetSafeHwnd(),m_myAtom,MOD_ALT,VK_F10);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Stop");
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(TRUE);
SetDlgItemText(IDC_STATIC_INFO,"Set the mouse over the window \nand press ALT + F10 to hide it...");
}
else
{
UnregisterHotKey(this->GetSafeHwnd(),m_myAtom);
GlobalDeleteAtom(m_myAtom);
CButton *pBtn = (CButton *)GetDlgItem(IDC_BUTTON_UNHIDE);
pBtn->EnableWindow(FALSE);
SetDlgItemText(IDC_BUTTON_ACTIVE,"Activate");
}
}
Basically this code activates/deactivates the hot key ALT+F10, once it activates you can hide/unhide a running window on the system by setting the mouse pointer over the window and press ALT+F10...
This is from the WindowProc function:
if(message == WM_HOTKEY)
{
CString tmp;
POINT pc;
GetCursorPos(&pc);
if(GetAsyncKeyState(VK_F10))
{
HWND hwnd=::WindowFromPoint(pc);
if(hwnd)
{
tmp.Format("%08Xh",hwnd);
m_HideWins.InsertString(m_HideWins.GetCount(),tmp);
::ShowWindow(hwnd,SW_HIDE);
}
}
}
You can use the code to register your own HOT Key and use it to take a screenshot...
Hope it helps...

Qt: Can't set drag mode

I've been stuck on this for a little while now, I'm trying to set the drag mode of my QGraphicsView to ScrollHandDrag so that I can build a panning feature on my application.
However whenever I try to set the drag mode Qt always complains that DragMode is an undeclared identifier.
I'm also aiming to build a crop functionality (I assume I'd be using rubber band dragging for that?), I'm just wondering why I can't set the drag mode on the View
void MainWindow::on_btnCrop_clicked()
{
cropping = true;
QApplication::setOverrideCursor(Qt::CrossCursor);
// Stuck with this...
ui->imageView->setDragMode(ScrollHandDrag);
}
^ I have tried multiple other workarounds but I've not yet found any solution, any suggestions would be greatly appreciated.
This is not QGraphicsView specific an issue, but generic C++. Your problem is located at this line:
ui->imageView->setDragMode(ScrollHandDrag);
The problem is that you assume that you have visibility to the ScrollHandDrag value, whereas it appears inside the QGraphicsView scope. Therefore, since you are trying to access that value in your MainWindow, you will need add the scope explicitly as follows:
ui->imageView->setDragMode(QGraphicsView::ScrollHandDrag);
Note that how even the documentation specifies the scope for this constant:
QGraphicsView::ScrollHandDrag 1 The cursor changes into a pointing hand, and dragging the mouse around will scroll the scrolbars. This mode works both in interactive and non-interactive mode.
Here is my minimal building code:
#include <QGraphicsView>
int main()
{
QGraphicsView graphicsView;
graphicsView.setDragMode(QGraphicsView::ScrollHandDrag);
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT += widgets
SOURCES += main.cpp
Build and Run
qmake && make

c++: owlnext + vcl: New Window missing its Parent

I have a Application mostly written with the owl-libary.
There I want open new vcl-windows out of the main owl-window.
This works great, though if a dialog-window is opened (even with ShowModal) and I focus another application, then the main-window get's into foreground but is blocked by the window behind it.
I guess the Problem is the missing parent-setting.
However, I can't convert owl's TWindow to vcl's TWinControl.
Is there a trick to set a vcl's parent setting to a owl's TWindow-Object?
Or could this be caused by something entirely different?
EDIT:
I'm using...
void(TWindow* parent){
Form=new TForm((HWND)parent->Handle);
Form->ParentWindow=parent->Handle;
Form->BorderIcons >> biMinimize >> biMaximize << biSystemMenu; //No minimize, no maximize, but close
Form->BorderStyle = bsSingle;
Form->Position = poMainFormCenter;
...
Form->ShowModal();
...now.
However, the new window is locked up and can not be clicked/closed/switched to.
Is there something I missed in using ParentWindow?
EDIT2:
I think it might be a Problem that the parent is a TDecoratedMDIFrame, which is a MDI-Container, so my dialog is treated like a mdi-child instead of a normal dialog...
TWinControl has a ParentWindow property for specifying a non-VCL parent window.
Also, in modern VCL versions, you can specify a ParentWnd when displaying a VCL dialog.