JWebBrowser not rendered correctly inside a docking container

Hi,

When adding chrriis.dj.nativeswing.swtimpl.components.JWebBrowser inside a docking container I won’t be able to see the content of the page anymore
Could you please advise?

import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;

import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.action.predefined.CCloseAction;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.util.DirectWindowProvider;
import bibliothek.gui.dock.util.Priority;

import net.miginfocom.swing.MigLayout;



public class ExampleWithDocking {
    private static String DOCKBALE_RESTORE = "Restore";
    private static String DOCKBALE_DETACH = "Detach";
	
	public ExampleWithDocking() {
		JPanel rootPanel = new JPanel();
		rootPanel.setLayout(new MigLayout("fill, insets 0"));
		
		final CControl control = new CControl();
		control.setGroupBehavior(CGroupBehavior.TOPMOST);
		CContentArea contentArea = control.getContentArea();
		CGrid grid = new CGrid(control);
        control.getController().getTexts().put(Priority.CLIENT, "normalize.in", DOCKBALE_RESTORE);
        control.getController().getTexts().put(Priority.CLIENT, "externalize.in", DOCKBALE_DETACH);
        control.getController().getTexts().put(Priority.CLIENT, "externalize.out", DOCKBALE_RESTORE);
        control.getController().getTexts().put(Priority.CLIENT, "maximize_externalized.out", DOCKBALE_RESTORE);
        control.getController().getTexts().put(Priority.CLIENT, "maximize_externalized.out", DOCKBALE_RESTORE);
        control.getController().getTexts().put(Priority.CLIENT, "preference.shortcut.externalize.label", DOCKBALE_DETACH);
        control.setTheme(ThemeMap.KEY_ECLIPSE_THEME);
        
        control.setRootWindow(new DirectWindowProvider(null));
        
        JPanel navigationPanel = new JPanel();
        navigationPanel.setLayout(new MigLayout("fill, insets 0"));
        
        JPanel consolePanel = new JPanel();
        consolePanel.setLayout(new MigLayout("fill, insets 0 0 0 0"));
        
        DefaultSingleCDockable dockable = new DefaultSingleCDockable("console_dockable", consolePanel);
        grid.add(0, 50, 50, 15, dockable);
        dockable.setMinimizable(false);
        dockable.setMaximizable(false);
        dockable.setCloseable(false);
        dockable.setExternalizable(false);
        dockable.setTitleText("Console");
        dockable.setTitleToolTip(null);
        dockable.setTitleIcon(null);
        contentArea.deploy(grid);
        
        
        DefaultSingleCDockable navigationDockable = new DefaultSingleCDockable("navigation_dockable", navigationPanel);
        grid.add(0, 11, 2, 40, navigationDockable);
        navigationDockable.setMinimizable(true);
        navigationDockable.setMaximizable(true);
        navigationDockable.setCloseable(false);
        navigationDockable.setExternalizable(false);
        navigationDockable.setTitleText("Navigation");
        navigationDockable.setTitleToolTip(null);
        navigationDockable.setTitleIcon(null);
        contentArea.deploy(grid);
        
        CStack screensStack = new CStack("screens");
        screensStack.setHideIfEmpty(false);
        control.addStation(screensStack, true);
        
        final JPanel initialScreen = new JPanel();
        initialScreen.setLayout(new MigLayout("fill"));
        NativeInterface.open();
        SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JWebBrowser webBrowser = new JWebBrowser(JWebBrowser.destroyOnFinalization());
                    initialScreen.add(webBrowser, "grow");
                    webBrowser.navigate("www.google.com");
                   
                }
            });
        NativeInterface.runEventPump();
		
		DefaultSingleCDockable initialScreenDockable = new DefaultSingleCDockable("child_1", initialScreen);
		initialScreenDockable.setMinimizable(false);
		initialScreenDockable.setMaximizable(true);
		initialScreenDockable.setExternalizable(true);
		initialScreenDockable.setCloseable(true);
		initialScreenDockable.setTitleToolTip(null);
		initialScreenDockable.setTitleText("Title");
		initialScreenDockable.putAction(CDockable.ACTION_KEY_CLOSE, new CCloseAction(control) {
			@Override
			public void close( CDockable dockable ){
				super.close(dockable);
				control.remove(dockable.asStation());
			}
		});
        control.addDockable(initialScreenDockable);
        screensStack.getStation().add(initialScreenDockable.intern(), 0);
        dockable.setVisible(true);
        
        grid.add(40, 11, 48, 40, screensStack);
        contentArea.deploy(grid);
        
        rootPanel.add(contentArea, "grow, cell 0 0");
        JFrame frame = new JFrame();
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(800, 800);
        frame.setLayout(new MigLayout("fill, insets 0 0 0 0", "[fill, grow]", "[fill, grow]"));
        frame.add(rootPanel, "grow");
        control.setRootWindow(new DirectWindowProvider(frame));
        frame.doLayout();
        frame.setVisible(true);
	}
	
	public static void main(String[] args) {
		new ExampleWithDocking();
	}
}```


```import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.intern.AbstractDockableCStation;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.mode.CNormalModeArea;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.perspective.CStationPerspective;
import bibliothek.gui.dock.facile.mode.Location;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.ModeAreaListener;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.support.mode.AffectedSet;
import bibliothek.gui.dock.util.DockUtilities;

