LWToolkit.java revision 4639
3013N/A/*
3793N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3013N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3013N/A *
3013N/A * This code is free software; you can redistribute it and/or modify it
3013N/A * under the terms of the GNU General Public License version 2 only, as
3013N/A * published by the Free Software Foundation. Oracle designates this
3013N/A * particular file as subject to the "Classpath" exception as provided
3013N/A * by Oracle in the LICENSE file that accompanied this code.
3013N/A *
3013N/A * This code is distributed in the hope that it will be useful, but WITHOUT
3013N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3013N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3013N/A * version 2 for more details (a copy is included in the LICENSE file that
3013N/A * accompanied this code).
3013N/A *
3013N/A * You should have received a copy of the GNU General Public License version
3013N/A * 2 along with this work; if not, write to the Free Software Foundation,
3013N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3013N/A *
3013N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3013N/A * or visit www.oracle.com if you need additional information or have any
3013N/A * questions.
3013N/A */
3013N/A
3013N/Apackage sun.lwawt;
3013N/A
3013N/Aimport java.awt.*;
3793N/Aimport java.awt.List;
3013N/Aimport java.awt.datatransfer.*;
3013N/Aimport java.awt.dnd.*;
3013N/Aimport java.awt.dnd.peer.*;
3013N/Aimport java.awt.image.*;
3793N/Aimport java.awt.peer.*;
3793N/Aimport java.security.*;
3013N/Aimport java.util.*;
3013N/A
3013N/Aimport sun.awt.*;
3793N/Aimport sun.lwawt.macosx.*;
3013N/Aimport sun.print.*;
3013N/A
3013N/Apublic abstract class LWToolkit extends SunToolkit implements Runnable {
3793N/A
3013N/A private final static int STATE_NONE = 0;
3013N/A private final static int STATE_INIT = 1;
3013N/A private final static int STATE_MESSAGELOOP = 2;
3013N/A private final static int STATE_SHUTDOWN = 3;
3013N/A private final static int STATE_CLEANUP = 4;
3013N/A private final static int STATE_DONE = 5;
3013N/A
3013N/A private int runState = STATE_NONE;
3013N/A
3013N/A private Clipboard clipboard;
3013N/A private MouseInfoPeer mouseInfoPeer;
3926N/A
3926N/A private static Map<PlatformWindow, LWWindowPeer> delegateMap =
3926N/A new HashMap<PlatformWindow, LWWindowPeer>();
3013N/A
3013N/A public LWToolkit() {
3013N/A }
3013N/A
3247N/A /*
3013N/A * This method is called by subclasses to start this toolkit
4608N/A * by launching the message loop.
3013N/A *
3013N/A * This method waits for the toolkit to be completely initialized
3013N/A * and returns before the message pump is started.
3013N/A */
3013N/A protected final void init() {
3013N/A AWTAutoShutdown.notifyToolkitThreadBusy();
3013N/A
3013N/A ThreadGroup mainTG = AccessController.doPrivileged(
3013N/A new PrivilegedAction<ThreadGroup>() {
3013N/A public ThreadGroup run() {
3013N/A ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
4608N/A ThreadGroup parentTG = currentTG.getParent();
3013N/A while (parentTG != null) {
3013N/A currentTG = parentTG;
3013N/A parentTG = currentTG.getParent();
4608N/A }
3013N/A return currentTG;
3013N/A }
3013N/A }
3013N/A );
3013N/A
3013N/A Runtime.getRuntime().addShutdownHook(
3013N/A new Thread(mainTG, new Runnable() {
4608N/A public void run() {
3013N/A shutdown();
3013N/A waitForRunState(STATE_CLEANUP);
3013N/A }
3013N/A })
3013N/A );
3013N/A
3013N/A Thread toolkitThread = new Thread(mainTG, this, "AWT-LW");
3013N/A toolkitThread.setDaemon(true);
4608N/A toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
3013N/A toolkitThread.start();
3013N/A
3013N/A waitForRunState(STATE_MESSAGELOOP);
3013N/A }
3013N/A
3013N/A /*
3013N/A * Implemented in subclasses to initialize platform-dependent
3013N/A * part of the toolkit (open X display connection, create
3926N/A * toolkit HWND, etc.)
3926N/A *
3013N/A * This method is called on the toolkit thread.
3013N/A */
3013N/A protected abstract void platformInit();
3013N/A
3013N/A /*
3013N/A * Sends a request to stop the message pump.
3013N/A */
3013N/A public void shutdown() {
3013N/A setRunState(STATE_SHUTDOWN);
3013N/A platformShutdown();
3013N/A }
3013N/A
3013N/A /*
3013N/A * Implemented in subclasses to release all the platform-
3013N/A * dependent resources. Called after the message loop is
3013N/A * terminated.
3013N/A *
3013N/A * Could be called (always called?) on a non-toolkit thread.
3013N/A */
4608N/A protected abstract void platformShutdown();
3013N/A
3013N/A /*
3013N/A * Implemented in subclasses to release all the platform
3013N/A * resources before the application is terminated.
3013N/A *
3013N/A * This method is called on the toolkit thread.
3013N/A */
3013N/A protected abstract void platformCleanup();
3013N/A
3013N/A private synchronized int getRunState() {
3013N/A return runState;
3013N/A }
3013N/A
3013N/A private synchronized void setRunState(int state) {
3013N/A runState = state;
3013N/A notifyAll();
3013N/A }
3013N/A
3013N/A public boolean isTerminating() {
3013N/A return getRunState() >= STATE_SHUTDOWN;
3013N/A }
3013N/A
3013N/A private void waitForRunState(int state) {
3013N/A while (getRunState() < state) {
3013N/A try {
3013N/A synchronized (this) {
3013N/A wait();
3013N/A }
3013N/A } catch (InterruptedException z) {
3013N/A // TODO: log
3013N/A break;
4608N/A }
4608N/A }
4608N/A }
4608N/A
3013N/A public void run() {
3013N/A setRunState(STATE_INIT);
3013N/A platformInit();
3013N/A AWTAutoShutdown.notifyToolkitThreadFree();
3013N/A setRunState(STATE_MESSAGELOOP);
while (getRunState() < STATE_SHUTDOWN) {
try {
platformRunMessage();
if (Thread.currentThread().isInterrupted()) {
if (AppContext.getAppContext().isDisposed()) {
break;
}
}
} catch (ThreadDeath td) {
//XXX: if there isn't native code on the stack, the VM just
//kills the thread right away. Do we expect to catch it
//nevertheless?
break;
} catch (Throwable t) {
// TODO: log
System.err.println("Exception on the toolkit thread");
t.printStackTrace(System.err);
}
}
//XXX: if that's a secondary loop, jump back to the STATE_MESSAGELOOP
setRunState(STATE_CLEANUP);
AWTAutoShutdown.notifyToolkitThreadFree();
platformCleanup();
setRunState(STATE_DONE);
}
/*
* Process the next message(s) from the native event queue.
*
* Initially, all the LWToolkit implementations were supposed
* to have the similar message loop sequence: check if any events
* available, peek events, wait. However, the later analysis shown
* that X11 and Windows implementations are really different, so
* let the subclasses do whatever they require.
*/
protected abstract void platformRunMessage();
public static LWToolkit getLWToolkit() {
return (LWToolkit)Toolkit.getDefaultToolkit();
}
// ---- TOPLEVEL PEERS ---- //
/*
* Note that LWWindowPeer implements WindowPeer, FramePeer
* and DialogPeer interfaces.
*/
private LWWindowPeer createDelegatedPeer(Window target, PlatformComponent platformComponent,
PlatformWindow platformWindow)
{
LWWindowPeer peer = new LWWindowPeer(target, platformComponent, platformWindow);
targetCreatedPeer(target, peer);
targetDelegate(platformWindow, peer);
peer.initialize();
return peer;
}
@Override
public WindowPeer createWindow(Window target) {
PlatformComponent platformComponent = createPlatformComponent();
PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.SIMPLEWINDOW);
return createDelegatedPeer(target, platformComponent, platformWindow);
}
@Override
public FramePeer createFrame(Frame target) {
PlatformComponent platformComponent = createPlatformComponent();
PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.FRAME);
return createDelegatedPeer(target, platformComponent, platformWindow);
}
CPrinterDialogPeer createCPrinterDialog(CPrinterDialog target) {
PlatformComponent platformComponent = createPlatformComponent();
PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.DIALOG);
CPrinterDialogPeer peer = new CPrinterDialogPeer(target, platformComponent, platformWindow);
targetCreatedPeer(target, peer);
return peer;
}
@Override
public DialogPeer createDialog(Dialog target) {
if (target instanceof CPrinterDialog) {
return createCPrinterDialog((CPrinterDialog)target);
}
PlatformComponent platformComponent = createPlatformComponent();
PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.DIALOG);
return createDelegatedPeer(target, platformComponent, platformWindow);
}
@Override
public FileDialogPeer createFileDialog(FileDialog target) {
FileDialogPeer peer = createFileDialogPeer(target);
targetCreatedPeer(target, peer);
return peer;
}
// ---- LIGHTWEIGHT COMPONENT PEERS ---- //
@Override
public ButtonPeer createButton(Button target) {
PlatformComponent platformComponent = createPlatformComponent();
LWButtonPeer peer = new LWButtonPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public CheckboxPeer createCheckbox(Checkbox target) {
PlatformComponent platformComponent = createPlatformComponent();
LWCheckboxPeer peer = new LWCheckboxPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
throw new RuntimeException("not implemented");
}
@Override
public ChoicePeer createChoice(Choice target) {
PlatformComponent platformComponent = createPlatformComponent();
LWChoicePeer peer = new LWChoicePeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public LabelPeer createLabel(Label target) {
PlatformComponent platformComponent = createPlatformComponent();
LWLabelPeer peer = new LWLabelPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public CanvasPeer createCanvas(Canvas target) {
PlatformComponent platformComponent = createPlatformComponent();
LWCanvasPeer peer = new LWCanvasPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public ListPeer createList(List target) {
PlatformComponent platformComponent = createPlatformComponent();
LWListPeer peer = new LWListPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public MenuPeer createMenu(Menu target) {
throw new RuntimeException("not implemented");
}
@Override
public MenuBarPeer createMenuBar(MenuBar target) {
throw new RuntimeException("not implemented");
}
@Override
public MenuItemPeer createMenuItem(MenuItem target) {
throw new RuntimeException("not implemented");
}
@Override
public PanelPeer createPanel(Panel target) {
PlatformComponent platformComponent = createPlatformComponent();
LWPanelPeer peer = new LWPanelPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public PopupMenuPeer createPopupMenu(PopupMenu target) {
throw new RuntimeException("not implemented");
}
@Override
public ScrollPanePeer createScrollPane(ScrollPane target) {
PlatformComponent platformComponent = createPlatformComponent();
LWScrollPanePeer peer = new LWScrollPanePeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public ScrollbarPeer createScrollbar(Scrollbar target) {
PlatformComponent platformComponent = createPlatformComponent();
LWScrollBarPeer peer = new LWScrollBarPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public TextAreaPeer createTextArea(TextArea target) {
PlatformComponent platformComponent = createPlatformComponent();
LWTextAreaPeer peer = new LWTextAreaPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
@Override
public TextFieldPeer createTextField(TextField target) {
PlatformComponent platformComponent = createPlatformComponent();
LWTextFieldPeer peer = new LWTextFieldPeer(target, platformComponent);
targetCreatedPeer(target, peer);
peer.initialize();
return peer;
}
// ---- NON-COMPONENT PEERS ---- //
@Override
public ColorModel getColorModel() throws HeadlessException {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().getColorModel();
}
@Override
public boolean isDesktopSupported() {
return true;
}
@Override
protected DesktopPeer createDesktopPeer(Desktop target) {
return new CDesktopPeer();
}
@Override
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) {
DragSourceContextPeer dscp = CDragSourceContextPeer.createDragSourceContextPeer(dge);
return dscp;
}
@Override
public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
return LWKeyboardFocusManagerPeer.getInstance(manager);
}
@Override
public synchronized MouseInfoPeer getMouseInfoPeer() {
if (mouseInfoPeer == null) {
mouseInfoPeer = createMouseInfoPeerImpl();
}
return mouseInfoPeer;
}
protected MouseInfoPeer createMouseInfoPeerImpl() {
return new LWMouseInfoPeer();
}
public PrintJob getPrintJob(Frame frame, String doctitle, Properties props) {
return getPrintJob(frame, doctitle, null, null);
}
public PrintJob getPrintJob(Frame frame, String doctitle, JobAttributes jobAttributes, PageAttributes pageAttributes) {
if (GraphicsEnvironment.isHeadless()) {
throw new IllegalArgumentException();
}
PrintJob2D printJob = new PrintJob2D(frame, doctitle, jobAttributes, pageAttributes);
if (printJob.printDialog() == false) {
printJob = null;
}
return printJob;
}
@Override
public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
throw new RuntimeException("not implemented");
}
@Override
public boolean isTraySupported() {
throw new RuntimeException("not implemented");
}
@Override
public SystemTrayPeer createSystemTray(SystemTray target) {
throw new RuntimeException("not implemented");
}
@Override
public TrayIconPeer createTrayIcon(TrayIcon target) {
throw new RuntimeException("not implemented");
}
@Override
public Clipboard getSystemClipboard() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkSystemClipboardAccess();
}
synchronized (this) {
if (clipboard == null) {
clipboard = createPlatformClipboard();
}
}
return clipboard;
}
// ---- DELEGATES ---- //
public abstract Clipboard createPlatformClipboard();
/*
* Creates a delegate for the given peer type (window, frame, dialog, etc.)
*/
protected abstract PlatformWindow createPlatformWindow(LWWindowPeer.PeerType peerType);
protected abstract PlatformComponent createPlatformComponent();
protected abstract FileDialogPeer createFileDialogPeer(FileDialog target);
public static void targetDelegate(PlatformWindow delegate, LWWindowPeer peer) {
delegateMap.put(delegate, peer);
}
public static LWWindowPeer delegateToPeer(PlatformWindow delegate) {
return delegateMap.get(delegate);
}
// ---- UTILITY METHODS ---- //
/*
* Expose non-public targetToPeer() method.
*/
public final static Object targetToPeer(Object target) {
return SunToolkit.targetToPeer(target);
}
/*
* Expose non-public targetDisposedPeer() method.
*/
public final static void targetDisposedPeer(Object target, Object peer) {
SunToolkit.targetDisposedPeer(target, peer);
}
/*
* Returns the current cursor manager.
*/
public abstract LWCursorManager getCursorManager();
public static void postEvent(AWTEvent event) {
postEvent(targetToAppContext(event.getSource()), event);
}
// use peer's back buffer to implement non-opaque windows.
@Override
public boolean needUpdateWindow() {
return true;
}
}