Activate window - c++

i have a QMainWindow. It has this parameters:
this->setWindowFlags(Qt::Tool);
this->setFocusPolicy(Qt::StrongFocus);
this->setAttribute(Qt::WA_QuitOnClose,true);
After showEvent calles my window is shown but unactivated.
I tried to overload show function:
...
QMainWindow::showEvent(event);
this->activateWindow();
...
But it doesn't help me.
EDIT:
When i commented line
this->setWindowFlags(Qt::Tool);
everything worked fine, but i need in tool-flag.
Any ideas?
EDIT:
OS: Linux
Programming language: c++
Qt version: 4.5.1

The Windows Manager Decides
Before I start: As pointed out by elcuco and Javier, focus policy and other aspects of the windows layout (e.g. the title bar) belongs to a substantial extend to the respective windows manager, and Qt might have limited control. To see this, just look at a user interface that has a "focus follows mouse" policy. In these cases, the windows manager might ignore Qt's focus request. For this reasons, the Qt documentation calls many of the respective flags "hints". Consequently, some of the suggested solutions might or might not work for you.
QApplication::setActiveWindow()
This not withstanding, e.tadeu's solution to use QApplication::setActiveWindow() works for me for both Windows and Ubuntu with Gnome. I tested it with the following code. Apologies that it is Python using PyQt (I use questions like these to learn a bit about PyQt). It should be fairly easy for you to read it and translate it into C++.
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self)
# main window
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Test')
# text editor
self.textEdit = QtGui.QTextEdit()
self.setCentralWidget(self.textEdit)
def closeEvent(self, event):
QtGui.QApplication.instance().quit()
#main
app = QtGui.QApplication(sys.argv)
testWindow = MainWindow()
testWindow.setWindowFlags(QtCore.Qt.Tool)
testWindow.show()
app.setActiveWindow(testWindow)
app.exec_()
Note that you have to add some handling of the close event of the testWindow, because the app does not exit automatically if you close a Qt::Tool window.
The grabKeyboard() Hack
If this does not work for you, the following hack might. I assume that you have a window in your application that is active. You can then use grabKeyboard() to redirect the input. The Qt::Tool window doesn't get the focus, but receives the input. The following main code demonstrates it (the other code remains unchanged).
#main
app = QtGui.QApplication(sys.argv)
testWindow = MainWindow()
testWindow.setWindowFlags(QtCore.Qt.Tool)
testWindow2 = MainWindow() # second window which is active
testWindow2.show()
testWindow.show()
testWindow.textEdit.grabKeyboard()
app.exec_()
Basically, while the window testWindow2 is the active one, all text entered shows up in testWindow.textEdit. It is not nice, I know...
Creating Your Own Window
You gain the most flexibility (and create the most work for yourself) by rolling out your own window layout. The idea is described in the following FAQ.
Other "Solutions"
You could directly call the respective window manager's API function to get the desired result (clearly against the very reason for using Qt in the first place). You could also hack the Qt source code. For example, on Windows, Qt uses the ShowWindow() function with a SW_SHOWNOACTIVATE flag, to show a window with style WS_EX_TOOLWINDOW if you set the Qt::Tool flag. You could easily replace the SW_SHOWNOACTIVATE with whatever you want. Linux should be the same. Clearly also not recommended.

Try to use QApplication::setActiveWindow()

The original apple Human Interface Guidelines(*) said that toolbox windows were "always on top but never activated". It also advises against using text boxes on them, precisely because the lack of activation-state feedback.
Check how other 'toolbox heavy' apps behave. I faintly recall that at least GIMP and InkScape seem very different in this aspect.
As elcuco said, the window manager can do whatever it wants with Qt's flags. Also, it sure would be different under KDE, Gnome, fluxbox, whatever.
(*):great document! somewhat outdated; but tool windows were already used and considered

Which operating system? Which Qt4?
On Linux you are doomed, the window manager can ignore what you are telling him. Keep it under consideration.

Does the same thing happen if you just make it a regular QWidget instead of a QMainWindow?
Also, perhaps you might be better trying to achieve whatever effect you need Qt::Tool for by other means if that's possible?