import bibliothek.util.Path;


public class CStack extends AbstractDockableCStation<StackDockStation> implements CNormalModeArea, SingleCDockable {
    private boolean hideIfEmpty;


    public CStack(String id) {
        CStackDockStation delegate = new CStackDockStation(this);
        CLocation stationLocation = new CLocation() {
            @Override
            public CLocation getParent() {
                return null;
            }

            @Override
            public String findRoot() {
                return getUniqueId();
            }

            @Override
            public DockableProperty findProperty(DockableProperty successor) {
                return successor;
            }

            @Override
            public ExtendedMode findMode() {
                return ExtendedMode.NORMALIZED;
            }

            @Override
            public CLocation aside() {
                return this;
            }
        };
        init(delegate, id, stationLocation, delegate);
    }


    public void setHideIfEmpty(boolean hideIfEmpty) {
        this.hideIfEmpty = hideIfEmpty;
    }

    @Override
    public CStationPerspective createPerspective() {
        /* For this example we do not support perspectives. */
        throw new IllegalStateException("not implemented");
    }

    @Override
    public boolean isNormalModeChild(Dockable dockable) {
        return isChild(dockable);
    }

    @Override
    public DockableProperty getLocation(Dockable child) {
        return DockUtilities.getPropertyChain(getStation(), child);
    }

    @Override
    public void setLocation(Dockable dockable, DockableProperty location, AffectedSet set) {
        set.add(dockable);
        if (isChild(dockable)) {
            getStation().move(dockable, location);
        } else {
            if (!getStation().drop(dockable, location)) {
                getStation().drop(dockable);
            }
        }
    }

    @Override
    public void addModeAreaListener(ModeAreaListener listener) {
        // not required
    }

    @Override
    public Path getTypeId() {
        // not required
        return null;
    }

    @Override
    public boolean autoDefaultArea() {
        return true;
    }

    @Override
    public boolean isChild(Dockable dockable) {
        return dockable.getDockParent() == getStation();
    }

    @Override
    public void removeModeAreaListener(ModeAreaListener listener) {
        // not required
    }

    @Override
    public void setController(DockController controller) {
        // ignore
    }

    @Override
    public void setMode(LocationMode mode) {
        // ignore
    }

    @Override
    public CLocation getCLocation(Dockable dockable) {
        DockableProperty property = DockUtilities.getPropertyChain(getStation(), dockable);
        return getStationLocation().expandProperty(property);
    }

    @Override
    public CLocation getCLocation(Dockable dockable, Location location) {
        DockableProperty property = location.getLocation();
        if (property == null) {
            return getStationLocation();
        }
        return getStationLocation().expandProperty(property);
    }

    @Override
    public boolean respectWorkingAreas() {
        return false;
    }

    @Override
    public boolean isCloseable() {
        return false;
    }

    @Override
    public boolean isExternalizable() {
        return false;
    }

    @Override
    public boolean isMaximizable() {
        return false;
    }

    @Override
    public boolean isMinimizable() {
        return false;
    }

    @Override
    public boolean isStackable() {
        return false;
    }

    @Override
    public boolean isWorkingArea() {
        return false;
    }

    public boolean hideIfEmpty() {
        return hideIfEmpty;
    }

