What is the expected behavior of _NET_WM_STATE_MODAL? - modal-dialog

I am making a cross-platform windowing layer. When making window relationship stuffs, I got some trouble on window modality.
I have read the official spec: Application Window Properties, and some related topics like this: X11 modal dialog. It seems not sufficient to only set transient-for, but _NET_WM_STATE_MODAL is also required. So I tried to make small programs that apply this property along with transient-for.
I firstly made the program that create the window using SDL2, and use X11 stuffs using the fetched native window handle. But I did not observe any behavior change after the _NET_WM_STATE_MODAL attribute is set: the transient-for target window is still receiving mouse button events, which is not like a modal-blocked parent window that cannot operated by user.
To avoid potential evil stuffs done by SDL2, I further made the test program using GDK3, which provides ready-to-use wrapper functions. The behavior is same as the SDL2 program.
As I did not observed any change before/after _NET_WM_STATE_MODAL is set, what is the expected behavior of that property?

As I did not observed any change before/after _NET_WM_STATE_MODAL is set, what is the expected behavior of that property?
That's a question we cannot answer. It's a hint for the window manager to indicate modality, but, as in most cases, it is up to the window manager to decide what to do with this hint.
In other words behavior depends entirely upon the window manager and you haven't stated which window manager you were testing with.
Furthermore, this hint requires the window manager to be EWMH-compliant, which not all of them are or aren't fully. You can use _NET_SUPPORTED on the root window to see a list of atoms the window manager claims to support. If _NET_WM_STATE_MODAL isn't listed there, chances are the window manager really doesn't implement this hint at all. If it is listed, the window manager claims to support it, but a) it might be lying (let's not assume that, though) and b) behavior is up to the window manager.

Related

Moving (repositioning) a Child Window or Dialog in Gtk / Gtkmm