Regarding Qt::Tool WindowFlags To quote Qt documentation
Indicates that the widget is a tool
window. A tool window is often a small
window with a smaller than usual title
bar and decoration, typically used for
collections of tool buttons. It there
is a parent, the tool window will
always be kept on top of it. If there
isn't a parent, you may consider using
Qt::WindowStaysOnTopHint as well. If
the window system supports it, a tool
window can be decorated with a
somewhat lighter frame. It can also be
combined with Qt::FramelessWindowHint
It seems the flags is a problem and using Qt::WindowStaysOnTopHint should solve your problem.

Just call show() after setWindowFlags().

Related

Mac override window maximize button c++

I am writing an application, and I want to change the default behavior of the Window Maximize button on Mac.
Since few latest versions of MacOS it defaults to putting the app in fullscreen mode, however it's not what I want.
I want the same behavior as in Windows OS.
I'm using C++.
Ideally what I want is to intercept some window function callback, disable entering fullscreen and instead just maximize the window to entire desktop working area.
How to do this?
Thanks
It's going to be difficult to help you since there's no native C++ binding for Cocoa. If you're programming using C++, you must be using some third-party library like Qt or SDL or something like that, but you neglect to tell us what that is.
Also, macOS doesn't have and never has had a "maximize" feature, let alone one like Windows. It has a zoom operation on windows, but that's not the same thing. It's simply an automated resize, it doesn't put the window into a mode where it's locked to the new size until it's restored.
Anyway, to achieve what you want, you should set the window's collectionBehavior property to include NSWindowCollectionBehaviorFullScreenNone and not NSWindowCollectionBehaviorFullScreenPrimary or NSWindowCollectionBehaviorFullScreenAuxiliary. So, in Objective-C(++):
window.collectionBehavior &= ~(NSWindowCollectionBehaviorFullScreenPrimary | NSWindowCollectionBehaviorFullScreenAuxiliary);
window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenNone;
If your window is defined in a NIB, you can set its Full Screen behavior to None in the Attributes inspector.
Setting this for NSWindow did the trick:
self.collectionBehavior|=NSWindowCollectionBehaviorFullScreenNone;

Qt 5 Mac toolbar woes

I am trying to make a very simple toolbar in a QMainWindow on a Mac, with Qt 5.2.1, with not a single satisfaction. I was using still Qt 4.8 but I thought I'd give Qt5 a try.
As QtMacExtras are concerned, I don't find the native toolbar class anymore, except in private headers. So I tried a simple QToolbar.
I have a very basic and stupid toolbar:
setUnifiedTitleAndToolBarOnMac(true);
toolbar_ = new QToolBar(this);
toolbar_->setMovable(false);
toolbar_->setFloatable(false);
toolbar_->addAction("h");
toolbar_->addAction("w");
toolbar_->addSeparator();
toolbar_->addAction("f");
As you can see, well, it isn't acceptable.
Is there any chance, by some arcane and weird means, that I could have a nice unified, or better "native look and feel", toolbar on a mac?
QMainWindow::addToolBar(QToolBar *toolbar) should do it.
The NSToolbar does not form part of the Qt widget hierarchy, so your admirably idiomatic conference of parenthood from the main window to the toolbar is working perfectly to specification, yet is obviously dissatisfying.
However, as the Trolls say in the QMainWindow documentation:
"You add a toolbar to a main window with addToolBar()."
Here is the effect as shown in rsync client for Mac.
I don't have my mac with me otherwise I would give this a quick test. I was surprised when browsing how many bugs are still being reported for Mac. I did find this article, which does appear to have better looking toolbar.

QT How to embed an application into QT widget

