Issues with external window

I have CWorkingArea (MAIN_AREA) and here is how the new dockables are added:

...
dockable.setStackable(true);
dockable.setSingleTabShown(false);
dockable.putAction(CDockable.ACTION_KEY_CLOSE, new CCloseAction(UIManager.DOCKING_CONTROL) {
            @Override
            public void close(CDockable dockable) {
                super.close(dockable);
                if (dockable.getFocusComponent() instanceof SeriesViewer) {
                    ((SeriesViewer) dockable.getFocusComponent()).close();
                }
                Dockable prevDockable =
                    UIManager.DOCKING_CONTROL.getController().getFocusHistory()
                        .getNewestOn(dockable.getWorkingArea().getStation());
                if (prevDockable != null) {
                   CDockable ld = ((DefaultCommonDockable) prevDockable).getDockable();
                    if (ld instanceof AbstractCDockable) {
                        ((AbstractCDockable) ld).toFront();
                    }
                } 
            }
        });
dockable.setCloseable(true);
dockable.setMinimizable(false);
dockable.setExternalizable(true);
dockable.setFocusComponent(ViewerPlugin.this);
MAIN_AREA.add(dockable);
dockable.setDefaultLocation(ExtendedMode.NORMALIZED, CLocation.working(MAIN_AREA).stack());
dockable.setVisible(true);

And a custom CFocusListener on CControl. The action of this listener can modify other dockables. The problem is that two focus events is received with the drag and drop of a dockable (it is Ok with externalize button action, I guess because the whole station is moving).
For instance, when dockable A and B are in MAIN_AREA (in stack mode) and C in externalized window:
Selecting A => in CFocusListener getting A
Dragging A into C => in CFocusListener getting B, then A

I don’t understand why B gets the focus because it is not selected. Is there a way to prevent or filter the focus of B.

I also noticed that the action of maximizing and normalizing (from the button of an external window) is very slow.

At the moment A is removed from the stack, the selection on the stack changes to B. In such a case the stack automatically tries to focus B. A little bit later the drag and drop operation is finished, and the “operation”-Object itself tries to focus A again.

In this case the code is not wrong - just not very efficient. I’ll update the code a bit, so that the stack realizes that a drag and drop operation is currently in progress, and that there is no need to change the focus. But there is no guarantee that similar inefficiencies remain in the code.

One good idea may be to delay any work that is related to focus-events by a few milliseconds - and ignore events that are overridden by newer events.


About the speed of maximizing and normalizing.

The last time I’ve heard issues like this, the problems were related to focus as well. In that other case the application was not happy about the fact, that DockingFrames calls “Component.requestFocus” 20 times in a row whenever it wants to focus a Component (the reason for this is that any focus request has a delay, but once an application requested the focus it may not request the focus on another component - at least that was happening in Java 1.5).

I would not know any other reason why only these two actions are slow - it works on my system… Maybe you could install a tool like VisualVM to find out what your application is actually doing?

Thanks for your quick reply.

Another solution would be to add a event object in CFocusListener like in the FocusEvent class with a method isTemporary(). It will be adapted for drag and drop, the temporary flag will be at true until the drop event.

I’ll investigate more for the maximize action of an external window.

[QUOTE=Beni]At the moment A is removed from the stack, the selection on the stack changes to B. In such a case the stack automatically tries to focus B. A little bit later the drag and drop operation is finished, and the “operation”-Object itself tries to focus A again.

In this case the code is not wrong - just not very efficient. I’ll update the code a bit, so that the stack realizes that a drag and drop operation is currently in progress, and that there is no need to change the focus. But there is no guarantee that similar inefficiencies remain in the code.

One good idea may be to delay any work that is related to focus-events by a few milliseconds - and ignore events that are overridden by newer events.


About the speed of maximizing and normalizing.

The last time I’ve heard issues like this, the problems were related to focus as well. In that other case the application was not happy about the fact, that DockingFrames calls “Component.requestFocus” 20 times in a row whenever it wants to focus a Component (the reason for this is that any focus request has a delay, but once an application requested the focus it may not request the focus on another component - at least that was happening in Java 1.5).

I would not know any other reason why only these two actions are slow - it works on my system… Maybe you could install a tool like VisualVM to find out what your application is actually doing?[/QUOTE]

In this case I don’t like the “temporary”-flag: If the framework already knows that the event is temporary, then it also knows that the focus request was unnecessary… and should never have requested the focus. Or in other words: the flag should always be “false”, and everytime it is “true” there is a bug in the framework.

Thanks, I just rebuild the framework with the focus fix and it works perfectly now.

I still have some problems with external windows on another screen:

  • External default size doesn’t work, it seems it is the size of the dockable component which is taken.
    dockable.setDefaultLocation(ExtendedMode.EXTERNALIZED, CLocation.external(b.x + 25, b.y + 25, b.width - 100, b.height - 100));
    For instance, when the dockable is externalized in the second monitor (which is smaller) even with a bound smaller than the screen, the window is displayed on the whole screen and it cannot be resized any more.
  • Sometimes maximizing the window is not correct (the screen inset spaces are two times). I also noticed the same problem on non externalized window, I found a workaround by removing the method “win.setMaximizedBounds(bound);” in my code. I there something in the framework that overriding the maximized bound of a window?

