Path: blob/master/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java
41153 views
/*1* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.lwawt;2627import java.awt.*;28import java.awt.List;29import java.awt.datatransfer.*;30import java.awt.dnd.DropTarget;31import java.awt.image.*;32import java.awt.peer.*;33import java.security.*;34import java.util.*;3536import sun.awt.*;37import sun.print.*;38import sun.awt.util.ThreadGroupUtils;3940import static sun.lwawt.LWWindowPeer.PeerType;4142public abstract class LWToolkit extends SunToolkit implements Runnable {4344private static final int STATE_NONE = 0;45private static final int STATE_INIT = 1;46private static final int STATE_MESSAGELOOP = 2;47private static final int STATE_SHUTDOWN = 3;48private static final int STATE_CLEANUP = 4;49private static final int STATE_DONE = 5;5051private int runState = STATE_NONE;5253private Clipboard clipboard;54private MouseInfoPeer mouseInfoPeer;5556/**57* Dynamic Layout Resize client code setting.58*/59private volatile boolean dynamicLayoutSetting = true;6061protected LWToolkit() {62}6364/*65* This method is called by subclasses to start this toolkit66* by launching the message loop.67*68* This method waits for the toolkit to be completely initialized69* and returns before the message pump is started.70*/71@SuppressWarnings("removal")72protected final void init() {73AWTAutoShutdown.notifyToolkitThreadBusy();74AccessController.doPrivileged((PrivilegedAction<Void>) () -> {75Runnable shutdownRunnable = () -> {76shutdown();77waitForRunState(STATE_CLEANUP);78};79Thread shutdown = new Thread(80ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable,81"AWT-Shutdown", 0, false);82shutdown.setContextClassLoader(null);83Runtime.getRuntime().addShutdownHook(shutdown);84String name = "AWT-LW";85Thread toolkitThread = new Thread(86ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false);87toolkitThread.setDaemon(true);88toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);89toolkitThread.start();90return null;91});92waitForRunState(STATE_MESSAGELOOP);93}9495/*96* Implemented in subclasses to initialize platform-dependent97* part of the toolkit (open X display connection, create98* toolkit HWND, etc.)99*100* This method is called on the toolkit thread.101*/102protected abstract void platformInit();103104/*105* Sends a request to stop the message pump.106*/107public final void shutdown() {108setRunState(STATE_SHUTDOWN);109platformShutdown();110}111112/*113* Implemented in subclasses to release all the platform-114* dependent resources. Called after the message loop is115* terminated.116*117* Could be called (always called?) on a non-toolkit thread.118*/119protected abstract void platformShutdown();120121/*122* Implemented in subclasses to release all the platform123* resources before the application is terminated.124*125* This method is called on the toolkit thread.126*/127protected abstract void platformCleanup();128129private synchronized int getRunState() {130return runState;131}132133private synchronized void setRunState(int state) {134runState = state;135notifyAll();136}137138public final boolean isTerminating() {139return getRunState() >= STATE_SHUTDOWN;140}141142private void waitForRunState(int state) {143while (getRunState() < state) {144try {145synchronized (this) {146wait();147}148} catch (InterruptedException z) {149// TODO: log150break;151}152}153}154155@Override156public final void run() {157setRunState(STATE_INIT);158platformInit();159AWTAutoShutdown.notifyToolkitThreadFree();160setRunState(STATE_MESSAGELOOP);161while (getRunState() < STATE_SHUTDOWN) {162try {163platformRunMessage();164if (Thread.currentThread().isInterrupted()) {165if (AppContext.getAppContext().isDisposed()) {166break;167}168}169} catch (ThreadDeath td) {170//XXX: if there isn't native code on the stack, the VM just171//kills the thread right away. Do we expect to catch it172//nevertheless?173break;174} catch (Throwable t) {175// TODO: log176System.err.println("Exception on the toolkit thread");177t.printStackTrace(System.err);178}179}180//XXX: if that's a secondary loop, jump back to the STATE_MESSAGELOOP181setRunState(STATE_CLEANUP);182AWTAutoShutdown.notifyToolkitThreadFree();183platformCleanup();184setRunState(STATE_DONE);185}186187/*188* Process the next message(s) from the native event queue.189*190* Initially, all the LWToolkit implementations were supposed191* to have the similar message loop sequence: check if any events192* available, peek events, wait. However, the later analysis shown193* that X11 and Windows implementations are really different, so194* let the subclasses do whatever they require.195*/196protected abstract void platformRunMessage();197198public static LWToolkit getLWToolkit() {199return (LWToolkit)Toolkit.getDefaultToolkit();200}201202// ---- TOPLEVEL PEERS ---- //203204/*205* Note that LWWindowPeer implements WindowPeer, FramePeer206* and DialogPeer interfaces.207*/208protected LWWindowPeer createDelegatedPeer(Window target,209PlatformComponent platformComponent,210PlatformWindow platformWindow,211PeerType peerType) {212LWWindowPeer peer = new LWWindowPeer(target, platformComponent, platformWindow, peerType);213targetCreatedPeer(target, peer);214peer.initialize();215return peer;216}217218@Override219public final FramePeer createLightweightFrame(LightweightFrame target) {220PlatformComponent platformComponent = createLwPlatformComponent();221PlatformWindow platformWindow = createPlatformWindow(PeerType.LW_FRAME);222LWLightweightFramePeer peer = new LWLightweightFramePeer(target,223platformComponent,224platformWindow);225targetCreatedPeer(target, peer);226peer.initialize();227return peer;228}229230@Override231public final WindowPeer createWindow(Window target) {232PlatformComponent platformComponent = createPlatformComponent();233PlatformWindow platformWindow = createPlatformWindow(PeerType.SIMPLEWINDOW);234return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.SIMPLEWINDOW);235}236237@Override238public final FramePeer createFrame(Frame target) {239PlatformComponent platformComponent = createPlatformComponent();240PlatformWindow platformWindow = createPlatformWindow(PeerType.FRAME);241return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.FRAME);242}243244@Override245public DialogPeer createDialog(Dialog target) {246PlatformComponent platformComponent = createPlatformComponent();247PlatformWindow platformWindow = createPlatformWindow(PeerType.DIALOG);248return createDelegatedPeer(target, platformComponent, platformWindow, PeerType.DIALOG);249}250251@Override252public final FileDialogPeer createFileDialog(FileDialog target) {253FileDialogPeer peer = createFileDialogPeer(target);254targetCreatedPeer(target, peer);255return peer;256}257258// ---- LIGHTWEIGHT COMPONENT PEERS ---- //259260@Override261public final ButtonPeer createButton(Button target) {262PlatformComponent platformComponent = createPlatformComponent();263LWButtonPeer peer = new LWButtonPeer(target, platformComponent);264targetCreatedPeer(target, peer);265peer.initialize();266return peer;267}268269@Override270public final CheckboxPeer createCheckbox(Checkbox target) {271PlatformComponent platformComponent = createPlatformComponent();272LWCheckboxPeer peer = new LWCheckboxPeer(target, platformComponent);273targetCreatedPeer(target, peer);274peer.initialize();275return peer;276}277278@Override279public final ChoicePeer createChoice(Choice target) {280PlatformComponent platformComponent = createPlatformComponent();281LWChoicePeer peer = new LWChoicePeer(target, platformComponent);282targetCreatedPeer(target, peer);283peer.initialize();284return peer;285}286287@Override288public final LabelPeer createLabel(Label target) {289PlatformComponent platformComponent = createPlatformComponent();290LWLabelPeer peer = new LWLabelPeer(target, platformComponent);291targetCreatedPeer(target, peer);292peer.initialize();293return peer;294}295296@Override297public final CanvasPeer createCanvas(Canvas target) {298PlatformComponent platformComponent = createPlatformComponent();299LWCanvasPeer<?, ?> peer = new LWCanvasPeer<>(target, platformComponent);300targetCreatedPeer(target, peer);301peer.initialize();302return peer;303}304305@Override306public final ListPeer createList(List target) {307PlatformComponent platformComponent = createPlatformComponent();308LWListPeer peer = new LWListPeer(target, platformComponent);309targetCreatedPeer(target, peer);310peer.initialize();311return peer;312}313314@Override315public final PanelPeer createPanel(Panel target) {316PlatformComponent platformComponent = createPlatformComponent();317LWPanelPeer peer = new LWPanelPeer(target, platformComponent);318targetCreatedPeer(target, peer);319peer.initialize();320return peer;321}322323@Override324public final ScrollPanePeer createScrollPane(ScrollPane target) {325PlatformComponent platformComponent = createPlatformComponent();326LWScrollPanePeer peer = new LWScrollPanePeer(target, platformComponent);327targetCreatedPeer(target, peer);328peer.initialize();329return peer;330}331332@Override333public final ScrollbarPeer createScrollbar(Scrollbar target) {334PlatformComponent platformComponent = createPlatformComponent();335LWScrollBarPeer peer = new LWScrollBarPeer(target, platformComponent);336targetCreatedPeer(target, peer);337peer.initialize();338return peer;339}340341@Override342public final TextAreaPeer createTextArea(TextArea target) {343PlatformComponent platformComponent = createPlatformComponent();344LWTextAreaPeer peer = new LWTextAreaPeer(target, platformComponent);345targetCreatedPeer(target, peer);346peer.initialize();347return peer;348}349350@Override351public final TextFieldPeer createTextField(TextField target) {352PlatformComponent platformComponent = createPlatformComponent();353LWTextFieldPeer peer = new LWTextFieldPeer(target, platformComponent);354targetCreatedPeer(target, peer);355peer.initialize();356return peer;357}358359// ---- NON-COMPONENT PEERS ---- //360361@Override362public final boolean isDesktopSupported() {363return true;364}365366@Override367public final boolean isTaskbarSupported() {368return true;369}370371@Override372public final KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() {373return LWKeyboardFocusManagerPeer.getInstance();374}375376@Override377public final synchronized MouseInfoPeer getMouseInfoPeer() {378if (mouseInfoPeer == null) {379mouseInfoPeer = createMouseInfoPeerImpl();380}381return mouseInfoPeer;382}383384protected final MouseInfoPeer createMouseInfoPeerImpl() {385return new LWMouseInfoPeer();386}387388protected abstract PlatformWindow getPlatformWindowUnderMouse();389390@Override391public final PrintJob getPrintJob(Frame frame, String doctitle,392Properties props) {393return getPrintJob(frame, doctitle, null, null);394}395396@Override397public final PrintJob getPrintJob(Frame frame, String doctitle,398JobAttributes jobAttributes,399PageAttributes pageAttributes) {400if (frame == null) {401throw new NullPointerException("frame must not be null");402}403404if (GraphicsEnvironment.isHeadless()) {405throw new IllegalArgumentException();406}407408PrintJob2D printJob = new PrintJob2D(frame, doctitle, jobAttributes, pageAttributes);409410if (!printJob.printDialog()) {411printJob = null;412}413414return printJob;415}416417@Override418public final Clipboard getSystemClipboard() {419@SuppressWarnings("removal")420SecurityManager security = System.getSecurityManager();421if (security != null) {422security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION);423}424425synchronized (this) {426if (clipboard == null) {427clipboard = createPlatformClipboard();428}429}430return clipboard;431}432433protected abstract SecurityWarningWindow createSecurityWarning(434Window ownerWindow, LWWindowPeer ownerPeer);435436// ---- DELEGATES ---- //437438public abstract Clipboard createPlatformClipboard();439440/*441* Creates a delegate for the given peer type (window, frame, dialog, etc.)442*/443protected abstract PlatformWindow createPlatformWindow(PeerType peerType);444445protected abstract PlatformComponent createPlatformComponent();446447protected abstract PlatformComponent createLwPlatformComponent();448449protected abstract FileDialogPeer createFileDialogPeer(FileDialog target);450451protected abstract PlatformDropTarget createDropTarget(DropTarget dropTarget,452Component component,453LWComponentPeer<?, ?> peer);454455// ---- UTILITY METHODS ---- //456457/*458* Expose non-public targetToPeer() method.459*/460public static final Object targetToPeer(Object target) {461return SunToolkit.targetToPeer(target);462}463464/*465* Expose non-public targetDisposedPeer() method.466*/467public static final void targetDisposedPeer(Object target, Object peer) {468SunToolkit.targetDisposedPeer(target, peer);469}470471/*472* Returns the current cursor manager.473*/474public abstract LWCursorManager getCursorManager();475476public static void postEvent(AWTEvent event) {477postEvent(targetToAppContext(event.getSource()), event);478}479480@Override481public final void grab(final Window w) {482final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);483if (peer != null) {484((LWWindowPeer) peer).grab();485}486}487488@Override489public final void ungrab(final Window w) {490final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);491if (peer != null) {492((LWWindowPeer) peer).ungrab(false);493}494}495496@Override497protected final Object lazilyLoadDesktopProperty(final String name) {498if (name.equals("awt.dynamicLayoutSupported")) {499return isDynamicLayoutSupported();500}501return super.lazilyLoadDesktopProperty(name);502}503504@Override505public final void setDynamicLayout(final boolean dynamic) {506dynamicLayoutSetting = dynamic;507}508509@Override510protected final boolean isDynamicLayoutSet() {511return dynamicLayoutSetting;512}513514@Override515public final boolean isDynamicLayoutActive() {516// "Live resizing" is active by default and user's data is ignored.517return isDynamicLayoutSupported();518}519520/**521* Returns true if dynamic layout of Containers on resize is supported by522* the underlying operating system and/or window manager.523*/524protected final boolean isDynamicLayoutSupported() {525// "Live resizing" is supported by default.526return true;527}528}529530531