    public DockActionSource[] getSources() {
        return new DockActionSource[] { getClose() };
    }

    /* This method is called by the CControl and allows access to some inner API that is
     * * * hidden from normal clients. */
    @Override
    protected void install(CControlAccess access) {
        access.getLocationManager().getNormalMode().add(this);
    }

    @Override
    protected void uninstall(CControlAccess access) {
        access.getLocationManager().getNormalMode().remove(getUniqueId());
    }
}
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.station.CommonDockStation;
import bibliothek.gui.dock.event.DockStationAdapter;
import bibliothek.gui.dock.util.DockUtilities;

public class CStackDockStation extends StackDockStation implements CommonDockStation<StackDockStation, CStackDockStation>, CommonDockable {

    private CStack delegate;


    public CStackDockStation(CStack stack) {
        this.delegate = stack;
        final Runnable makeVisible = new Runnable() {
            @Override
            public void run() {
                delegate.setVisible(true);
            }
        };
        DockUtilities.disableCheckLayoutLocked();
        addDockStationListener(new DockStationAdapter() {
                @Override
                public void dockableAdded(DockStation station, Dockable dockable) {
                    DockController controller = delegate.getControl().getOwner().getController();
                    controller.getHierarchyLock().onRelease(makeVisible);
                }
            });
    }


    @Override
    public CDockable getDockable() {
        return delegate;
    }

    @Override
    public DockActionSource[] getSources() {
        return delegate.getSources();
    }

    @Override
    public CStation<StackDockStation> getStation() {
        return delegate;
    }

    @Override
    public StackDockStation getDockStation() {
        return this;
    }

    @Override
    public CStackDockStation asDockStation() {
        return this;
    }

    @Override
    public CommonDockable asDockable() {
        return this;
    }
}

Thx

I could imagine that the JWebBrowser gets confused by the invisible JComponents that DockingFrames puts over all Dockables (most like the JWebBrowser does not handle the word invisible in “invisible JComponent” well).

I have to install the JWebBrowser for myself to test this theory. That will take some time (probably until the weekend). If you know some flags that “optimize” the painting of JWebBrowser I would first try to disable them.

Well, as you can see in the screenshot below, I did not have any issues. Tested on Ubuntu 64 Bit, Java 1.6. I have radically shortened your code, so I might have deleted the code that created the issue. But before I start a long search:

  • Could you please run the code below on your machine and tell me what happens? Does the browser show up or not?
  • And please test and confirm that an application not using DockingFrames does show the browser.
  • Is there anything special with your system? JVM, OS, …


import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.util.DirectWindowProvider;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;

public class WebBrowserTest {
	public static void main( String[] args ){
		new WebBrowserTest();
	}

	public WebBrowserTest(){
		final CControl control = new CControl();
		control.setTheme( ThemeMap.KEY_ECLIPSE_THEME );
		control.getContentArea(); // lazy initialization

		CGrid grid = new CGrid( control );

		control.setRootWindow( new DirectWindowProvider( null ) );

		final DefaultSingleCDockable initialScreenDockable = new DefaultSingleCDockable( "child_1" );
		initialScreenDockable.setMinimizable( false );
		initialScreenDockable.setMaximizable( true );
		initialScreenDockable.setExternalizable( true );
		initialScreenDockable.setCloseable( true );
		initialScreenDockable.setTitleToolTip( null );
		initialScreenDockable.setTitleText( "Title" );

		control.addDockable( initialScreenDockable );
		initialScreenDockable.setVisible( true );

		JFrame frame = new JFrame();
		frame.setResizable( true );
		frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
		frame.setSize( 800, 800 );
		frame.add( control.getContentArea() );
		control.setRootWindow( new DirectWindowProvider( frame ) );
		frame.doLayout();
		frame.setVisible( true );

		NativeInterface.open();
		SwingUtilities.invokeLater( new Runnable(){
			@Override
			public void run(){
				JWebBrowser webBrowser = new JWebBrowser( JWebBrowser.destroyOnFinalization() );
				initialScreenDockable.add( webBrowser );
				webBrowser.navigate( "www.google.com" );

			}
		} );
		NativeInterface.runEventPump();
	}
}```

Hi,

Could you please run the code below on your machine and tell me what happens? Does the browser show up or not?

The browser with latest example you provided doesn’t sow up on my machine

And please test and confirm that an application not using DockingFrames does show the browser.

Yes I confirm. I did an example without docking frames and it is showing. Check code below

import javax.swing.SwingUtilities;

import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
 
public class WebBrowserTest {
	private JFrame frame;
    public static void main( String[] args ){
        new WebBrowserTest();
    }
 
    public WebBrowserTest(){
    	NativeInterface.open();
        frame = new JFrame();
        frame.setResizable( true );
        frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
        frame.setSize( 800, 800 );
        frame.doLayout();
        frame.setVisible( true );
     
        SwingUtilities.invokeLater( new Runnable(){
            @Override
            public void run(){
            	JWebBrowser webBrowser = new JWebBrowser( JWebBrowser.destroyOnFinalization());
                frame.getContentPane().add(webBrowser);
            	webBrowser.navigate( "www.google.com" );
 
            }
        } );
       
        NativeInterface.runEventPump();
    }
}```


