Bugzilla – Attachment 106 Details for
Bug 316
Multi-Head issues, identical to issue 241
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
Log In
[x]
|
Forgot Password
Login:
[x]
Demo that illustrates TwinView error
JOGLWithNVidiaTwinView.java (text/plain), 11.96 KB, created by
Sven Gothel
on 2007-09-07 10:31:00 CEST
(
hide
)
Description:
Demo that illustrates TwinView error
Filename:
MIME Type:
Creator:
Sven Gothel
Created:
2007-09-07 10:31:00 CEST
Size:
11.96 KB
patch
obsolete
>import java.awt.EventQueue; >import java.awt.GraphicsDevice; >import java.awt.GraphicsEnvironment; >import java.awt.Rectangle; >import java.awt.event.ComponentAdapter; >import java.awt.event.ComponentEvent; >import java.awt.event.ComponentListener; >import java.awt.event.ContainerAdapter; >import java.awt.event.ContainerEvent; >import java.awt.event.ContainerListener; >import java.awt.event.WindowAdapter; >import java.awt.event.WindowEvent; >import java.awt.event.WindowListener; > >import javax.media.opengl.GLCanvas; >import javax.swing.JFrame; > >/** > * Class to exhibit issue with JOGL on Linux/Xorg/NVidia/TwinView. > * > * This will cause an IllegalArgumentException to be thrown when adding a GLCanvas to > * a JFrame (the JFrame's content pane): > * > * java.lang.IllegalArgumentException: adding a container to a container on a different GraphicsDevice > at java.awt.Component.checkGD(Component.java:965) > at java.awt.Container.addImpl(Container.java:1027) > at java.awt.Container.add(Container.java:352) > at JOGLWithNVidiaTwinView$2.run(JOGLWithNVidiaTwinView.java:88) > at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) > at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) > at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273) > at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) > at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173) > at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) > at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) > at java.awt.EventDispatchThread.run(EventDispatchThread.java:121) > */ >public class JOGLWithNVidiaTwinView { > > /** > * @param args Not used > */ > public static void main(String[] args) { > final XScreenDevice[] twinViewPair = XScreenDevice.findTwinViewScreens(); > if (twinViewPair == null) { > System.out.println("No TwinView screen pair was found, exiting."); > System.exit(1); > } > > /* > * Create a new Window on one head. > */ > final JFrame frame = new JFrame(twinViewPair[0].device.getDefaultConfiguration()); > frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); > frame.setSize(200, 200); > /* > * Set the frame visible. We will wait until the window is opened before > * moving it. > */ > try { > openAndWait(frame); > > System.out.println("Frame is on device with ID: " > + frame.getGraphicsConfiguration().getDevice().getIDstring()); > System.out.flush(); > addCanvas(frame); > > System.out.println("Moving window to second device..."); > System.out.flush(); > /* > * Get the bounds of the second device and move the frame there. > */ > final Rectangle secondDeviceBounds = twinViewPair[1].device.getDefaultConfiguration().getBounds(); > > moveTo(frame, secondDeviceBounds); > > System.out.println("Frame is on device with ID: " > + frame.getGraphicsConfiguration().getDevice().getIDstring()); > System.out.println("Adding GLCanvas..."); > System.out.flush(); > addCanvas(frame); > } catch (InterruptedException ie) { > System.out.println("Interrupted..."); > } > } > > /** > * Creates and adds a new GLCanvas to the specified JFrame, blocking > * until the operation is complete (do not call this from the Event Thread) > * > * @param frame > * @throws InterruptedException > */ > static void addCanvas(final JFrame frame) throws InterruptedException { > final boolean[] added = new boolean[] { false }; > final GLCanvas canvas = new GLCanvas(); > final ContainerListener listener = new ContainerAdapter() { > > @Override > public void componentAdded(ContainerEvent e) { > if (e.getComponent() == canvas) { > synchronized (added) { > added[0] = true; > added.notifyAll(); > } > } > } > > }; > EventQueue.invokeLater(new Runnable() { > > public void run() { > final GLCanvas canvas = new GLCanvas(); > try { > frame.getContentPane().add(canvas); > } catch (IllegalArgumentException iae) { > System.out.println("Caught exception while adding canvas: "); > System.out.flush(); > iae.printStackTrace(); > } > } > }); > try { > synchronized (added) { > while (!added[0]) > added.wait(); > } > } finally { > frame.removeContainerListener(listener); > } > } > > /** > * Moves the specified frame somewhere (top-left corner) of the specified rectangle, blocking until > * the operation is complete (do not call this from the Event Thread). > * > * @param frame > * @param target > * @throws InterruptedException > */ > static void moveTo(final JFrame frame, final Rectangle target) throws InterruptedException { > final boolean[] moved = new boolean[] { target.contains(frame.getX(), frame.getY(), frame.getWidth(), frame > .getHeight()) }; > final ComponentListener listener = new ComponentAdapter() { > > public void componentMoved(ComponentEvent e) { > synchronized (moved) { > if (moved[0] = target.contains(frame.getX(), frame.getY(), frame.getWidth(), frame.getHeight())) { > moved.notifyAll(); > System.out.println("Moved to: " + frame.getX() + ", " + frame.getY()); > } else { > System.out.println("Moved somewhere unexpected: " + frame.getX() + ", " + frame.getY()); > } > } > } > }; > frame.addComponentListener(listener); > EventQueue.invokeLater(new Runnable() { > > public void run() { > frame.setLocation(target.x, target.y); > } > }); > try { > synchronized (moved) { > while (!moved[0]) > moved.wait(); > } > } finally { > frame.removeComponentListener(listener); > } > } > > /** > * Sets the specified frame visible and waits for a corresponding WindowEvent. > * Do not call from Event Thread. > * > * @param frame > * @throws InterruptedException > */ > static void openAndWait(JFrame frame) throws InterruptedException { > final boolean[] open = new boolean[] { frame.isVisible() }; > final WindowListener listener = new WindowAdapter() { > > public void windowOpened(WindowEvent e) { > synchronized (open) { > open[0] = true; > open.notifyAll(); > } > } > }; > frame.addWindowListener(listener); > frame.setVisible(true); > try { > synchronized (open) { > while (!open[0]) > open.wait(); > } > } finally { > frame.removeWindowListener(listener); > } > } > > /** > * Class to extract some (Unix, or possible Linux-specific) > * info from a GraphicsDevice instance's idString. > */ > static class XScreenDevice { > > public final GraphicsDevice device; > public final String hostName; > public final String serverID; > public final String displayID; > > public XScreenDevice(GraphicsDevice device) { > this.device = device; > String idStr = device.getIDstring(); > > final int colonIdx = idStr.indexOf(':'); > if (colonIdx < 0) { > throw new IllegalArgumentException("The specified device (id: " + idStr > + ") does not appear to be an X screen device."); > } > hostName = idStr.substring(0, colonIdx); > > idStr = idStr.substring(colonIdx + 1); > final int dotIdx = idStr.indexOf('.'); > if (dotIdx < 0) { > displayID = ""; > serverID = idStr; > } else { > serverID = idStr.substring(0, dotIdx); > displayID = idStr.substring(dotIdx + 1); > } > } > > /** > * Checks whether the specified device might be involved in a TwinView > * configuration with this device. This means that the hostNames and > * serverIDs must be identical, and the displayID and device must be > * different. > * > * @param device A non-null XScreenDevice. > * @return <code>true</code> if the specified device is (probably) in > * a TwinView configuration with this device, false otherwise. > */ > public boolean isTwinViewComplement(XScreenDevice device) { > return device.device != this.device && device.hostName.equals(this.hostName) > && device.hostName.equals(this.hostName) && !device.displayID.equals(this.displayID); > } > > public String toString() { > return "X Screen Device -- id: " + device.getIDstring() + " (host=" + hostName + ", serverID=" + serverID > + ", displayID=" + displayID + ")"; > } > > /** > * Identifies a pair of TwinView screens in the local graphics > * environment. A TwinView pair (for the purposes of this method) has X > * display IDs comprised of identical hostnames, followed by a colon, > * identical server ids, followed by a '.', and unique display ids. For > * example, ':0.0' and ':0.1' would be a pair. > * > * > * @return A pair of XScreenDevice instances representing two distinct > * GraphicsDevices in the local environment that are believed to > * be a TwinView pair, or null if none are found. > */ > public static XScreenDevice[] findTwinViewScreens() { > final GraphicsEnvironment graphicsEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); > final GraphicsDevice[] screenDevices = graphicsEnv.getScreenDevices(); > if (screenDevices == null || screenDevices.length < 2) { > /* > * Not enough devices for a TwinView pair. > */ > return null; > } > for (int firstScreenIdx = 1; firstScreenIdx < screenDevices.length; firstScreenIdx++) { > final XScreenDevice firstDevice; > try { > firstDevice = new XScreenDevice(screenDevices[firstScreenIdx]); > System.out.println("Searching for TwinView complement to: " + firstDevice); > } catch (IllegalArgumentException iae) { > System.out.println("Device: " + screenDevices[firstScreenIdx].getIDstring() > + " does not appear to be an X screen"); > continue; > } > > for (int secondScreenIdx = firstScreenIdx - 1; secondScreenIdx >= 0; secondScreenIdx--) { > try { > final XScreenDevice secondDevice = new XScreenDevice(screenDevices[secondScreenIdx]); > System.out.println("\tTesting: " + secondDevice); > if (firstDevice.isTwinViewComplement(secondDevice)) { > System.out.println("TwinView Pair Identified!"); > return new XScreenDevice[] { firstDevice, secondDevice }; > } > } catch (IllegalArgumentException iae) { > /* > * Already warned above... > */ > } > } > } > /* > * None found. > */ > return null; > } > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 316
: 106 |
107