![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.swt.widgets.Display Maven / Gradle / Ivy
/******************************************************************************* * Copyright (c) 2000, 2022 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation * Christoph Läubrich - Issue #64 - Integration with java.util.concurrent framework *******************************************************************************/ package org.eclipse.swt.widgets; import java.net.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.function.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.ole.win32.*; import org.eclipse.swt.internal.win32.*; /** * Instances of this class are responsible for managing the * connection between SWT and the underlying operating * system. Their most important function is to implement * the SWT event loop in terms of the platform event model. * They also provide various methods for accessing information * about the operating system, and have overall control over * the operating system resources which SWT allocates. *
method of the runnable to * be invoked by the user-interface thread at the next * reasonable opportunity. The caller of this method continues * to run in parallel, and is not notified when the * runnable has completed. Specifying* Applications which are built with SWT will almost always * require only a single display. In particular, some platforms * which SWT supports will not allow more than one active * display. In other words, some platforms do not support * creating a new display if one already exists that has not been * sent the
dispose()
message. ** In SWT, the thread which creates a
* The user-interface thread for a particular display has the * following special attributes: *Display
* instance is distinguished as the user-interface thread * for that display. **
*- * The event loop for that display must be run from the thread. *
*- * Some SWT API methods (notably, most of the public methods in *
*Widget
and its subclasses), may only be called * from the thread. (To support multi-threaded user-interface * applications, classDisplay
provides inter-thread * communication methods which allow threads other than the * user-interface thread to request that it perform operations * on their behalf.) *- * The thread is not allowed to construct other *
*Display
s until that display has been disposed. * (Note that, this is in addition to the restriction mentioned * above concerning platform support for multiple displays. Thus, * the only way to have multiple simultaneously active displays, * even on platforms which support it, is to have multiple threads.) ** Enforcing these attributes allows SWT to be implemented directly * on the underlying operating system's event model. This has * numerous benefits including smaller footprint, better use of * resources, safer memory management, clearer program logic, * better performance, and fewer overall operating system threads * required. The down side however, is that care must be taken * (only) when constructing multi-threaded applications to use the * inter-thread communication mechanisms which this class provides * when required. *
* All SWT API methods which may only be called from the user-interface * thread are distinguished in their documentation by indicating that * they throw the "
*ERROR_THREAD_INVALID_ACCESS
" * SWT exception. **
*- Styles:
*- (none)
*- Events:
*- Close, Dispose, OpenDocument, Settings, Skin
** IMPORTANT: This class is not intended to be subclassed. *
* @see #syncExec * @see #asyncExec * @see #wake * @see #readAndDispatch * @see #sleep * @see Device#dispose * @see Display snippets * @see Sample code and further information * @noextend This class is not intended to be subclassed by clients. */ public class Display extends Device implements Executor { /** * the handle to the OS message queue * (Warning: This field is platform dependent) ** IMPORTANT: This field is not part of the SWT * public API. It is marked public only so that it can be shared * within the packages provided by SWT. It is not available on all * platforms and should never be accessed from application code. *
* * @noreference This field is not intended to be referenced by clients. */ public MSG msg = new MSG (); static String APP_NAME = "SWT"; //$NON-NLS-1$ static String APP_VERSION = ""; //$NON-NLS-1$ String appLocalDir; /* Windows and Events */ Event [] eventQueue; Callback windowCallback; long windowProc; int threadId; TCHAR windowClass, windowShadowClass, windowOwnDCClass; static int WindowClassCount; static final String WindowName = "SWT_Window"; //$NON-NLS-1$ static final String WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$ static final String WindowOwnDCName = "SWT_WindowOwnDC"; //$NON-NLS-1$ EventTable eventTable, filterTable; boolean useOwnDC; boolean externalEventLoop; // events are dispatched outside SWT, e.g. TrackPopupMenu or DoDragDrop private boolean rescalingAtRuntime; /* Widget Table */ private MapcontrolByHandle; static final int GROW_SIZE = 1024; /* Startup info */ static STARTUPINFO lpStartupInfo; static { lpStartupInfo = new STARTUPINFO (); lpStartupInfo.cb = STARTUPINFO.sizeof; OS.GetStartupInfo (lpStartupInfo); } /* XP Themes */ private Map themeDataMap = new HashMap<>(); static final char [] EXPLORER = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 0}; static final char [] TREEVIEW = new char [] {'T', 'R', 'E', 'E', 'V', 'I', 'E', 'W', 0}; /* Emergency switch to be used in case of regressions. Not supposed to be changed when app is running. */ static final boolean disableCustomThemeTweaks = Boolean.valueOf(System.getProperty("org.eclipse.swt.internal.win32.disableCustomThemeTweaks")); //$NON-NLS-1$ /** * Changes Windows theme to 'DarkMode_Explorer' for Controls that can benefit from it. * Effects as of Windows 10 version 1909:
**
* Limitations:- Button - default background/foreground colors
*- Scrollbars in controls tha have them - this is the most important change for many applications.
*- Tree - dark theme compatible expander icon.
*- Tree - dark theme compatible colors for selected and hovered items.
*- The list is not exhaustive. Also, effects can change, because Windows dark theme is not yet official.
*
**
* All Scrollable-based Controls are affected. */ static final String USE_DARKMODE_EXPLORER_THEME_KEY = "org.eclipse.swt.internal.win32.useDarkModeExplorerTheme"; boolean useDarkModeExplorerTheme; /** * Sets Shell titles to match theme selected in Windows. That is, dark is system is dark. * Limitations:- Only available since Win10 version 1903.
*- Does not affect already created controls.
*
**
*/ static final String USE_SHELL_TITLE_COLORING = "org.eclipse.swt.internal.win32.useShellTitleColoring"; boolean useShellTitleColoring; /** * Configures background/foreground colors of Menu(SWT.BAR).- Only available since Win10.
*- Does not affect already created Shells.
*
* Side effects: **
* Expects a- Menu items are no longer highlighted when mouse hovers over
*Color
value. */ static final String MENUBAR_FOREGROUND_COLOR_KEY = "org.eclipse.swt.internal.win32.menuBarForegroundColor"; //$NON-NLS-1$ int menuBarForegroundPixel = -1; static final String MENUBAR_BACKGROUND_COLOR_KEY = "org.eclipse.swt.internal.win32.menuBarBackgroundColor"; //$NON-NLS-1$ int menuBarBackgroundPixel = -1; /** * Color of the 1px separator between Menu(SWT.BAR) and Shell's client area.
* Expects aColor
value. */ static final String MENUBAR_BORDER_COLOR_KEY = "org.eclipse.swt.internal.win32.menuBarBorderColor"; //$NON-NLS-1$ long menuBarBorderPen; /** * Use a different border for Controls. * This often gives better results for dark themes. * The effect is slightly different for different controls. */ static final String USE_WS_BORDER_ALL_KEY = "org.eclipse.swt.internal.win32.all.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderAll = false; static final String USE_WS_BORDER_CANVAS_KEY = "org.eclipse.swt.internal.win32.Canvas.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderCanvas = false; static final String USE_WS_BORDER_LABEL_KEY = "org.eclipse.swt.internal.win32.Label.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderLabel = false; static final String USE_WS_BORDER_LIST_KEY = "org.eclipse.swt.internal.win32.List.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderList = false; static final String USE_WS_BORDER_TABLE_KEY = "org.eclipse.swt.internal.win32.Table.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderTable = false; static final String USE_WS_BORDER_TEXT_KEY = "org.eclipse.swt.internal.win32.Text.use_WS_BORDER"; //$NON-NLS-1$ boolean useWsBorderText = false; /** * Changes the color of Table header's column delimiters. * Only affects custom-drawn header, that is when background/foreground header color is set. * Expects aColor
value. */ static final String TABLE_HEADER_LINE_COLOR_KEY = "org.eclipse.swt.internal.win32.Table.headerLineColor"; //$NON-NLS-1$ int tableHeaderLinePixel = -1; /** * Disabled Label is drawn with specified foreground color. * Expects aColor
value. */ static final String LABEL_DISABLED_FOREGROUND_COLOR_KEY = "org.eclipse.swt.internal.win32.Label.disabledForegroundColor"; //$NON-NLS-1$ int disabledLabelForegroundPixel = -1; /** * Use dark theme for Combo. * Limitations:
**
* Expects a- Only available since Win10 version 1903.
*- Does not affect already created controls.
*boolean
value. */ static final String COMBO_USE_DARK_THEME = "org.eclipse.swt.internal.win32.Combo.useDarkTheme"; //$NON-NLS-1$ boolean comboUseDarkTheme = false; /** * Use .setForeground() .setBackground() theme for ProgressBar. * Limitations:
**
* Side effects: *- Does not affect already created controls.
**
* Expects a- ProgressBar's shine animation is lost.
*boolean
value. */ static final String PROGRESSBAR_USE_COLORS = "org.eclipse.swt.internal.win32.ProgressBar.useColors"; //$NON-NLS-1$ boolean progressbarUseColors = false; /** * Use dark theme compatible icons for Text with SWT.ICON_SEARCH, SWT.ICON_CANCEL * Limitations:
**
* Expects a- Must be configured before first Text is created.
*boolean
value. */ static final String USE_DARKTHEME_TEXT_ICONS = "org.eclipse.swt.internal.win32.Text.useDarkThemeIcons"; //$NON-NLS-1$ boolean textUseDarkthemeIcons = false; /** * Use dark prefered color scheme in Edge browser. * Note:
**
* Expects a- When setting this property on the display, it is first AND'ed with !disableCustomThemeTweaks. *
- The data is then read from withing Edge. *
- This is to avoid adding public methods/members. *
boolean
value. */ static final String EDGE_USE_DARK_PREFERED_COLOR_SCHEME = "org.eclipse.swt.internal.win32.Edge.useDarkPreferedColorScheme"; //$NON-NLS-1$ /* Custom icons */ private HashMapsizeToSearchIconHandle = new HashMap<>(); private HashMap sizeToCancelIconHandle = new HashMap<>(); /* Focus */ int focusEvent; Control focusControl; /* Menus */ Menu [] bars, popups; MenuItem [] items; /* * The start value for WM_COMMAND id's. * Windows reserves the values 0..100. * * The SmartPhone SWT resource file reserves * the values 101..107. */ static final int ID_START = 108; /* Filter Hook */ Callback msgFilterCallback; long msgFilterProc, filterHook; MSG hookMsg = new MSG (); boolean runDragDrop = true, dragCancelled = false; /* Idle Hook */ Callback foregroundIdleCallback; long foregroundIdleProc, idleHook; /* Message Hook and Embedding */ boolean ignoreNextKey; Callback getMsgCallback, embeddedCallback; long getMsgProc, msgHook, embeddedHwnd, embeddedProc; static final String AWT_WINDOW_CLASS = "SunAwtWindow"; //$NON-NLS-1$ static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'}; /* Sync/Async Widget Communication */ Synchronizer synchronizer; Consumer runtimeExceptionHandler = DefaultExceptionHandler.RUNTIME_EXCEPTION_HANDLER; Consumer errorHandler = DefaultExceptionHandler.RUNTIME_ERROR_HANDLER; boolean runMessagesInIdle = false, runMessagesInMessageProc = true; static final String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$ static final String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "org.eclipse.swt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$ static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; //$NON-NLS-1$ static final String ACCEL_KEY_HIT = "org.eclipse.swt.internal.win32.accelKeyHit"; //$NON-NLS-1$ static final String EXTERNAL_EVENT_LOOP_KEY = "org.eclipse.swt.internal.win32.externalEventLoop"; //$NON-NLS-1$ static final String APPLOCAL_DIR_KEY = "org.eclipse.swt.internal.win32.appLocalDir"; //$NON-NLS-1$ Thread thread; /* Display Shutdown */ Runnable [] disposeList; /* Deferred Layout list */ Composite[] layoutDeferred; int layoutDeferredCount; /* System Tray */ Tray tray; int nextTrayId; /* TaskBar */ TaskBar taskBar; static final String TASKBAR_EVENT = "/SWTINTERNAL_ID"; //$NON-NLS-1$ static final String LAUNCHER_PREFIX = "--launcher.openFile "; //$NON-NLS-1$ /* Timers */ long [] timerIds; Runnable [] timerList; long nextTimerId = SETTINGS_ID + 1; /* Settings */ static final long SETTINGS_ID = 100; static final int SETTINGS_DELAY = 2000; /* Keyboard and Mouse */ RECT clickRect; int clickCount, lastTime, lastButton; long lastClickHwnd; Point scrollRemainderEvt = new Point(0, 0); Point scrollRemainderBar = new Point(0, 0); int lastKey, lastMouse, lastAscii; boolean lastVirtual, lastDead; byte [] keyboard = new byte [256]; boolean accelKeyHit, mnemonicKeyHit; boolean lockActiveWindow, captureChanged, xMouse; /* Gesture state */ double magStartDistance, lastDistance; double rotationAngle; int lastX, lastY; /* Touch state */ TouchSource [] touchSources; /* Tool Tips */ int nextToolTipId; /* MDI */ boolean ignoreRestoreFocus; Control lastHittestControl; int lastHittest; /* Message Only Window */ Callback messageCallback; long hwndMessage, messageProc; /* System Resources */ @Deprecated(since = "3.126.0") LOGFONT lfSystemFont; @Deprecated(since = "3.126.0") Font systemFont; Image errorImage, infoImage, questionImage, warningIcon; Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1]; Resource [] resources; static final int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1; /* ImageList Cache */ ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList; /* Custom Colors for ChooseColor */ long lpCustColors; /* Table */ char [] tableBuffer; /* Resize and move recursion */ int resizeCount; static final int RESIZE_LIMIT = 4; /* Display Data */ Object data; String [] keys; Object [] values; /* Key Mappings */ static final int [] [] KeyTable = { /* Keyboard and Mouse Masks */ {OS.VK_MENU, SWT.ALT}, {OS.VK_SHIFT, SWT.SHIFT}, {OS.VK_CONTROL, SWT.CONTROL}, // {OS.VK_????, SWT.COMMAND}, /* NOT CURRENTLY USED */ // {OS.VK_LBUTTON, SWT.BUTTON1}, // {OS.VK_MBUTTON, SWT.BUTTON3}, // {OS.VK_RBUTTON, SWT.BUTTON2}, /* Non-Numeric Keypad Keys */ {OS.VK_UP, SWT.ARROW_UP}, {OS.VK_DOWN, SWT.ARROW_DOWN}, {OS.VK_LEFT, SWT.ARROW_LEFT}, {OS.VK_RIGHT, SWT.ARROW_RIGHT}, {OS.VK_PRIOR, SWT.PAGE_UP}, {OS.VK_NEXT, SWT.PAGE_DOWN}, {OS.VK_HOME, SWT.HOME}, {OS.VK_END, SWT.END}, {OS.VK_INSERT, SWT.INSERT}, /* Virtual and Ascii Keys */ {OS.VK_BACK, SWT.BS}, {OS.VK_RETURN, SWT.CR}, {OS.VK_DELETE, SWT.DEL}, {OS.VK_ESCAPE, SWT.ESC}, {OS.VK_RETURN, SWT.LF}, {OS.VK_TAB, SWT.TAB}, /* Functions Keys */ {OS.VK_F1, SWT.F1}, {OS.VK_F2, SWT.F2}, {OS.VK_F3, SWT.F3}, {OS.VK_F4, SWT.F4}, {OS.VK_F5, SWT.F5}, {OS.VK_F6, SWT.F6}, {OS.VK_F7, SWT.F7}, {OS.VK_F8, SWT.F8}, {OS.VK_F9, SWT.F9}, {OS.VK_F10, SWT.F10}, {OS.VK_F11, SWT.F11}, {OS.VK_F12, SWT.F12}, {OS.VK_F13, SWT.F13}, {OS.VK_F14, SWT.F14}, {OS.VK_F15, SWT.F15}, {OS.VK_F16, SWT.F16}, {OS.VK_F17, SWT.F17}, {OS.VK_F18, SWT.F18}, {OS.VK_F19, SWT.F19}, {OS.VK_F20, SWT.F20}, /* Numeric Keypad Keys */ {OS.VK_MULTIPLY, SWT.KEYPAD_MULTIPLY}, {OS.VK_ADD, SWT.KEYPAD_ADD}, {OS.VK_RETURN, SWT.KEYPAD_CR}, {OS.VK_SUBTRACT, SWT.KEYPAD_SUBTRACT}, {OS.VK_DECIMAL, SWT.KEYPAD_DECIMAL}, {OS.VK_DIVIDE, SWT.KEYPAD_DIVIDE}, {OS.VK_NUMPAD0, SWT.KEYPAD_0}, {OS.VK_NUMPAD1, SWT.KEYPAD_1}, {OS.VK_NUMPAD2, SWT.KEYPAD_2}, {OS.VK_NUMPAD3, SWT.KEYPAD_3}, {OS.VK_NUMPAD4, SWT.KEYPAD_4}, {OS.VK_NUMPAD5, SWT.KEYPAD_5}, {OS.VK_NUMPAD6, SWT.KEYPAD_6}, {OS.VK_NUMPAD7, SWT.KEYPAD_7}, {OS.VK_NUMPAD8, SWT.KEYPAD_8}, {OS.VK_NUMPAD9, SWT.KEYPAD_9}, // {OS.VK_????, SWT.KEYPAD_EQUAL}, /* Other keys */ {OS.VK_CAPITAL, SWT.CAPS_LOCK}, {OS.VK_NUMLOCK, SWT.NUM_LOCK}, {OS.VK_SCROLL, SWT.SCROLL_LOCK}, {OS.VK_PAUSE, SWT.PAUSE}, {OS.VK_CANCEL, SWT.BREAK}, {OS.VK_SNAPSHOT, SWT.PRINT_SCREEN}, // {OS.VK_????, SWT.HELP}, }; /* Multiple Displays */ static Display Default; static Display [] Displays = new Display [1]; /* Multiple Monitors */ Monitor[] monitors = null; int monitorCount = 0; /* Modality */ Shell [] modalShells; Dialog modalDialog; static boolean TrimEnabled = false; /* Private SWT Window Messages */ static final int SWT_GETACCELCOUNT = OS.WM_APP; static final int SWT_GETACCEL = OS.WM_APP + 1; static final int SWT_KEYMSG = OS.WM_APP + 2; static final int SWT_DESTROY = OS.WM_APP + 3; static final int SWT_TRAYICONMSG = OS.WM_APP + 4; static final int SWT_NULL = OS.WM_APP + 5; static final int SWT_RUNASYNC = OS.WM_APP + 6; static int TASKBARCREATED; static int TASKBARBUTTONCREATED; static int SWT_RESTORECARET; static int DI_GETDRAGIMAGE; static int SWT_OPENDOC; /* Skinning support */ Widget [] skinList = new Widget [GROW_SIZE]; int skinCount; /* Package Name */ static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$ /* * TEMPORARY CODE. Install the runnable that * gets the current display. This code will * be removed in the future. */ static { DeviceFinder = () -> { Device device = getCurrent (); if (device == null) { device = getDefault (); } setDevice (device); }; } static { CommonWidgetsDPIChangeHandlers.registerCommonHandlers(); } /* * TEMPORARY CODE. */ static void setDevice (Device device) { CurrentDevice = device; } /** * Constructs a new instance of this class. * * Note: The resulting display is marked as the current * display. If this is the first display which has been * constructed since the application started, it is also * marked as the default display. *
* * @exception SWTException*
* * @see #getCurrent * @see #getDefault * @see Widget#checkSubclass * @see Shell */ public Display () { this (null); } /** * Constructs a new instance of this class using the parameter. * * @param data the device data */ public Display (DeviceData data) { super (data); } Control _getFocusControl () { return findControl (OS.GetFocus ()); } void addBar (Menu menu) { if (bars == null) bars = new Menu [4]; int length = bars.length; for (int i=0; i- ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display
*- ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
*= skinList.length) { Widget[] newSkinWidgets = new Widget [(skinList.length + 1) * 3 / 2]; System.arraycopy (skinList, 0, newSkinWidgets, 0, skinList.length); skinList = newSkinWidgets; } skinList [skinCount++] = widget; } /** * Adds the listener to the collection of listeners who will * be notified when an event of the given type occurs anywhere * in a widget. The event type is one of the event constants * defined in class SWT
. When the event does occur, * the listener is notified by sending it thehandleEvent()
* message. ** Setting the type of an event to
* * @param eventType the type of event to listen for * @param listener the listener which should be notified when the event occurs * * @exception IllegalArgumentExceptionSWT.None
from * within thehandleEvent()
method can be used to * change the event type and stop subsequent Java listeners * from running. Because event filters run before other listeners, * event filters can both block other listeners and set arbitrary * fields within an event. For this reason, event filters are both * powerful and dangerous. They should generally be avoided for * performance, debugging and code maintenance reasons. **
* @exception SWTException- ERROR_NULL_ARGUMENT - if the listener is null
**
* * @see Listener * @see SWT * @see #removeFilter * @see #removeListener * * @since 3.0 */ public void addFilter (int eventType, Listener listener) { checkDevice (); if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); if (filterTable == null) filterTable = new EventTable (); filterTable.hook (eventType, listener); } void addLayoutDeferred (Composite comp) { if (layoutDeferred == null) layoutDeferred = new Composite [64]; if (layoutDeferredCount == layoutDeferred.length) { Composite [] temp = new Composite [layoutDeferred.length + 64]; System.arraycopy (layoutDeferred, 0, temp, 0, layoutDeferred.length); layoutDeferred = temp; } layoutDeferred[layoutDeferredCount++] = comp; } /** * Adds the listener to the collection of listeners who will * be notified when an event of the given type occurs. The event * type is one of the event constants defined in class- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*- ERROR_DEVICE_DISPOSED - if the receiver has been disposed
*SWT
. * When the event does occur in the display, the listener is notified by * sending it thehandleEvent()
message. * * @param eventType the type of event to listen for * @param listener the listener which should be notified when the event occurs * * @exception IllegalArgumentException*
* @exception SWTException- ERROR_NULL_ARGUMENT - if the listener is null
**
* * @see Listener * @see SWT * @see #removeListener * * @since 2.0 */ public void addListener (int eventType, Listener listener) { checkDevice (); if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); if (eventTable == null) eventTable = new EventTable (); eventTable.hook (eventType, listener); } void addMenuItem (MenuItem item) { if (items == null) items = new MenuItem [64]; for (int i=0; i- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*- ERROR_DEVICE_DISPOSED - if the receiver has been disposed
*run() null
as the * runnable simply wakes the user-interface thread when run. ** Note that at the time the runnable is invoked, widgets * that have the receiver as their display may have been * disposed. Therefore, it is necessary to check for this * case inside the runnable before accessing the widget. *
* * @param runnable code to run on the user-interface thread ornull
* * @exception SWTException
-
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- If the calling thread is the user-interface thread of this display it is * executed immediately and the method returns after the command has run, as with * the method {@link Display#syncExec(Runnable)}. *
- In all other cases the
run()
method of the runnable is * asynchronously executed as with the method * {@link Display#asyncExec(Runnable)} at the next reasonable opportunity. The * caller of this method continues to run in parallel, and is not notified when * the runnable has completed.
*
* This can be used in cases where one want to execute some piece of code that * should be guaranteed to run in the user-interface thread regardless of the * current thread. *
* ** Note that at the time the runnable is invoked, widgets that have the receiver * as their display may have been disposed. Therefore, it is advised to check * for this case inside the runnable before accessing the widget. *
* * @param runnable the runnable to execute in the user-interface thread, never *null
* @throws RejectedExecutionException if this task cannot be accepted for
* execution
* @throws NullPointerException if runnable is null
*/
@Override
public void execute(Runnable runnable) {
Objects.requireNonNull(runnable);
if (isDisposed()) {
throw new RejectedExecutionException(new SWTException (SWT.ERROR_WIDGET_DISPOSED, null));
}
if (thread == Thread.currentThread()) {
syncExec(runnable);
} else {
asyncExec(runnable);
}
}
/**
* Causes the system hardware to emit a short sound
* (if it supports this capability).
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* IMPORTANT: See the comment in Widget.checkSubclass()
.
*
-
*
- ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* This method is called before init
.
*
release
.
*
* @see Device#dispose
* @see #release
*/
@Override
protected void destroy () {
if (this == Default) Default = null;
deregister (this);
destroyDisplay ();
}
void destroyDisplay () {
}
/**
* Causes the run()
method of the runnable to
* be invoked by the user-interface thread just before the
* receiver is disposed. Specifying a null
runnable
* is ignored.
*
* @param runnable code to run at dispose time.
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
Widget
subclass which
* represents it in the currently running application, if
* such exists, or null if no matching widget can be found.
* * IMPORTANT: This method should not be called from * application code. The arguments are platform-specific. *
* * @param handle the handle for the widget * @return the SWT widget that the handle represents * * @exception SWTException-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
Widget
subclass which represents
* the handle/id pair in the currently running application,
* if such exists, or null if no matching widget can be found.
* * IMPORTANT: This method should not be called from * application code. The arguments are platform-specific. *
* * @param handle the handle for the widget * @param id the id for the subwidget (usually an item) * @return the SWT widget that the handle/id pair represents * * @exception SWTException-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
Widget
subclass which represents
* the widget/id pair in the currently running application,
* if such exists, or null if no matching widget can be found.
*
* @param widget the widget
* @param id the id for the subwidget (usually an item)
* @return the SWT subwidget (usually an item) that the widget/id pair represents
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
as the thread will return null
* for the display.
*
* @param thread the user-interface thread
* @return the display for the given thread
*/
public static Display findDisplay (Thread thread) {
synchronized (Device.class) {
for (Display display : Displays) {
if (display != null && display.thread == thread) {
return display;
}
}
return null;
}
}
TouchSource findTouchSource (long touchDevice, Monitor monitor) {
if (touchSources == null) touchSources = new TouchSource [4];
int length = touchSources.length;
for (int i=0; i-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
if there is no application menu bar for the platform.
*
* @return the application menu bar, or null
*
* @exception SWTException -
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Applications may have associated arbitrary objects with the
* receiver in this fashion. If the objects stored in the
* properties need to be notified when the display is disposed
* of, it is the application's responsibility to provide a
* disposeExec()
handler which does so.
*
-
*
- ERROR_NULL_ARGUMENT - if the key is null *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Applications may put arbitrary objects in this field. If
* the object stored in the display specific data needs to
* be notified when the display is disposed of, it is the
* application's responsibility to provide a
* disposeExec()
handler which does so.
*
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
LEFT
or RIGHT
.
* The button dismissal alignment is the ordering that should be used when positioning the
* default dismissal button for a dialog. For example, in a dialog that contains an OK and
* CANCEL button, on platforms where the button dismissal alignment is LEFT
, the
* button ordering should be OK/CANCEL. When button dismissal alignment is RIGHT
,
* the button ordering should be CANCEL/OK.
*
* @return the button dismissal order
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Note: This operation is a hint and is not supported on * platforms that do not have this concept. *
* * @return the high contrast mode * * @exception SWTException-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
true
if the current OS theme has a dark appearance, else
* returns false
.
* * Note: This operation is a hint and is not supported on platforms that do not * have this concept. *
** Note: Windows 10 onwards users can separately configure the theme for OS and * Application level and this can be read from the Windows registry. Since the * application needs to honor the application level theme, this API reads the * Application level theme setting. *
* * @returntrue
if the current OS theme has a dark appearance, else
* returns false
.
*
* @since 3.112
*/
public static boolean isSystemDarkTheme () {
boolean isDarkTheme = false;
/*
* The registry settings, and Dark Theme itself, is present since Win10 1809
*/
if (OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1809) {
int[] result = OS.readRegistryDwords(OS.HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme");
if (result!=null) {
isDarkTheme = (result[0] == 0);
}
}
return isDarkTheme;
}
int getLastEventTime () {
return OS.GetMessageTime ();
}
MenuItem getMenuItem (int id) {
if (items == null) return null;
id = id - ID_START;
if (0 <= id && id < items.length) return items [id];
return null;
}
Shell getModalShell () {
if (modalShells == null) return null;
int index = modalShells.length;
while (--index >= 0) {
Shell shell = modalShells [index];
if (shell != null) return shell;
}
return null;
}
Dialog getModalDialog () {
return modalDialog;
}
Monitor getMonitor (long hmonitor) {
MONITORINFO lpmi = new MONITORINFO ();
lpmi.cbSize = MONITORINFO.sizeof;
OS.GetMonitorInfo (hmonitor, lpmi);
Monitor monitor = new Monitor ();
monitor.handle = hmonitor;
Rectangle boundsInPixels = new Rectangle(lpmi.rcMonitor_left, lpmi.rcMonitor_top, lpmi.rcMonitor_right - lpmi.rcMonitor_left,lpmi.rcMonitor_bottom - lpmi.rcMonitor_top);
Rectangle clientAreaInPixels = new Rectangle(lpmi.rcWork_left, lpmi.rcWork_top, lpmi.rcWork_right - lpmi.rcWork_left, lpmi.rcWork_bottom - lpmi.rcWork_top);
int [] dpiX = new int[1];
int [] dpiY = new int[1];
int result = OS.GetDpiForMonitor (monitor.handle, OS.MDT_EFFECTIVE_DPI, dpiX, dpiY);
result = (result == OS.S_OK) ? DPIUtil.mapDPIToZoom (dpiX[0]) : 100;
if (DPIUtil.isAutoScaleOnRuntimeActive()) {
int autoscaleZoom = DPIUtil.getZoomForAutoscaleProperty(result);
monitor.setBounds(getMonitorBoundsInPointsInDisplayCoordinateSystem(boundsInPixels, autoscaleZoom));
monitor.setClientArea(getMonitorBoundsInPointsInDisplayCoordinateSystem(clientAreaInPixels, autoscaleZoom));
} else {
monitor.setBounds(DPIUtil.autoScaleDown(boundsInPixels));
monitor.setClientArea(DPIUtil.autoScaleDown(clientAreaInPixels));
}
if (result == 0) {
System.err.println("***WARNING: GetDpiForMonitor: SWT could not get valid monitor scaling factor.");
result = 100;
}
/*
* Always return true monitor zoom value as fetched from native, else will lead
* to scaling issue on OS Win8.1 and above, for more details refer bug 537614.
*/
monitor.zoom = result;
return monitor;
}
private Rectangle getMonitorBoundsInPointsInDisplayCoordinateSystem(Rectangle boundsInPixels, int zoom) {
Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, zoom);
bounds.x = boundsInPixels.x;
bounds.y = boundsInPixels.y;
return bounds;
}
/**
* Returns an array of monitors attached to the device.
*
* @return the array of monitors
*
* @since 3.0
*/
public Monitor [] getMonitors () {
checkDevice ();
monitors = new Monitor [4];
Callback callback = new Callback (this, "monitorEnumProc", 4); //$NON-NLS-1$
OS.EnumDisplayMonitors (0, null, callback.getAddress (), 0);
callback.dispose ();
Monitor [] result = new Monitor [monitorCount];
System.arraycopy (monitors, 0, result, 0, monitorCount);
monitors = null;
monitorCount = 0;
return result;
}
long getMsgProc (long code, long wParam, long lParam) {
if (embeddedHwnd == 0) {
long hInstance = OS.GetModuleHandle (null);
embeddedHwnd = OS.CreateWindowEx (0,
windowClass,
null,
OS.WS_OVERLAPPED,
0, 0, 0, 0,
0,
0,
hInstance,
null);
embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
embeddedProc = embeddedCallback.getAddress ();
OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, embeddedProc);
}
if (code >= 0 && (wParam & OS.PM_REMOVE) != 0) {
MSG msg = new MSG ();
OS.MoveMemory (msg, lParam, MSG.sizeof);
switch (msg.message) {
case OS.WM_KEYDOWN:
case OS.WM_KEYUP:
case OS.WM_SYSKEYDOWN:
case OS.WM_SYSKEYUP: {
Control control = findControl (msg.hwnd);
if (control != null) {
long hHeap = OS.GetProcessHeap ();
long keyMsg = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, MSG.sizeof);
OS.MoveMemory (keyMsg, msg, MSG.sizeof);
OS.PostMessage (hwndMessage, SWT_KEYMSG, wParam, keyMsg);
switch ((int)msg.wParam) {
case OS.VK_SHIFT:
case OS.VK_MENU:
case OS.VK_CONTROL:
case OS.VK_CAPITAL:
case OS.VK_NUMLOCK:
case OS.VK_SCROLL:
break;
default:
msg.message = OS.WM_NULL;
OS.MoveMemory (lParam, msg, MSG.sizeof);
}
}
}
}
}
return OS.CallNextHookEx (msgHook, (int)code, wParam, lParam);
}
/**
* Returns the primary monitor for that device.
*
* @return the primary monitor
*
* @since 3.0
*/
public Monitor getPrimaryMonitor () {
checkDevice ();
long hmonitor = OS.MonitorFromWindow (0, OS.MONITOR_DEFAULTTOPRIMARY);
return getMonitor (hmonitor);
}
/**
* Returns a (possibly empty) array containing all shells which have
* not been disposed and have the receiver as their display.
*
* @return the receiver's shells
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
syncExec
* or null if no such runnable is currently being invoked by
* the user-interface thread.
* * Note: If a runnable invoked by asyncExec is currently * running, this method will return null. *
* * @return the receiver's sync-interface thread * * @exception SWTException-
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
SWT
. Any value other
* than one of the SWT color constants which is passed
* in will result in the color black. This color should
* not be free'd because it was allocated by the system,
* not the application.
*
* @param id the color constant
* @return the matching color
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
SWT
. This cursor should
* not be free'd because it was allocated by the system,
* not the application. A value of null
will
* be returned if the supplied constant is not an SWT cursor
* constant.
*
* @param id the SWT cursor constant
* @return the corresponding cursor or null
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Typically, applications which want the default look * should simply not set the font on the widgets they * create. Widgets are always created with the correct * default font for the class of user-interface component * they represent. *
* * @return a font * * @exception SWTException-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
SWT
. This image should
* not be free'd because it was allocated by the system,
* not the application. A value of null
will
* be returned either if the supplied constant is not an
* SWT icon constant or if the platform does not define an
* image that corresponds to the constant.
*
* @param id the SWT icon constant
* @return the corresponding image or null
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
on platforms where no menu is provided for the application.
*
* @return the system menu, or null
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
*
* @exception SWTException -
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
null
*
* @exception SWTException -
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
true
if a touch-aware input device is detected, or false
otherwise
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* IMPORTANT: This method is not part of the public
* API for Display
. It is marked public only so that it
* can be shared within the packages provided by SWT. It is not
* available on all platforms, and should never be called from
* application code.
*
-
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_NO_HANDLES if a handle could not be obtained for gc creation *
* This method is called after create
.
*
* IMPORTANT: This method is not part of the public
* API for Display
. It is marked public only so that it
* can be shared within the packages provided by SWT. It is not
* available on all platforms, and should never be called from
* application code.
*
* NOTE: On right-to-left platforms where the coordinate * systems are mirrored, special care needs to be taken * when mapping coordinates from one control to another * to ensure the result is correctly mirrored. * * Mapping a point that is the origin of a rectangle and * then adding the width and height is not equivalent to * mapping the rectangle. When one control is mirrored * and the other is not, adding the width and height to a * point that was mapped causes the rectangle to extend * in the wrong direction. Mapping the entire rectangle * instead of just one point causes both the origin and * the corner of the rectangle to be mapped. *
* * @param from the sourceControl
or null
* @param to the destination Control
or null
* @param point to be mapped
* @return point with mapped coordinates
*
* @exception IllegalArgumentException -
*
- ERROR_NULL_ARGUMENT - if the point is null *
- ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* NOTE: On right-to-left platforms where the coordinate * systems are mirrored, special care needs to be taken * when mapping coordinates from one control to another * to ensure the result is correctly mirrored. * * Mapping a point that is the origin of a rectangle and * then adding the width and height is not equivalent to * mapping the rectangle. When one control is mirrored * and the other is not, adding the width and height to a * point that was mapped causes the rectangle to extend * in the wrong direction. Mapping the entire rectangle * instead of just one point causes both the origin and * the corner of the rectangle to be mapped. *
* * @param from the sourceControl
or null
* @param to the destination Control
or null
* @param x coordinates to be mapped
* @param y coordinates to be mapped
* @return point with mapped coordinates
*
* @exception IllegalArgumentException -
*
- ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* NOTE: On right-to-left platforms where the coordinate * systems are mirrored, special care needs to be taken * when mapping coordinates from one control to another * to ensure the result is correctly mirrored. * * Mapping a point that is the origin of a rectangle and * then adding the width and height is not equivalent to * mapping the rectangle. When one control is mirrored * and the other is not, adding the width and height to a * point that was mapped causes the rectangle to extend * in the wrong direction. Mapping the entire rectangle * instead of just one point causes both the origin and * the corner of the rectangle to be mapped. *
* * @param from the sourceControl
or null
* @param to the destination Control
or null
* @param rectangle to be mapped
* @return rectangle with mapped coordinates
*
* @exception IllegalArgumentException -
*
- ERROR_NULL_ARGUMENT - if the rectangle is null *
- ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* NOTE: On right-to-left platforms where the coordinate * systems are mirrored, special care needs to be taken * when mapping coordinates from one control to another * to ensure the result is correctly mirrored. * * Mapping a point that is the origin of a rectangle and * then adding the width and height is not equivalent to * mapping the rectangle. When one control is mirrored * and the other is not, adding the width and height to a * point that was mapped causes the rectangle to extend * in the wrong direction. Mapping the entire rectangle * instead of just one point causes both the origin and * the corner of the rectangle to be mapped. *
* * @param from the sourceControl
or null
* @param to the destination Control
or null
* @param x coordinates to be mapped
* @param y coordinates to be mapped
* @param width coordinates to be mapped
* @param height coordinates to be mapped
* @return rectangle with mapped coordinates
*
* @exception IllegalArgumentException -
*
- ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
post
is used to generate low level keyboard
* and mouse events. The intent is to enable automated UI
* testing by simulating the input from the user. Most
* SWT applications should never need to call this method.
* * Note that this operation can fail when the operating system * fails to generate the event for any reason. For example, * this can happen when there is no such key or mouse button * or when the system event queue is full. *
** Event Types: *
KeyDown, KeyUp *
The following fields in the Event
apply:
*
-
*
- (in) type KeyDown or KeyUp
Either one of:
*- (in) character a character that corresponds to a keyboard key *
- (in) keyCode the key code of the key that was typed,
* as defined by the key code constants in class
SWT
Optional (on some platforms):
*- (in) stateMask the state of the keyboard modifier,
* as defined by the key code constants in class
SWT
*
*
MouseDown, MouseUp
*The following fields in the Event
apply:
*
-
*
- (in) type MouseDown or MouseUp *
- (in) button the button that is pressed or released *
MouseMove
*The following fields in the Event
apply:
*
-
*
- (in) type MouseMove *
- (in) x the x coordinate to move the mouse pointer to in screen coordinates *
- (in) y the y coordinate to move the mouse pointer to in screen coordinates *
MouseWheel
*The following fields in the Event
apply:
-
*
- (in) type MouseWheel *
- (in) detail either SWT.SCROLL_LINE or SWT.SCROLL_PAGE *
- (in) count the number of lines or pages to scroll *
-
*
- ERROR_NULL_ARGUMENT - if the event is null *
-
*
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
true
* if there is potentially more work to do, or false
* if the caller can sleep until another event is placed on
* the event queue.
*
* In addition to checking the system event queue, this method also
* checks if any inter-thread messages (created by syncExec()
* or asyncExec()
) are waiting to be processed, and if
* so handles them before returning.
*
false
if the caller can sleep upon return from this method
*
* @exception SWTException -
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
- ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message *
true
when sent the message
* isDisposed()
.
*
* When a device is destroyed, resources that were acquired
* on behalf of the programmer need to be returned to the
* operating system. For example, if the device allocated a
* font to be used as the system font, this font would be
* freed in release
. Also,to assist the garbage
* collector and minimize the amount of memory that is not
* reclaimed when the programmer keeps a reference to a
* disposed device, all fields except the handle are zero'd.
* The handle is needed by destroy
.
*
destroy
.
*
* @see Device#dispose
* @see #destroy
*/
@Override
protected void release () {
try (ExceptionStash exceptions = new ExceptionStash ()) {
try {
sendEvent (SWT.Dispose, new Event ());
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
for (Shell shell : getShells ()) {
try {
if (!shell.isDisposed ()) shell.dispose ();
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
}
try {
if (tray != null) tray.dispose ();
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
tray = null;
try {
if (taskBar != null) taskBar.dispose ();
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
taskBar = null;
for (;;) {
try {
if (!readAndDispatch ()) break;
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
}
if (disposeList != null) {
for (Runnable next : disposeList) {
if (next == null) continue;
try {
next.run ();
} catch (Error | RuntimeException ex) {
exceptions.stash (ex);
}
}
}
disposeList = null;
synchronizer.releaseSynchronizer ();
synchronizer = null;
releaseDisplay ();
super.release ();
}
}
void releaseDisplay () {
if (embeddedHwnd != 0) {
OS.PostMessage (embeddedHwnd, SWT_DESTROY, 0, 0);
}
/* Free custom icons */
sizeToSearchIconHandle.values().forEach(handle -> OS.DestroyIcon(handle));
sizeToCancelIconHandle.values().forEach(handle -> OS.DestroyIcon(handle));
sizeToSearchIconHandle.clear();
sizeToCancelIconHandle.clear();
/* Release XP Themes */
resetThemes();
if (menuBarBorderPen != 0) OS.DeleteObject (menuBarBorderPen);
menuBarBorderPen = 0;
/* Unhook the message hook */
if (msgHook != 0) OS.UnhookWindowsHookEx (msgHook);
msgHook = 0;
/* Unhook the filter hook */
if (filterHook != 0) OS.UnhookWindowsHookEx (filterHook);
filterHook = 0;
msgFilterCallback.dispose ();
msgFilterCallback = null;
msgFilterProc = 0;
/* Unhook the idle hook */
if (idleHook != 0) OS.UnhookWindowsHookEx (idleHook);
idleHook = 0;
foregroundIdleCallback.dispose ();
foregroundIdleCallback = null;
foregroundIdleProc = 0;
/* Stop the settings timer */
OS.KillTimer (hwndMessage, SETTINGS_ID);
/* Destroy the message only HWND */
if (hwndMessage != 0) OS.DestroyWindow (hwndMessage);
hwndMessage = 0;
messageCallback.dispose ();
messageCallback = null;
messageProc = 0;
/* Unregister the SWT window class */
long hHeap = OS.GetProcessHeap ();
long hInstance = OS.GetModuleHandle (null);
OS.UnregisterClass (windowClass, hInstance);
/* Unregister the SWT drop shadow and CS_OWNDC window class */
OS.UnregisterClass (windowShadowClass, hInstance);
OS.UnregisterClass (windowOwnDCClass, hInstance);
windowClass = windowShadowClass = windowOwnDCClass = null;
windowCallback.dispose ();
windowCallback = null;
windowProc = 0;
/* Release the System fonts */
systemFont = null;
lfSystemFont = null;
/* Release the System Images */
if (errorImage != null) errorImage.dispose ();
if (infoImage != null) infoImage.dispose ();
if (questionImage != null) questionImage.dispose ();
if (warningIcon != null) warningIcon.dispose ();
errorImage = infoImage = questionImage = warningIcon = null;
/* Release the System Cursors */
for (Cursor cursor : cursors) {
if (cursor != null) cursor.dispose ();
}
cursors = null;
/* Release Acquired Resources */
if (resources != null) {
for (Resource resource : resources) {
if (resource != null) resource.dispose ();
}
resources = null;
}
/* Release Custom Colors for ChooseColor */
if (lpCustColors != 0) OS.HeapFree (hHeap, 0, lpCustColors);
lpCustColors = 0;
/* Uninitialize OLE */
OS.OleUninitialize ();
/* Uninitialize buffered painting */
OS.BufferedPaintUnInit ();
/* Release references */
thread = null;
msg = hookMsg = null;
keyboard = null;
modalDialog = null;
modalShells = null;
data = null;
keys = null;
values = null;
bars = popups = null;
timerIds = null;
lastHittestControl = null;
imageList = toolImageList = toolHotImageList = toolDisabledImageList = null;
timerList = null;
tableBuffer = null;
eventTable = filterTable = null;
items = null;
clickRect = null;
monitors = null;
touchSources = null;
/* Release handles */
threadId = 0;
}
void releaseImageList (ImageList list) {
int i = 0;
int length = imageList.length;
while (i < length) {
if (imageList [i] == list) {
if (list.removeRef () > 0) return;
list.dispose ();
System.arraycopy (imageList, i + 1, imageList, i, --length - i);
imageList [length] = null;
for (int j=0; j-
*
- ERROR_NULL_ARGUMENT - if the listener is null *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
SWT
.
*
* @param eventType the type of event to listen for
* @param listener the listener which should no longer be notified
*
* @exception IllegalArgumentException -
*
- ERROR_NULL_ARGUMENT - if the listener is null *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_NULL_ARGUMENT - if the point is null *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Applications may have associated arbitrary objects with the
* receiver in this fashion. If the objects stored in the
* properties need to be notified when the display is disposed
* of, it is the application's responsibility provide a
* disposeExec()
handler which does so.
*
-
*
- ERROR_NULL_ARGUMENT - if the key is null *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* Applications may put arbitrary objects in this field. If
* the object stored in the display specific data needs to
* be notified when the display is disposed of, it is the
* application's responsibility provide a
* disposeExec()
handler which does so.
*
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
* The application name can be used in several ways, * depending on the platform and tools being used. * Accessibility tools could ask for the application * name. On Windows, if the application name is set * to any value other than "SWT" (case insensitive), * it is used to set the application user model ID * which is used by the OS for taskbar grouping. *
*
* Specifying null
for the name clears it.
*
null
*/
public static void setAppName (String name) {
APP_NAME = name;
}
/**
* Sets the application version to the argument.
*
* @param version the new app version
*
* @since 3.6
*/
public static void setAppVersion (String version) {
APP_VERSION = version;
}
void setModalDialog(Dialog modalDailog) {
this.modalDialog = modalDailog;
for (Shell shell : getShells()) {
shell.updateModal();
}
}
void setModalShell (Shell shell) {
if (modalShells == null) modalShells = new Shell [4];
int index = 0, length = modalShells.length;
while (index < length) {
if (modalShells [index] == shell) return;
if (modalShells [index] == null) break;
index++;
}
if (index == length) {
Shell [] newModalShells = new Shell [length + 4];
System.arraycopy (modalShells, 0, newModalShells, 0, length);
modalShells = newModalShells;
}
modalShells [index] = shell;
for (Shell activeShell : getShells ()) {
activeShell.updateModal ();
}
}
/**
* Sets the synchronizer used by the display to be
* the argument, which can not be null.
*
* @param synchronizer the new synchronizer for the display (must not be null)
*
* @exception IllegalArgumentException -
*
- ERROR_NULL_ARGUMENT - if the synchronizer is null *
-
*
- ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver *
- ERROR_DEVICE_DISPOSED - if the receiver has been disposed *
- ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message *
* The default SWT error handling policy is to rethrow exceptions.
*
* @param runtimeExceptionHandler new exception handler to be registered.
* @since 3.106
*/
public final void setRuntimeExceptionHandler (Consumer
* The default SWT error handling policy is to rethrow exceptions.
*
* @param errorHandler new error handler to be registered.
* @since 3.106
*/
public final void setErrorHandler (Consumer
* Note that at the time the runnable is invoked, widgets
* that have the receiver as their display may have been
* disposed. Therefore, it is necessary to check for this
* case inside the runnable before accessing the widget.
*
* Note that at the time the callable is invoked, widgets that have the receiver
* as their display may have been disposed. Therefore, it is necessary to check
* for this case inside the callable before accessing the widget.
*
* Any exception that is thrown from the callable is re-thrown in the calling
* thread. Note: The exception retains its original stack trace from the
* throwing thread. The call to {@code syncCall} will not be present in the
* stack trace.
*
* Note that at the time the runnable is invoked, widgets
* that have the receiver as their display may have been
* disposed. Therefore, it is necessary to check for this
* case inside the runnable before accessing the widget.
*
* Note: This functionality is only available on Windows. Calling this
* method on other operating system will always return false.
*
* @since 3.127
*/
public boolean isRescalingAtRuntime() {
return rescalingAtRuntime;
}
/**
* Activates or deactivates rescaling of shells at runtime whenever the DPI
* scaling of the shell's monitor changes. This is only safe to call as long as
* no shell has been created for this display. When changing the value after a
* shell has been created for this display, the effect is undefined.
*
* Note: This functionality is only available on Windows. Calling this
* method on other operating system will have no effect.
*
* @param activate whether rescaling shall be activated or deactivated
* @return whether activating or deactivating the rescaling was successful
* @since 3.127
*/
public boolean setRescalingAtRuntime(boolean activate) {
int desiredApiAwareness = activate ? OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 : OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
if (setDPIAwareness(desiredApiAwareness)) {
rescalingAtRuntime = activate;
// dispose a existing font registry for the default display
SWTFontProvider.disposeFontRegistry(this);
return true;
}
return false;
}
private boolean setDPIAwareness(int desiredDpiAwareness) {
if (OS.WIN32_BUILD < OS.WIN32_BUILD_WIN10_1607) {
System.err.println("***WARNING: the OS version does not support setting DPI awareness.");
return false;
}
if (desiredDpiAwareness == OS.GetThreadDpiAwarenessContext()) {
return true;
}
if (desiredDpiAwareness == OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
// "Per Monitor V2" only available in more recent Windows version
boolean perMonitorV2Available = OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1809;
if (!perMonitorV2Available) {
System.err.println("***WARNING: the OS version does not support DPI awareness mode PerMonitorV2.");
return false;
}
}
long setDpiAwarenessResult = OS.SetThreadDpiAwarenessContext(desiredDpiAwareness);
if (setDpiAwarenessResult == 0L) {
System.err.println("***WARNING: setting DPI awareness failed.");
return false;
}
return true;
}
private Monitor getContainingMonitor(int x, int y) {
Monitor[] monitors = getMonitors();
for (Monitor currentMonitor : monitors) {
Rectangle clientArea = currentMonitor.getClientArea();
if (clientArea.contains(x, y)) {
return currentMonitor;
}
}
return getPrimaryMonitor();
}
private Monitor getContainingMonitor(int x, int y, int width, int height) {
Rectangle rectangle = new Rectangle(x, y, width, height);
Monitor[] monitors = getMonitors();
Monitor selectedMonitor = getPrimaryMonitor();
int highestArea = 0;
for (Monitor currentMonitor : monitors) {
Rectangle clientArea = currentMonitor.getClientArea();
Rectangle intersection = clientArea.intersection(rectangle);
int area = intersection.width * intersection.height;
if (area > highestArea) {
selectedMonitor = currentMonitor;
highestArea = area;
}
}
return selectedMonitor;
}
private Monitor getContainingMonitorInPixelsCoordinate(int xInPixels, int yInPixels) {
Monitor[] monitors = getMonitors();
for (Monitor current : monitors) {
Rectangle clientArea = getMonitorClientAreaInPixels(current);
if (clientArea.contains(xInPixels, yInPixels)) {
return current;
}
}
return getPrimaryMonitor();
}
private Rectangle getMonitorClientAreaInPixels(Monitor monitor) {
int zoom = getApplicableMonitorZoom(monitor);
int widthInPixels = DPIUtil.scaleUp(monitor.clientWidth, zoom);
int heightInPixels = DPIUtil.scaleUp(monitor.clientHeight, zoom);
return new Rectangle(monitor.clientX, monitor.clientY, widthInPixels, heightInPixels);
}
private Point getPixelsFromPoint(Monitor monitor, int x, int y) {
int zoom = getApplicableMonitorZoom(monitor);
int mappedX = DPIUtil.scaleUp(x - monitor.clientX, zoom) + monitor.clientX;
int mappedY = DPIUtil.scaleUp(y - monitor.clientY, zoom) + monitor.clientY;
return new Point(mappedX, mappedY);
}
private Point getPointFromPixels(Monitor monitor, int x, int y) {
int zoom = getApplicableMonitorZoom(monitor);
int mappedX = DPIUtil.scaleDown(x - monitor.clientX, zoom) + monitor.clientX;
int mappedY = DPIUtil.scaleDown(y - monitor.clientY, zoom) + monitor.clientY;
return new Point(mappedX, mappedY);
}
}
null
.
* @since 3.106
*/
public final Consumernull
.
* @since 3.106
*/
public final Consumertrue
if an event requiring dispatching was placed on the queue.
*
* @exception SWTException
*
*
* @see #wake
*/
public boolean sleep () {
checkDevice ();
if (!synchronizer.isMessagesEmpty()) return true;
sendPreExternalEventDispatchEvent ();
boolean result = OS.WaitMessage ();
sendPostExternalEventDispatchEvent ();
return result;
}
/**
* Causes the run()
method of the runnable to
* be invoked by the user-interface thread at the next
* reasonable opportunity. The thread which calls this method
* is suspended until the runnable completes. Specifying null
* as the runnable simply wakes the user-interface thread.
* null
*
* @exception SWTException
*
*
* @see #asyncExec
*/
public void syncExec (Runnable runnable) {
Synchronizer synchronizer;
synchronized (Device.class) {
if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
synchronizer = this.synchronizer;
}
synchronizer.syncExec (runnable);
}
/**
* Calls the callable on the user-interface thread at the next reasonable
* opportunity, and returns the its result from this method. The thread which
* calls this method is suspended until the callable completes.
* ERROR_DEVICE_DISPOSED
- if the receiver
* has been disposed
* @exception E An exception that is thrown by the callable on the
* user-interface thread, and re-thrown on the calling
* thread
*
* @see #syncExec(Runnable)
* @see SwtCallable#call()
* @since 3.118
*/
public run()
method of the runnable to
* be invoked by the user-interface thread after the specified
* number of milliseconds have elapsed. If milliseconds is less
* than zero, the runnable is not executed.
*
*
* @exception SWTException
*
*
* @see #asyncExec
*/
public void timerExec (int milliseconds, Runnable runnable) {
checkDevice ();
if (runnable == null) error (SWT.ERROR_NULL_ARGUMENT);
if (timerList == null) timerList = new Runnable [4];
if (timerIds == null) timerIds = new long [4];
int index = 0;
while (index < timerList.length) {
if (timerList [index] == runnable) break;
index++;
}
long timerId = 0;
if (index != timerList.length) {
timerId = timerIds [index];
if (milliseconds < 0) {
OS.KillTimer (hwndMessage, timerId);
timerList [index] = null;
timerIds [index] = 0;
return;
}
} else {
if (milliseconds < 0) return;
index = 0;
while (index < timerList.length) {
if (timerList [index] == null) break;
index++;
}
timerId = nextTimerId++;
if (index == timerList.length) {
Runnable [] newTimerList = new Runnable [timerList.length + 4];
System.arraycopy (timerList, 0, newTimerList, 0, timerList.length);
timerList = newTimerList;
long [] newTimerIds = new long [timerIds.length + 4];
System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
timerIds = newTimerIds;
}
}
long newTimerID = OS.SetTimer (hwndMessage, timerId, milliseconds, 0);
if (newTimerID != 0) {
timerList [index] = runnable;
timerIds [index] = newTimerID;
}
}
boolean translateAccelerator (MSG msg, Control control) {
accelKeyHit = true;
boolean result = control.translateAccelerator (msg);
accelKeyHit = false;
return result;
}
static int translateKey (int key) {
for (int[] element : KeyTable) {
if (element [0] == key) return element [1];
}
return 0;
}
boolean translateMnemonic (MSG msg, Control control) {
switch (msg.message) {
case OS.WM_CHAR:
case OS.WM_SYSCHAR:
return control.translateMnemonic (msg);
}
return false;
}
boolean translateTraversal (MSG msg, Control control) {
switch (msg.message) {
case OS.WM_KEYDOWN:
switch ((int)msg.wParam) {
case OS.VK_RETURN:
case OS.VK_ESCAPE:
case OS.VK_TAB:
case OS.VK_UP:
case OS.VK_DOWN:
case OS.VK_LEFT:
case OS.VK_RIGHT:
case OS.VK_PRIOR:
case OS.VK_NEXT:
return control.translateTraversal (msg);
}
break;
case OS.WM_SYSKEYDOWN:
switch ((int)msg.wParam) {
case OS.VK_MENU:
return control.translateTraversal (msg);
}
break;
}
return false;
}
static int untranslateKey (int key) {
for (int[] element : KeyTable) {
if (element [1] == key) return element [0];
}
return 0;
}
/**
* Forces all outstanding paint requests for the display
* to be processed before this method returns.
*
* @exception SWTException
*
*
* @see Control#update()
*/
public void update() {
checkDevice ();
/*
* Feature in Windows. When an application does not remove
* events from the event queue for some time, Windows assumes
* the application is not responding and no longer sends paint
* events to the application. The fix is to detect that the
* application is not responding and call PeekMessage() with
* PM_REMOVE to tell Windows that the application is ready
* to dispatch events. Note that the message does not have
* to be found or dispatched in order to wake Windows up.
*
* NOTE: This allows other cross thread messages to be delivered,
* most notably WM_ACTIVATE.
*/
if (OS.IsHungAppWindow (hwndMessage)) {
MSG msg = new MSG ();
int flags = OS.PM_REMOVE | OS.PM_NOYIELD;
OS.PeekMessage (msg, hwndMessage, SWT_NULL, SWT_NULL, flags);
}
for (Shell shell : getShells ()) {
if (!shell.isDisposed ()) shell.update (true);
}
}
/**
* If the receiver's user-interface thread was sleep
ing,
* causes it to be awakened and start running again. Note that this
* method may be called from any thread.
*
* @exception SWTException
*
*
* @see #sleep
*/
public void wake () {
synchronized (Device.class) {
if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
if (thread == Thread.currentThread ()) return;
wakeThread ();
}
}
void wakeThread () {
OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
}
long windowProc (long hwnd, long msg, long wParam, long lParam) {
Control control = getControl(hwnd);
if (control != null) {
return control.windowProc (hwnd, (int)msg, wParam, lParam);
}
return OS.DefWindowProc (hwnd, (int)msg, wParam, lParam);
}
int textWidth (String text, long handle) {
long oldFont = 0;
RECT rect = new RECT ();
long hDC = OS.GetDC (handle);
long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
char [] buffer = text.toCharArray ();
OS.DrawText (hDC, buffer, buffer.length, rect, flags);
if (newFont != 0) OS.SelectObject (hDC, oldFont);
OS.ReleaseDC (handle, hDC);
return (rect.right - rect.left);
}
String wrapText (String text, long handle, int width) {
String Lf = "\r\n"; //$NON-NLS-1$
text = withCrLf (text);
int length = text.length ();
if (width <= 0 || length == 0 || length == 1) return text;
StringBuilder result = new StringBuilder ();
int lineStart = 0, lineEnd = 0;
while (lineStart < length) {
lineEnd = text.indexOf (Lf, lineStart);
boolean noLf = lineEnd == -1;
if (noLf) lineEnd = length;
int nextStart = lineEnd + Lf.length ();
while (lineEnd > lineStart + 1 && Character.isWhitespace (text.charAt (lineEnd - 1))) {
lineEnd--;
}
int wordStart = lineStart, wordEnd = lineStart;
int i = lineStart;
while (i < lineEnd) {
int lastStart = wordStart, lastEnd = wordEnd;
wordStart = i;
while (i < lineEnd && !Character.isWhitespace (text.charAt (i))) {
i++;
}
wordEnd = i - 1;
String line = text.substring (lineStart, wordEnd + 1);
int lineWidth = textWidth (line, handle);
while (i < lineEnd && Character.isWhitespace (text.charAt (i))) {
i++;
}
if (lineWidth > width) {
if (lastStart == wordStart) {
while (wordStart < wordEnd) {
line = text.substring (lineStart, wordStart + 1);
lineWidth = textWidth (line, handle);
if (lineWidth >= width) break;
wordStart++;
}
if (wordStart == lastStart) wordStart++;
lastEnd = wordStart - 1;
}
line = text.substring (lineStart, lastEnd + 1);
result.append (line); result.append (Lf);
i = wordStart; lineStart = wordStart; wordEnd = wordStart;
}
}
if (lineStart < lineEnd) {
result.append (text.substring (lineStart, lineEnd));
}
if (!noLf) {
result.append (Lf);
}
lineStart = nextStart;
}
return result.toString ();
}
static String withCrLf (String string) {
/* If the string is empty, return the string. */
int length = string.length ();
if (length == 0) return string;
/*
* Check for an LF or CR/LF and assume the rest of
* the string is formated that way. This will not
* work if the string contains mixed delimiters.
*/
int i = string.indexOf ('\n', 0);
if (i == -1) return string;
if (i > 0 && string.charAt (i - 1) == '\r') {
return string;
}
/*
* The string is formatted with LF. Compute the
* number of lines and the size of the buffer
* needed to hold the result
*/
i++;
int count = 1;
while (i < length) {
if ((i = string.indexOf ('\n', i)) == -1) break;
count++; i++;
}
count += length;
/* Create a new string with the CR/LF line terminator. */
i = 0;
StringBuilder result = new StringBuilder (count);
while (i < length) {
int j = string.indexOf ('\n', i);
if (j == -1) j = length;
result.append (string.substring (i, j));
if ((i = j) < length) {
result.append ("\r\n"); //$NON-NLS-1$
i++;
}
}
return result.toString ();
}
static char [] withCrLf (char [] string) {
/* If the string is empty, return the string. */
int length = string.length;
if (length == 0) return string;
/*
* Check for an LF or CR/LF and assume the rest of
* the string is formated that way. This will not
* work if the string contains mixed delimiters.
* Also, compute the number of lines.
*/
int count = 0;
for (int i = 0; i < string.length; i++) {
if (string [i] == '\n') {
count++;
if (count == 1 && i > 0 && string [i - 1] == '\r') return string;
}
}
if (count == 0) return string;
/*
* The string is formatted with LF.
*/
count += length;
/* Create a new string with the CR/LF line terminator. */
char [] result = new char [count];
for (int i = 0, j = 0; i < length && j < count; i++) {
if (string [i] == '\n') {
result [j++] = '\r';
}
result [j++] = string [i];
}
return result;
}
static boolean isActivateShellOnForceFocus() {
return "true".equals(System.getProperty("org.eclipse.swt.internal.activateShellOnForceFocus", "true")); //$NON-NLS-1$
}
private ThemeData getOrCreateThemeData(int dpi) {
if (themeDataMap.containsKey(dpi)) {
return themeDataMap.get(dpi);
}
ThemeData themeData = new ThemeData(dpi);
themeDataMap.put(dpi, themeData);
return themeData;
}
private class ThemeData {
private long hButtonTheme;
private long hButtonThemeDark;
private long hEditTheme;
private long hExplorerBarTheme;
private long hScrollBarTheme;
private long hScrollBarThemeDark;
private long hTabTheme;
private int dpi;
private ThemeData(int dpi) {
this.dpi = dpi;
}
long hButtonTheme () {
if (hButtonTheme != 0) return hButtonTheme;
final char[] themeName = "BUTTON\0".toCharArray();
return hButtonTheme = openThemeData(themeName);
}
long hButtonThemeDark () {
if (hButtonThemeDark != 0) return hButtonThemeDark;
final char[] themeName = "Darkmode_Explorer::BUTTON\0".toCharArray();
return hButtonThemeDark = openThemeData(themeName);
}
long hEditTheme () {
if (hEditTheme != 0) return hEditTheme;
final char[] themeName = "EDIT\0".toCharArray();
return hEditTheme = openThemeData(themeName);
}
long hExplorerBarTheme () {
if (hExplorerBarTheme != 0) return hExplorerBarTheme;
final char[] themeName = "EXPLORERBAR\0".toCharArray();
return hExplorerBarTheme = openThemeData(themeName);
}
long hScrollBarTheme () {
if (hScrollBarTheme != 0) return hScrollBarTheme;
final char[] themeName = "SCROLLBAR\0".toCharArray();
return hScrollBarTheme = openThemeData(themeName);
}
long hScrollBarThemeDark () {
if (hScrollBarThemeDark != 0) return hScrollBarThemeDark;
final char[] themeName = "Darkmode_Explorer::SCROLLBAR\0".toCharArray();
return hScrollBarThemeDark = openThemeData(themeName);
}
long hTabTheme () {
if (hTabTheme != 0) return hTabTheme;
final char[] themeName = "TAB\0".toCharArray();
return hTabTheme = openThemeData(themeName);
}
public void reset() {
if (hButtonTheme != 0) {
OS.CloseThemeData (hButtonTheme);
hButtonTheme = 0;
}
if (hButtonThemeDark != 0) {
OS.CloseThemeData (hButtonThemeDark);
hButtonThemeDark = 0;
}
if (hEditTheme != 0) {
OS.CloseThemeData (hEditTheme);
hEditTheme = 0;
}
if (hExplorerBarTheme != 0) {
OS.CloseThemeData (hExplorerBarTheme);
hExplorerBarTheme = 0;
}
if (hScrollBarTheme != 0) {
OS.CloseThemeData (hScrollBarTheme);
hScrollBarTheme = 0;
}
if (hScrollBarThemeDark != 0) {
OS.CloseThemeData (hScrollBarThemeDark);
hScrollBarThemeDark = 0;
}
if (hTabTheme != 0) {
OS.CloseThemeData (hTabTheme);
hTabTheme = 0;
}
}
private long openThemeData(final char[] themeName) {
return OS.OpenThemeData(hwndMessage, themeName, dpi);
}
}
/**
* {@return whether rescaling of shells at runtime when the DPI scaling of a
* shell's monitor changes is activated for this device}
*