In our project we have three independent applications, and we have to develop a QT control application that controls these three applications. The main window will be seperated to three sub windows - each one display another one application.
I thought to use QX11EmbedWidget and QX11EmbedContainer widgets, but two problems with that:
The QX11Embed* is based on X11 protocol and I dont know if it's supported on non-x11 systems like Windows OS.
Since QT 5 these classes are not existing, and the QT documentation doesn't mention why.
So that I dont know whether to use it or not - I'll be happy to get an answers.
In addition, I see that the QT 5.1 contains QWidget::createWindowContainer(); function that in some posts it looks like this should be the replacement to the X11Embed. Can anyone please explian me more how can I use this function to create a QT widget that will run another application (a Calculator for example) inside its?
I have searched a lot in Google, and didn't find answers to my Qs.
Can anyone please help me? Am I on the right way?
Thanks!
If all three independent applications are written with Qt, and you have their source, you should be able to unify them just through the parenting of GUI objects in Qt.
http://qt-project.org/doc/qt-4.8/objecttrees.html
http://qt-project.org/doc/qt-4.8/widgets-and-layouts.html
http://qt-project.org/doc/qt-4.8/mainwindows-mdi.html
If you don't have access to them in that way, what you are talking about is like 3rd party window management. It is kind of like writing a shell, like Windows Explorer, that manipulates the state and the size of other window applications.
Use a program like Spy++ or AutoIt Spy for Windows and the similar ones for other OS's, and learn the identifying markings of your windows you want to control, like the class, the window title, etc. Or you can launch the exe yourself in a QProcess::startDetached() sort of thing.
http://qt-project.org/doc/qt-5.1/qtcore/qprocess.html#startDetached
Then using the OS dependent calls control the windows. The Qt library doesn't have this stuff built in for third party windows, only for ones under the QApplication that you launched. There are a lot of examples of doing things like this by AutoHotKey, or AHK. It is a scripting language that is made for automating a lot of things in the windows environment, and there is port for Mac as well (though I haven't tried the mac port myself).
So in the end you are looking at finding your window probably with a call like this:
#include <windows.h>
HWND hwnd_1 = ::FindWindow("Window_Class", "Window Name");
LONG retVal = GetWindowLongA(hwnd_1, GWL_STYLE); // to query the state of the window
Then manipulate the position and state of the window like so:
::MoveWindow(hwnd_1, x, y, width, height, TRUE);
::ShowWindow(hwnd_1, SW_SHOWMAXIMIZED);
You can even draw widgets on top of the windows you are controlling if you set your window flags correctly for the windows you are manipulating.
transparent QLabel with a pixmap
Cannot get QSystemTrayIcon to work correctly with activation reason
Some gotchas that come up in Windows when doing all of this, is finding out the quirks of the Windows UI when they set the Display scaling different from what you expect, and if you want to play nice with the Task bar, and handling all the modal windows of your programs you are manipulating.
So overall, it is do-able. Qt will make a nice interface for performing these commands, but in the end you are looking at a lot of work and debugging to get it in a beautiful, reliable, window manager.
Hope that helps.
I never tried it myself, but from the docs in Qt 5.1 I would try QWindow::fromId(WId id), which gives you a QWindow, which should be embeddable with createWindowContainer:
QWindow * QWindow::fromWinId(WId id) [static] Creates a local
representation of a window created by another process or by using
native libraries below Qt.
Given the handle id to a native window, this method creates a QWindow
object which can be used to represent the window when invoking methods
like setParent() and setTransientParent(). This can be used, on
platforms which support it, to embed a window inside a container or to
make a window stick on top of a window created by another process.
But no guarantee. :-)

Centering a Tkinter Toplevel window in both windows and remote X11?