A child Gtk::Window or Gtk::Dialog may be moved around by dragging on the title bar. Being top level windows this activity requires support from the window manager. What is the mechanism by which Gtk requests the window manager to move the position of the window?
Background
I have a Gtk application running on a custom Linux distribution (based on Yocto running Waland/Weston). The application is developed on Ubuntu 20 which has both X11 backend and Wayland backend. The child dialogs or windows that are spawned by the main window are perfectly centered on the main window (in Ubuntu on both backends). However on the target (with Weston) the dialogs or windows appear at random position. Now I understand that this is reported in several forums (like this one in stackoverflow itself).
Different Approach?
With what ever little I know I tried Gtk::Window::move, Gdk::Window::move and even dared to play with Wayland surfaces (gdk_wayland_window_set_transient_for_exported ) but with no avail.
That left me wondering how the user is able to move such child windows by grabbing the header bar (or title bar as Gtk::Window calls it) even under Weston. If I get to know how this works then perhaps I can emulate a grab-drag to position the window where ever I want.
I tried sifting through gtkwindow.c to find out what happens when one sets the title bar using the function gtk_window_set_titlebar but the rabbit hole went a little too deep.
It would be great if someone can point me in the right direction, at least quote some functions whose implementation I can study to get this working....
Your question consists of multiple smaller ones, so I'll try to give a shot at answering each and one of them.
The general idea is that Wayland is quite minimal, so to make it suitable for desktop use cases, you need a protocol extension. This extension is called XDG Shell.
A child Gtk::Window or Gtk::Dialog may be moved around by dragging on the title bar. Being top level windows this activity requires support from the window manager. What is the mechanism by which Gtk requests the window manager to move the position of the window?
This first part is described in the Wayland book, but the idea is that you forward an input event (usually a drag) back to the compositor, who will know what do with it. That might mean moving the window (or not moving it, if you've reached the edge of the screen.
However on the target (with Weston) the dialogs or windows appear at random position. Now I understand that this is reported in several forums (like this one in stackoverflow itself).
Note that your confusing 2 questions here: one is where to put a child window, compared to a parent window, while the second sentence here talks about position any toplevel window. There is also a section in the Wayland book on popups (part of XDG shell also) which also describe something similar.
So whether you can arbitrarily move windows: the answer is no.
The most important question then becomes: what can you do to solve your problems with Weston? It's hard to say without any kind of code. You might want to make sure you set the GtkDialog parent when constructing it (also known as the transient_for property. You might want to play around with the modal flag also. There might be other options too, but it's a bit of a blind guess.

Let a window display above a fullscreen window in GTK+

I have a full-screen window (winA) and another window (winB) which is always on top.
Now I need to let winB display above winA, while winA is still above any other windows.
How to do this in GTK+? Thanks. (Maybe this needs Xlib?)
PS1: I won't use POPUP windows because it will put all the windows under it. I just need put winB on winA but not all the others. For example, if I am watching videos in the fullscreen mode, I wouldn't like to see winB. But if winA it's here, winB is just above it.
PS2: winA & winB are in the same program. In this case, it may simplify the solution.
The main way to tell the window manager to keep winB above winA is through the "transient for" hint, set in GTK+ with gtk_window_set_transient_for().
If your window is not a dialog, the behavior may not come out quite how you'd like; you could try setting a semantic hint with gtk_window_set_type_hint() and see if that gets you anywhere.
But the behavior is basically going to vary with window manager (which is intended). So you kind of need to just live with that and assume people will use a WM that works how they want it to.

How can I make my Eclipse RCP app's keyboard shortcuts (accelerators) work immediately after startup?

Our Eclipse RCP application was originally built in the 3.1/3.2 era and was running on 3.2 until we switched to 3.6 recently. Its IApplication runs via PlatformUI.createAndRunWorkbench(...). The WorkbenchAdvisor we pass to that function overridescreateWorkbenchWindowAdvisor(...) to return a WorkbenchWindowAdvisor whose createActionBarAdvisor(...) returns an ActionBarAdvisor.
This ActionBarAdvisor's makeActions(...) creates and register()s a bunch of org.eclipse.jface.action.Actions, many of which do things like setAccelerator(SWT.CTRL | 'O'); in their constructors. The Actions are subsequently installed in the ActionBarAdvisor's fillMenuBar(...) and fillCoolBar(...) methods.
The problem we are having (now that we are on Eclipse RCP 3.6) is that these accelerators don't seem to be active until their menus are shown (even if no action is taken besides closing the menu again).
We see a relevant bug but are having some difficulty understanding how to apply its remedy to our situation. We recognize that instead of Actions we "ought" to be using commands, handlers, and key bindings. But we're hoping we don't have to go down that path just yet.
How can we make our accelerators "live" as soon as the application starts up?
If you don't choose to use o.e.ui.bindings extension point, then there isn't a better way. You should only force update the menuManager yourself as you have done in your answer.
As #Prakash mentioned, if you want to keep down that path in your RCP app you must render all of the main menus to see your accelerators.
There is a partial upgrade path that will get you on the right track to commands without forcing a complete switch over right away. For each action in your menu, define a command with an id and define a binding to the shortcut you want in your plugin.xml. Then, when you create the action in your ActionBarAdvisor, don't set the accelerator. Set the IAction.setActionDefinitionId(*) to the command id, can call register(action);
Then you no longer need to use menuManager.updateAll(true) to eagerly render all of your main menu.
After hunting around and experimenting a bit trying to apply the advice from the bug, we added the following to our WorkbenchWindowAdvisor, which seems to have done the trick:
#Override
public void postWindowCreate() {
getWindowConfigurer().getActionBarConfigurer().getMenuManager().updateAll(true);
}
We have no idea how well this fits with the Workbench's design expectations; there could be a better way.

Eclipse RCP Splash Screen

I'm involved in a project that is attempting to use the Eclipse RCP splash screen to gather user credentials, language, etc. If this screen loses focus, it is not available (under Windows at least) through the ALt-Tab functionality, and can only be found by minimizing all other windows and uncovering it. Any way of having this screen allow itself to be activated in this way? They're avoiding creating an intermediate screen, for reasons unknown at this point.
I think it might be time to examine those unknown reasons. Even eclipse doesn't use the splash screen in this way. If it needs to prompt for information, it opens a new dialog to ask for it.
Good luck.
[Edit] I stand corrected. This thread seems to have a solution to this. Good luck, I'm no SWT/RCP guru.
See this page. From one of the comments:
The splash screen window is created natively with the extended window style WS_EX_TOOLWINDOW which makes it not appear in the task bar. This corresponds to the SWT constant SWT.TOOL.
I don't know if it's possible to change the window style after it is created on Windows. You can always drop down to JNI if that's necessary.
Create your own implementation of AbstractSplashHandler.
When creating the shell, don't use the SWT.TOOL style.
The shell will be accessible through the windows task bar.

What determines the monitor my app runs on?

I am using Windows, and I have two monitors.
Some applications will always start on my primary monitor, no matter where they were when I closed them.
Others will always start on the secondary monitor, no matter where they were when I closed them.
Is there a registry setting buried somewhere, which I can manipulate to control which monitor applications launch into by default?
#rp: I have Ultramon, and I agree that it is indispensable, to the point that Microsoft should buy it and incorporate it into their OS. But as you said, it doesn't let you control the default monitor a program launches into.
Here's what I've found. If you want an app to open on your secondary monitor by default do the following:
1. Open the application.
2. Re-size the window so that it is not maximized or minimized.
3. Move the window to the monitor you want it to open on by default.
4. Close the application. Do not re-size prior to closing.
5. Open the application.
It should open on the monitor you just moved it to and closed it on.
6. Maximize the window.
The application will now open on this monitor by default. If you want to change it to another monitor, just follow steps 1-6 again.
Correctly written Windows apps that want to save their location from run to run will save the results of GetWindowPlacement() before shutting down, then use SetWindowPlacement() on startup to restore their position.
Frequently, apps will store the results of GetWindowPlacement() in the registry as a REG_BINARY for easy use.
The WINDOWPLACEMENTroute has many advantages over other methods:
Handles the case where the screen resolution changed since the last run: SetWindowPlacement() will automatically ensure that the window is not entirely offscreen
Saves the state (minimized/maximized) but also saves the restored (normal) size and position
Handles desktop metrics correctly, compensating for the taskbar position, etc. (i.e. uses "workspace coordinates" instead of "screen coordinates" -- techniques that rely on saving screen coordinates may suffer from the "walking windows" problem where a window will always appear a little lower each time if the user has a toolbar at the top of the screen).
Finally, programs that handle window restoration properly will take into account the nCmdShow parameter passed in from the shell. This parameter is set in the shortcut that launches the application (Normal, Minimized, Maximize):
if(nCmdShow != SW_SHOWNORMAL)
placement.showCmd = nCmdShow; //allow shortcut to override
For non-Win32 applications, it's important to be sure that the method you're using to save/restore window position eventually uses the same underlying call, otherwise (like Java Swing's setBounds()/getBounds() problem) you'll end up writing a lot of extra code to re-implement functionality that's already there in the WINDOWPLACEMENT functions.
It's not exactly the answer to this question but I dealt with this problem with the Shift + Win + [left,right] arrow keys shortcut. You can move the currently active window to another monitor with it.
Get UltraMon. Quickly.
http://realtimesoft.com/ultramon/
It doesn't let you specify what monitor an app starts on, but it lets you move an app to the another monitor, and keep its aspect ratio intact, with one mouse click. It is a very handy utility.
Most programs will start where you last left them. So if you have two monitors at work, but only one at home, it's possible to start you laptop at home and not see the apps running on the other monitor (which now isn't there). UltrMon also lets you move those orphan apps back to the main screen quickly and easily.
I'm fairly sure the primary monitor is the default. If the app was coded decently, when it's closed, it'll remember where it was last at and will reopen there, but -- as you've noticed -- it isn't a default behavior.
EDIT: The way I usually do it is to have the location stored in the app's settings. On load, if there is no value for them, it defaults to the center of the screen. On closing of the form, it records its position. That way, whenever it opens, it's where it was last. I don't know of a simple way to tell it to launch onto the second monitor the first time automatically, however.
-- Kevin Fairchild
Important note: If you remember the position of your application and shutdown and then start up again at that position, keep in mind that the user's monitor configuration may have changed while your application was closed.
Laptop users, for example, frequently change their display configuration. When docked there may be a 2nd monitor that disappears when undocked. If the user closes an application that was running on the 2nd monitor and the re-opens the application when the monitor is disconnected, restoring the window to the previous coordinates will leave it completely off-screen.
To figure out how big the display really is, check out GetSystemMetrics.
So I had this issue with Adobe Reader 9.0. Somehow the program forgot to open on my right monitor and was consistently opening on my left monitor. Most programs allow you to drag it over, maximize the screen, and then close it out and it will remember. Well, with Adobe, I had to drag it over and then close it before maximizing it, in order for Windows to remember which screen to open it in next time. Once you set it to the correct monitor, then you can maximize it. I think this is stupid, since almost all windows programs remember it automatically without try to rig a way for XP to remember.
So I agree there are some apps that you can configured to open on one screen by maximizing or right clicking and moving/sizing screen, then close and reopen. However, there are others that will only open on the main screen.
What I've done to resolve: set the monitor you prefer stubborn apps to open on, as monitor 1 and the your other monitor as 2, then change your monitor 2 to be the primary - so your desktop settings and start bar remain. Hope this helps.
Do not hold me to this but I am pretty sure it depends on the application it self. I know many always open on the main monitor, some will reopen to the same monitor they were previously run in, and some you can set. I know for example I have shortcuts to open command windows to particular directories, and each has an option in their properties to the location to open the window in. While Outlook just remembers and opens in the last screen it was open in. Then other apps open in what ever window the current focus is in.
So I am not sure there is a way to tell every program where to open. Hope that helps some.
I've noticed that if I put a shortcut on my desktop on one screen the launched application may appear on that screen (if that app doesn't reposition itself).
This also applies to running things from Windows Explorer - if Explorer is on one screen the launched application will pick that monitor to use.
Again - I think this is when the launching application specifies the default (windows managed) position. Most applications seem to override this default behavior in some way.
A simple window created like so will do this:
hWnd = CreateWindow(windowClass, windowTitle, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, SW_SHOW, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);
Right click the shortcut and select properties.
Make sure you are on the "Shortcut" Tab.
Select the RUN drop down box and change it to Maximized.
This may assist in launching the program in full screen on the primary monitor.