When isActive () is called in a window while dragging / resizing, false returns. (X11, Qt, 5.4.0)

I am using Qt 5.4.0 for linux (X11) and I need to determine if my window will be active. So, I wrote the sample code below. If this code is compiled on Windows, it only logs “false” in the console when the window is really inactive. But on linux (X11), it also writes “false” when I start dragging or resizing a window. Why is this happening and how to fix it on Linux? I want to know when my window is really inactive, and when it is active, but is being dragged / resized.

code snippet (C ++):

void MainWindow::changeEvent(QEvent *e) { if (e->type() == QEvent::ActivationChange) { if (this->isActiveWindow()) { std::cout << "True" << std::endl; } else { std::cout << "False" << std::endl; } } } 

same code on PyQt5:

 import sys from PyQt5.QtCore import Qt, QEvent from PyQt5.QtWidgets import QWidget, QApplication class TransparentWidget(QWidget): def __init__(self): super(TransparentWidget, self).__init__() def changeEvent(self, e): if e.type() == QEvent.ActivationChange: print(self.isActiveWindow()) if __name__ == '__main__': app = QApplication(sys.argv) transparent_widget = TransparentWidget() transparent_widget.show() app.exec_() 
+5
source share
2 answers

It probably logs a “false” because in X you actually see two windows: a window in which you draw your content and a larger window, which is the parent window and contains the border.

The reason is that X11 has no concept of “decorated border” with “close” / “max / min” buttons, a header, beautiful gradient colors, rounded borders, etc. (X11's own windows can have a border, but only as a solid color or texture). These controls are provided by your window manager. It happens that if you create a window, the window manager creates an additional X11 window, which is slightly larger than yours, and places your window as a child in this new window. From this moment, the two windows are closely related: resizing the window will resize the parent window and vice versa.

All this is handled by the window manager. For example, if you want to resize the window and click on the border, the click will not be in your window, but in the window manager, which will then determine where the click was and decide what to do with it. So, at this point, your own window is no longer active, which explains why isActiveWindow () returns false.

In Microsoft Windows, the border is an integral part of the window itself, so it remains "active".

In any case, to find out if your window is "active" or not, you should use QFocusEvent. If you look at the values ​​of gotFocus () and lostFocus (), you should keep track of when you are active or not.

+1
source

An active window is a window that currently accepts keyboard focus, and therefore is also a window to which keyboard events are sent.

During the resize / move operation, the active window does not register keyboard events (regardless of whether they are sent or not). Given this, it can be argued that the window should still be considered active during such operations.

Qt4 and Qt5 differ in how they deal with this. Qt4 does not report window activation changes (or focus changes) during resizing / moving on any platform (although I actually tested only on X11 and Windows). The same is true for Qt5 - except when it comes to X11.

In X11, Qt5 reports a change in window activation (and focus change) at the beginning and end of all resize / move operations. That is, isActiveWindow() returns False when the operation starts and True when it ends (and the corresponding FocusIn/FocusOut events are also FocusIn/FocusOut , as well as WindowActivate/WindowDeactivate , etc.).

It can be argued that the behavior of Qt5 on X11 is the only one that is accurate. However, it is incompatible with other platforms supported by Qt5, and therefore, from the point of view of the developer, it should be considered erroneous (or at least inconvenient).

Although the behavior on Qt4 is perhaps less acccurate, it is at least consistent across all supported platforms (that is, exactly what the developer expects from cross-platform toolkit).

Unfortunately, resize / move events only start after a window's activation changes, so there seems to be no obvious way to filter out unwanted activation events in Qt5.

0
source

Source: https://habr.com/ru/post/1215663/


All Articles