I know Tkinter can be an exercise in frustration at times, but I am stumped on the "correct" sequence of calls to a Tkinter/ttk Toplevel widget/window that will:
Display the window in the center of the screen WITHOUT drawing it off-center and THEN moving it.
Size the window properly.
Make the window toplevel to the parent form, but not system modal (that is, not toplevel to ALL apps/windows on the system).
Optionally create a taskbar button on Windows.
This is the current code that I have so far, with some unrelated bits removed for simplicity's sake:
def __init_ui__(self):
#// Basic setup.
self.wm_overrideredirect(False)
self.wm_resizable(False, False)
self.configure(relief=FLAT, borderwidth=4)
#// <Some extraneous widget-creation here>
#// Done!
self.update()
self.withdraw()
self.update_idletasks()
self.grid()
self.transient(self._parent)
self.grab_set()
self.form.initial_focus() #// sets initial focus before the window is displayed
center(self) #// https://stackoverflow.com/a/10018670
self.deiconify()
self._parent._parent.wait_window(self) #// Reaches back to the root Tk() obj.
# ENDIF
# END __init_ui__
This form inherits from a custom class I created that wraps a bunch of widget-creation calls, and the class inherits down from object. A second inheritance comes from ttk.Toplevel, to give it access to the various self.wm_* calls and other Tkinter goodies.
That said, I am certain some of my function calls are unneeded. But this particular call order seems to mostly work well on Windows 7. Under X11-over-ssh (using Xming for the X server in Windows), however, things get a bit weirder. In that case, if I move self.update() to be after self.withdraw(), then the window is centered correctly w/o redraw on Windows 7, but on X11, it is drawn and properly centered whilst hidden, but has ZERO geometry (only the compressed window border/decorations are shown). It's as-if grid propagation didn't fire or such.
But where self.update() is right now, it properly sizes and centers the window on both windows and X11 - but you can see the window getting created off-center THEN moved to center on both.
If I use self.wm_attributes("-toolwindow", 1) on Windows, then the windows gets centered without me seeing it, but -toolwindow only works on Windows system. It's an invalid command to both X11 and Aqua.
I'd like to avoid calls to tk::windowingsystem all the time to determine what my window manager is and having to apply different hacks for Windows and X11. And I can't test Mac/Aqua (don't own one, not going to buy), so I'll just have to hope the end look is somewhat functional on that platform.
Additionally, if I click away to another window/app under both Windows and remote X11, clicking back on the main form via the taskbar button only displays the main form -- the child Toplevel window only pops back up when you click anywhere inside the main form. Fixed: (kinda) -- I forgot that adding an argument to self._transient() kinda fixed that by specifying the parent. Earlier tonight, I didn't pass the parent argument in, thus the focusing wasn't right.
So is there some kind of tried-and-true magik recipe or invocation to the Priests of Ancient Mu to get a Tkinter/ttk Toplevel window to size, center, and properly get focus if it's not the root window? Using minimal X11, Motif-look, btw.
And no, I am not using PyGTK, PyQT, wxPython, or some other toolkit. It's standard Tkinter/ttk or bust, since that's what I've spent the last few weeks learning and writing wrapper functions for. The autocomplete combobox I worked up is a cute little contraption. Still slightly buggy, but that's a topic for another SO question...
PS, The Tkinter cookbook on Effbot is down. Looks like a server crash. Did anyone happen to mirror that site by chance?
Solved! Had to tweak the order of the calls a little bit:
#// Done!
self.withdraw()
self.grid()
self.transient(self._parent)
self.grab_set()
self.form.initial_focus()
center(self)
self.deiconify()
self._parent._parent.wait_window(self)
But the real fix was in the center() function I lifted from this answer, by changing the calls to winfo_width()/winfo_height() to winfo_reqwidth()/winfo_reqheight() and adding a call to update() as the first call in center(). Now I get my dialog windows to pop up in the center without seeing them move, focus is applied correctly, and it works on both Windows and remote X11. Maybe one day, I'll find out how well it works on Mac OS X/Aqua.

How to get the minimize and maximize buttons to appear on a wxDialog object

I've run into an issue using a wxDialog object on Linux In the construtor for the object I pass the relevant style flags (wxCAPTION|wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX|wx_RESIZE_BORDER) but the buttons don't show up. When I was designing the class in wxformbuilder they would appear on the displayed design but don't show up in my running application.
I'm using wxWidgets 2.8.7 at the moment and running on Scientific Linux 5 (RHEL 5). Any suggestions or ideas on how to work around this?
EDIT: BTW, This is related to this question
If you create a dialog on wxGTK then during construction
gtk_window_set_type_hint(GTK_WINDOW(m_widget), GDK_WINDOW_TYPE_HINT_DIALOG);
is called, which leaves it up to the window manager what decoration is shown for this window. So if you give it the style but no buttons are shown, then there's nothing you can do. In any case, I think showing a wxFrame while the parent frame is disabled should work just as well.
Can you use a wxWindow instead of a wxDialog? Maybe it doesn't make sense to minimize a dialog but those are usual operations for application windows.