With Eclipse theme, I tried the new button on the tab and I think it is a good enhancement. Adding by default “Close All” and “Close Others” in contextual menu of a tab would be great.

The “default location” is only applied if you click on the “externalize” button. If you drag and drop the Dockable, then it tries to keep its current size.

Earlier I always said that I do not have access to a system with multiple screens. That has changed, I have a new laptop - and I will do some testing as soon as I got all the required hardware (I need an adapter for the mini display port). But this will not happen before the weekend. Until then you are on your own. You could try out some of these things:

The boundaries of each externalized Dockable is restricted by a class called “MediumBoundaryRestriction”. It would be interesting to know, if replacing the restriction algorithm helps, try out this piece of code, and please tell me if the behavior is better.

control.putProperty( ScreenDockStation.BOUNDARY_RESTRICTION, BoundaryRestriction.HARD );```

About maximizing not being correct: I did never notice this particular bug. The code that calculates the boundaries of a maximized Dockable is in "DefaultScreenDockFullscreenStrategy", and searches the GraphicsDevice of the window, then takes the default GraphicsConfiguration and finally returns the boundaries described by that GraphicsConfiguration. You could replace the default FullScreenStrategy with the property key "ScreenDockStation.FULL_SCREEN_STRATEGY" (just like in the code snippet above). A breakpoint in the default strategy would be more interesting, to know if the correct GraphicsDevice  and the correct GraphicsConfiguration are selected.

I do not remember a method named "setMaximizedBounds" (nor did I find it), which version of the framework are you using?


Finally about the "Close All" and "Close Others" button. It's a nice idea, I put it on my todo list. Should not be that much work, maybe I cook something up in this or the next version (I do not make any promises).

Thanks for your quick reply.

The boundaries of each externalized Dockable is restricted by a class called „MediumBoundaryRestriction“. It would be interesting to know, if replacing the restriction algorithm helps, try out this piece of code, and please tell me if the behavior is better.

control.putProperty( ScreenDockStation.BOUNDARY_RESTRICTION, BoundaryRestriction.HARD );```

Yes it works, now it takes in account the default size, but there is still a space (same size as the system bar) between the system bar and the window. The result is the same if the default size is the screen size or the size less the insets of the screen.

About maximizing not being correct: I did never notice this particular bug. The code that calculates the boundaries of a maximized Dockable is in „DefaultScreenDockFullscreenStrategy“, and searches the GraphicsDevice of the window, then takes the default GraphicsConfiguration and finally returns the boundaries described by that GraphicsConfiguration. You could replace the default FullScreenStrategy with the property key „ScreenDockStation.FULL_SCREEN_STRATEGY“ (just like in the code snippet above). A breakpoint in the default strategy would be more interesting, to know if the correct GraphicsDevice and the correct GraphicsConfiguration are selected.

What should be the value of „ScreenDockStation.FULL_SCREEN_STRATEGY“?

Maximizing the external window on the main screen is OK, but not in the second monitor (with a system bar).

I do not remember a method named „setMaximizedBounds“ (nor did I find it), which version of the framework are you using?

I mean in the method of a JFrame. I think it is related to the Dockingframes because without it I don’t have this issue (I’m not 100% sure of that).

What should be the value of „ScreenDockStation.FULL_SCREEN_STRATEGY“?

I just added that line, in case you want to try out a custom implementation. There is only one strategy implemented.

The system bar… what OS are you using? And what JRE?

It would be interesting to see what numbers are actually used by the algorithms. Could you please run the application below and tell me what the output was? According to the API, „bounds - insets“ should return the size of a maximized window.


import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;

public class ScreenTest {
	public static void main(String[] args) {
		GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
		for(GraphicsDevice device : devices){
			System.out.println(device);
			
			GraphicsConfiguration config = device.getDefaultConfiguration();
			System.out.println(" - bounds: " + config.getBounds());
			System.out.println(" - insets: " + Toolkit.getDefaultToolkit().getScreenInsets(config));
		}
	}
}

I just got my adaptor and tested the framework on two screens (with different resolutions).

Unfortunately (or fortunately?) I could not reproduce the issue you described, with the insets being applied twice. I was using a Linux (Kubuntu) system.

I’ve investigated a bit more and I’ve found that:

  1. The method setMaximizedBounds() of JFrame must not included the insets of screen on Windows 7, but on Linux KDE the window is maximized correctly with or without the insets.

  2. For the externalized window, the problem is not that the insets is applied twice but that the insets are always equal to 0 with KDE and the maximized state is adjusted by the system. You should manage to reproduce the error on Kubuntu by changing the place of the bar on the second screen (or in the main screen). The maximized state is sometimes correct and sometimes shifted.

The result of setting the maximized bound seems to be different on the different operating systems. On KDE, it seems particularly difficult to manage it because you cannot get the insets of the screen.

On KDE, the following method always returns the screen size:
bibliothek.gui.dock.station.screen.DefaultScreenDockFullscreenStrategy.getAvailableBounds(GraphicsConfiguration)

[QUOTE=nroduit]On KDE, the following method always returns the screen size:
bibliothek.gui.dock.station.screen.DefaultScreenDockFullscreenStrategy.getAvailableBounds(GraphicsConfiguration)[/QUOTE]

Not even that is consistent, on my machine the insets are something else than 0/0/0/0 and I am using KDE.

Seems also to be an issue with the JDK, some bugs were fixed in JDK 7: bug 4737732