Sometimes we want to give the user a little feedback. "Saved!", "Please wait...", "Loading..", without having to resort to those bulky dialogs. 
For these use cases, we have invented MiniMessage. MM can display a small message at the current mouse pointer or above a specific control. 
Just paste the source code below into a UI project package and run as java application. It would be nice if this would make it into Nebula
It would be nice if the message box could be round/square/balloon/closable, etc..
Let me know what you think.
/*******************************************************************************
 * Copyright (c) 2021 Remain Software -  
http://remainsoftware.com * All rights reserved. This program is made available under the terms
 * of the Eclipse Public License v1.0 which does not accompanies this
 * distribution but is available at 
http://www.eclipse.org/legal/epl-v10.html *
 * Contributors:
 *     Wim Jongman - Initial Impl
 *******************************************************************************/
package com.remainsoftware.common.licensing.util;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
/**
 * Shows a mini message for those cases when you want to supply a quick feedback
 * to the user without going through the workflow of showing a dialog and
 * letting the user press Ok.
 * <p/>
 * Usage:
 * <p/>
 * <code>
 * // Show mini message just above cursor position
 * MiniMessage.get(2000).open("Saved!");
 * // Show mini message just above this control
 * MiniMessage(2000).get(1000).above(Control).open("Saved!");
 * </code>
 *
 * @author Wim Jongman
 *
 */
public class MiniMessage {	
	public static void main(String[] args) {
		Display display = new Display();
		MiniMessage.get(2000).openWait("Hello, World!");
		display.dispose();
	}
	/** Error message */
	public static final String ERROR = "E";
	/** Info message (default) */
	public static final String INFO = "I";
	/** Warning message */
	public static final String WARNING = "W";
	private StyledText fStyledText;
	private Shell fShell;
	private int fWaitBeforeFade = 0;
	private Control fControl;
	private String fType = INFO;
	/**
	 * Constructs a {@link MiniMessage}.
	 *
	 * @param waitBeforeFade waits n milliseconds before the message starts to fade.
	 *                       Fading itself takes about a second.
	 */
	private MiniMessage(int waitBeforeFade) {
		this.fWaitBeforeFade = waitBeforeFade;
	}
	/**
	 * Factory method to get a new MiniMessage.
	 *
	 * @param pWaitBeforeFade
	 * @return
	 */
	public static MiniMessage get(int pWaitBeforeFade) {
		return new MiniMessage(pWaitBeforeFade);
	}
	public MiniMessage above(Control pControl) {
		this.fControl = pControl;
		return this;
	}
	/**
	 * Opens the {@link MiniMessage} just above the current cursor position showing
	 * the passed text. It does not wait until the message has faded.
	 *
	 * @param text the text to show as the mini message.
	 *
	 * @see #openWait(String)
	 */
	public void openWait(String message) {
		doOpen(message, true);
	}
	/**
	 * Submits the mini message to the UI queue so that it is processed at the next
	 * convenience. Use this is you want to show some message after for example the
	 * createPartControl method in a view has finished.
	 * 
	 * Must be called from the UI thread.
	 *
	 * @param text the text to show as the mini message.
	 *
	 * @see #open(String)
	 * @see #openWait(String)
	 */
	public void submit(final String text) {
		Runnable runner = () -> doOpen(text, false);
		Display.getCurrent().asyncExec(runner);
	}
	/**
	 * Opens the {@link MiniMessage} just above the current cursor position showing
	 * the passed text. It does not wait until the message has faded.
	 *
	 * @param text the text to show as the mini message.
	 *
	 * @see #openWait(String)
	 */
	public void open(String text) {
		doOpen(text, false);
	}
	private void doOpen(String text, boolean wait) {
		try {
			Display display = Display.getDefault();
			fShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP | SWT.NO_FOCUS);
			GridLayout gridLayout = new GridLayout(1, false);
			gridLayout.marginWidth = 1;
			gridLayout.marginHeight = 1;
			gridLayout.verticalSpacing = 0;
			gridLayout.horizontalSpacing = 0;
			createContents(fShell, SWT.NONE);
			setText(text);
			Control focusControl = display.getFocusControl();
			fShell.setLayout(gridLayout);
			fShell.pack();
			fShell.setLocation(getLocation());
			fShell.open();
			fShell.layout();
			if (focusControl != null) {
				focusControl.forceFocus();
			}
			Thread thread = new Thread(new Fader(fWaitBeforeFade));
			thread.run();
			while (wait && !fShell.isDisposed()) {
				if (!display.readAndDispatch()) {
					display.sleep();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private Point getLocation() {
		if (fControl == null || fControl.isDisposed() || fControl.getParent() == null) {
			Display display = Display.getDefault();
			return display.getCursorLocation();
		}
		return fControl.getParent().toDisplay(
				fControl.getLocation().x + (fControl.getSize().x / 2) - (fShell.getSize().x / 2),
				fControl.getLocation().y - fControl.getSize().y - 10);
	}
	private void setText(String string) {
		fStyledText.setText(string);
	}
	/**
	 * Create the composite.
	 *
	 * @param parent
	 * @param style
	 */
	private void createContents(Composite parent, int style) {
		GridLayout gridLayout = new GridLayout();
		gridLayout.marginWidth = 9;
		gridLayout.marginHeight = 9;
		parent.setLayout(gridLayout);
		fStyledText = new StyledText(parent, SWT.BORDER);
		fStyledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		fStyledText.setEditable(false);
		fStyledText.setEnabled(false);
		if (ERROR.equals(fType)) {
			fStyledText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
			fStyledText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		}
		if (WARNING.equals(fType)) {
			fStyledText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
			fStyledText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		} else {
			fStyledText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN));
			fStyledText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		}
	}
	private class Fader implements Runnable {
		int fAlpha = 255;
		private int fTimerWait = 10;
		private int fWaitBeforeFade = 0;
		public Fader(int waitBeforeFade) {
			this.fWaitBeforeFade = waitBeforeFade;
		}
		@Override
		public void run() {
			if (fWaitBeforeFade > 0) {
				fShell.getDisplay().timerExec(fWaitBeforeFade, this);
				fWaitBeforeFade = 0;
			} else if (fAlpha <= 5) {
				fShell.dispose();
			} else {
				fAlpha -= 5;
				if (fAlpha < 255) {
					fShell.setAlpha(fAlpha);
				}
				fShell.getDisplay().timerExec(fTimerWait, this);
			}
		}
	}
	/**
	 * Sets the type. If the type is not any of the valid values then
	 * {@link MiniMessage#INFO} will be assumed.
	 * 
	 * @param pType
	 * @return this object for chaining
	 * 
	 * @see #ERROR
	 * @see #WARNING
	 * @see #INFO
	 */
	public MiniMessage setType(String pType) {
		fType = pType;
		return this;
	}
}