> Is there anything special with your system? JVM, OS, ...

OS = "Microsoft Windows XP Professional" and JDK version 1.6.18



Thx

I just tried the code on a Win XP with JDK 1.6.22, it works well. So I guess the next step would be to update the JDK? I’ll do some google-searching later (I’m currently at the office…), perhaps this is a known bug of the JDK itself (I’m not the only one using glass-panes, it’s a well established technique).

Hi,

I upgrade to jdk1.6.0_22 and unfortunately I’m still not able to see the web browser :frowning:
You can check the attached image to see what I’m getting

Thx

Hi,

I just noticed the following post:
http://forum.byte-welt.de/showthread.php?t=2367&highlight=WebBrowser

Could it be something related to the above post?

Thx

I do not think the issues are related. The other issue was about MouseEvents that were not delivered correctly. That does not have to do anything with painting stuff.

Maybe this helps? Setting “-Dsun.awt.disableMixing=true”? But I don’t know if there are unwanted side effects with that option.

I suggest the following: I think the client below should produce the error on your machine, cutting off half the browser. It is independent from DockingFrames. Copy it, paste it on djproject and ask if they have an idea. Since you are the one that can tell whether a solution works or not, it is better if you ask.

I do not say that there is a bug in JWebBrowser, but I would not know how else to implement a Glass-Pane.

P.S. if it can’t compile, then you are using a too old JDK.


import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;

public class GlassPaneTest {
	private JFrame frame;
	private JPanel panel;
	private JWebBrowser browser;
	private JPanel glassPane;
	
	public static void main( String[] args ){
		GlassPaneTest test = new GlassPaneTest();
		test.setupFrame();
		test.setupBrowser();
		test.setupGlassPane();
		
		test.frame.setVisible( true );
		NativeInterface.runEventPump();
	}
	
	public void setupFrame(){
		frame = new JFrame();
		panel = new JPanel(){
			@Override
			public void doLayout(){
				if( browser != null ){
					browser.setBounds( 0, 0, getWidth(), getHeight() );
				}
				if( glassPane != null ){
					glassPane.setBounds( 0, 0, getWidth()/2, getHeight() );
				}
			}
		};
		
        frame.setSize( 800, 800 );
        frame.setLayout( new BorderLayout() );
        frame.add( panel, BorderLayout.CENTER );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
	}
	
	public void setupBrowser(){
        NativeInterface.open();
        SwingUtilities.invokeLater( new Runnable(){
            @Override
            public void run(){
                browser = new JWebBrowser( JWebBrowser.destroyOnFinalization() );
                panel.add( browser, JLayeredPane.DEFAULT_LAYER );
                browser.navigate( "www.google.com" );
            }
        });
	}
	
	public void setupGlassPane(){
		glassPane = new JPanel(){
			@Override
			protected void paintComponent( Graphics g ){
				g.setColor( Color.BLUE );
				Graphics2D g2 = (Graphics2D)g;
				g2.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_IN, 0.5f ) );
				g.fillRect( 0, 0, getWidth(), getHeight() );
			}
		};
		glassPane.setOpaque( false );

		// Swing + AWT + Transparency = using inofficial methods... 
		com.sun.awt.AWTUtilities.setComponentMixingCutoutShape( glassPane, new Rectangle() );
		panel.add( glassPane );
	}
}