Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 120020

Summary: multiple Display does not work on Linux
Product: [Eclipse Project] Platform Reporter: cole harris <coharris>
Component: SWTAssignee: Bogdan Gheorghe <gheorghe>
Status: CLOSED WORKSFORME QA Contact:
Severity: major    
Priority: P3 CC: billy.biggs, carolynmacleod4, cocoakevin, csyperski, ericwill, fxu, pinnamur, rafaelkarst, remy.suen, tomasz.zarna
Version: 3.1Keywords: triaged
Target Milestone: ---   
Hardware: All   
OS: Linux-GTK   
Whiteboard:

Description cole harris CLA 2005-12-08 17:27:26 EST
I recently upgraded to SWT 3.1 and it no longer supports multiple displays in Linux.  My program creates a splash screen with a progress bar that updates as the main application launches.  To fix the multiple display issue I pass the main UI display to the splash screen class to use.  The issue arises in that I must create a separate thread to run the splash screen while the main app loads.  SWT/UI calls can not be made in any thread except the main UI thread which is running.  This is an easy fix using the call ‘display.asyncExec()’, however this seems to queue its newly created thread and only runs it after the main app is finished loading.  I have been mucking around with this and scanning the internet for a few days with no luck.  Has anyone experienced any similar issues?  Thanks   

Further more the attached code works on windows and gives a multiple display error on Linux
-Cole 

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;

import com.enterasys.dragon.ems.client.ui.Util;
import com.swtdesigner.ResourceManager;
import com.swtdesigner.SWTResourceManager;

public class SplashScreen extends Dialog implements Splash , Runnable{
	Thread T;
	public ProgressBar progressBar;
	public Display display;
	public SplashScreen(Shell parent) {
		super(parent);
		T = new Thread(this);
		T.start();
		
	}

	public void run() 
	{
		final Image image;
		Display display = new Display();
		final Shell dragonStartupScreenShell = new Shell(display, SWT.NO_TRIM);
		dragonStartupScreenShell.setText("Dragon Startup Screen");
		dragonStartupScreenShell.setImage(SWTResourceManager.getImage(SplashScreen.class, "/images/enterasysLogo.gif"));
		
		dragonStartupScreenShell.setSize(445, 287);
		dragonStartupScreenShell.setBackground(new Color(display,255,255,255));

//		 Center the splash screen
		Rectangle splashRect = dragonStartupScreenShell.getBounds();
		Rectangle displayRect = display.getMonitors()[0].getBounds();
		int x = (displayRect.width - splashRect.width) / 2;
		int y = (displayRect.height - splashRect.height) / 2;
		dragonStartupScreenShell.setLocation(x, y);
		
		Label label = new Label(dragonStartupScreenShell, SWT.None);
		label.setBounds(4, -6, 440, 280);
		image = new Image(display, 470, 310);
		label.setImage(ResourceManager.getImage(this.getClass(),"/images/Dragon_Splash470x265.jpg"));
		
		final Button _Button = new Button(dragonStartupScreenShell, SWT.NONE);
		_Button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) 
			{
				dragonStartupScreenShell.setMinimized(true);
			}
		});
		_Button.setFont(SWTResourceManager.getFont("Wide Latin", 10, SWT.BOLD));
		_Button.moveAbove(label);
		_Button.setText("-");
		_Button.setBounds(428, 1, 16, 13);

		T.setPriority(9);
		final ProgressBar progressBar = new ProgressBar(dragonStartupScreenShell, SWT.NONE);
		progressBar.setBounds(8, 270, 431, 15);
		progressBar.setMinimum(0);
		progressBar.setMaximum(100);
		progressBar.moveAbove(null);
		this.progressBar = progressBar; 
		this.display = display;
		dragonStartupScreenShell.open();
		while(!dragonStartupScreenShell.isDisposed())
		{
			if(!display.readAndDispatch())
			{
				display.sleep();
				progressBar.setSelection(PB);
				// Once PB equals 100 dispose screen bc Dragon is loaded.
				if (PB == 100)
				{
					dragonStartupScreenShell.dispose();
					image.dispose();
					label.dispose();
				}
			}
		}
	}
	
	public int PB;
	public void setProgress(int progress)
	{
		PB = progress;	
		//  display.wake is needed to retore focus control to SPlashScreen Thread once finished
		//  so it may destroy correctly.  However it is not needed nor handled in !windows
		if(Util.isWindowsOS())
		{
			display.wake();
		}
	}

}
Comment 1 David Michonneau CLA 2005-12-15 10:42:14 EST
*** Bug 121021 has been marked as a duplicate of this bug. ***
Comment 2 Billy Biggs CLA 2006-01-02 12:18:43 EST
Multiple displays are not yet supported under Linux, see bug 93294.  I
would just mark this as a duplicate but I really don't think you need
multiple displays to solve your problem.

Runnables passed to Display.asyncExec() are run on the UI thread when
running the event loop. You should be spinning events during your
startup sequence using Display.readAndDispatch().
Comment 3 cole harris CLA 2006-01-03 17:55:50 EST
Since multiple displays are not supported on Linux, If I want to run a splash screen off of a new thread I must then use the current main UI display.  This is where I am a bit confused… Are you saying that I should be running the splash screen from my main UI Thread within the readAndDispatch call?  I thought a simple asynchronous thread loop would run OK… but it never jumps into the loop when called from the passed in display.  Am I making sense?  I appreciate the help Bill.  Thank you 

 

-Cole


We should talk in the bug report.

I guess what I was saying is that there is one UI thread, and all UI work should happen there.  If you have another thread that's doing work, it can communicate back to the UI thread using async/syncExec.

-Billy


Bill,

I understand that all UI calls must be made from the same UI thread.  If I was to have a seperate thread running and want to make a UI call then I should simply be able to make a Display.aSyncExec() call which should run that thread using the main UI display.  My problem arises when I make that call it does not run aSyncrounsly.  My splash screen thread (which should be running async) is not kicked off until the Main thread has finished working. 

I tried a few hackish fixes like yielding and forcing my threads but with no luck.  Thanks once again.

-cole
Comment 4 Steve Northover CLA 2009-05-01 11:25:16 EDT
*** Bug 274639 has been marked as a duplicate of this bug. ***
Comment 5 Carolyn MacLeod CLA 2009-05-12 14:08:12 EDT
I am not sure if this helps, but Snippet104 shows how to create a splash screen in the UI thread.

http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet104.java
Comment 6 Felipe Heidrich CLA 2009-06-10 16:51:09 EDT
*** Bug 279865 has been marked as a duplicate of this bug. ***
Comment 7 Eric Williams CLA 2018-08-30 14:45:40 EDT
Seems this ticket is not relevant anymore, closing.