X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Fwidgets%2FDisplay.java;fp=bundles%2Forg.eclipse.swt.win32.win32.x86_64%2Fsrc%2Forg%2Feclipse%2Fswt%2Fwidgets%2FDisplay.java;h=832317961c9460ba2fd45853b172f2551a31e840;hb=db618b088560ad9a524dade82a3847f8d08bfb7c;hp=0000000000000000000000000000000000000000;hpb=930da66f9b2d7d1acba3e5dc805a323933abb780;p=simantics%2Fplatform.git diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java new file mode 100644 index 000000000..832317961 --- /dev/null +++ b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Display.java @@ -0,0 +1,4985 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 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 + *******************************************************************************/ +package org.eclipse.swt.widgets; + +import java.net.*; +import java.util.*; +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. + *
+ * 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 Display
+ * instance is distinguished as the user-interface thread
+ * for that display.
+ *
Widget
and its subclasses), may only be called
+ * from the thread. (To support multi-threaded user-interface
+ * applications, class Display
provides inter-thread
+ * communication methods which allow threads other than the
+ * user-interface thread to request that it perform operations
+ * on their behalf.)
+ * 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.
+ *
+ * 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 { + + /** + * 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$ + + /* 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 + + /* Widget Table */ + int freeSlot; + int [] indexTable; + Control lastControl, lastGetControl; + long lastHwnd, lastGetHwnd; + Control [] controlTable; + static final int GROW_SIZE = 1024; + static final int SWT_OBJECT_INDEX = OS.GlobalAddAtom (new TCHAR (0, "SWT_OBJECT_INDEX", true)); //$NON-NLS-1$ + + /* Startup info */ + static STARTUPINFO lpStartupInfo; + static { + lpStartupInfo = new STARTUPINFO (); + lpStartupInfo.cb = STARTUPINFO.sizeof; + OS.GetStartupInfo (lpStartupInfo); + } + + /* XP Themes */ + long hButtonTheme, hEditTheme, hExplorerBarTheme, hScrollBarTheme, hTabTheme; + static final char [] BUTTON = new char [] {'B', 'U', 'T', 'T', 'O', 'N', 0}; + static final char [] EDIT = new char [] {'E', 'D', 'I', 'T', 0}; + static final char [] EXPLORER = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 0}; + static final char [] EXPLORERBAR = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 'B', 'A', 'R', 0}; + static final char [] SCROLLBAR = new char [] {'S', 'C', 'R', 'O', 'L', 'L', 'B', 'A', 'R', 0}; + static final char [] LISTVIEW = new char [] {'L', 'I', 'S', 'T', 'V', 'I', 'E', 'W', 0}; + static final char [] TAB = new char [] {'T', 'A', 'B', 0}; + static final char [] TREEVIEW = new char [] {'T', 'R', 'E', 'E', 'V', 'I', 'E', 'W', 0}; + + /* Custom icons */ + long hIconSearch; + long hIconCancel; + + /* Focus */ + int focusEvent; + Control focusControl; + boolean fixFocus; + + /* 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 = new Synchronizer (this); + Consumer+ * 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 SWTExceptionSWT
. When the event does occur,
+ * the listener is notified by sending it the handleEvent()
+ * message.
+ *
+ * Setting the type of an event to SWT.None
from
+ * within the handleEvent()
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.
+ *
SWT
.
+ * When the event does occur in the display, the listener is notified by
+ * sending it the handleEvent()
message.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should be notified when the event occurs
+ *
+ * @exception IllegalArgumentException 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
+ * IMPORTANT: See the comment in Widget.checkSubclass()
.
+ *
+ * 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 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 SWTExceptionWidget
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 SWTExceptionWidget
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 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 (int i=0; inull
if there is no application menu bar for the platform.
+ *
+ * @return the application menu bar, or null
+ *
+ * @exception SWTException null
+ *
+ * @exception SWTException
+ * 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.
+ *
+ * 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.
+ *
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 null
+ *
+ * @exception SWTException + * Note: This operation is a hint and is not supported on + * platforms that do not have this concept. + *
+ * + * @return the high contrast mode + * + * @exception SWTExceptiontrue
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;
+ /*
+ * Win10 onwards we can read the Dark Theme from the OS registry.
+ */
+ if (OS.WIN32_VERSION >= OS.VERSION (10, 0)) {
+ try {
+ int result = OS.readRegistryDword(OS.HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme");
+ isDarkTheme = (result == 0);
+ } catch (Exception e) {
+ // Registry entry not found
+ }
+ }
+ 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;
+}
+
+int getMessageCount () {
+ /*
+ * On Windows10 (update 18272), an NPE is seen in below code which leads to a
+ * possible crash, adding a null check for synchronizer instance. For more
+ * details refer bug 540762
+ */
+ if (synchronizer != null) return synchronizer.getMessageCount ();
+ return 0;
+}
+
+
+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);
+ monitor.setBounds (DPIUtil.autoScaleDown (boundsInPixels));
+ Rectangle clientAreaInPixels = new Rectangle (lpmi.rcWork_left, lpmi.rcWork_top, lpmi.rcWork_right - lpmi.rcWork_left, lpmi.rcWork_bottom - lpmi.rcWork_top);
+ monitor.setClientArea (DPIUtil.autoScaleDown (clientAreaInPixels));
+ if (OS.WIN32_VERSION >= OS.VERSION (6, 3)) {
+ 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;
+ /*
+ * 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;
+ } else {
+ monitor.zoom = getDeviceZoom ();
+ }
+ return monitor;
+}
+
+/**
+ * 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$
+ long lpfnEnum = callback.getAddress ();
+ if (lpfnEnum == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+ OS.EnumDisplayMonitors (0, null, lpfnEnum, 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 ();
+ if (embeddedProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+ 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 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 SWTExceptionSWT
. 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 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 + * 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 SWTExceptionSWT
. 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 null
on platforms where no menu is provided for the application.
+ *
+ * @return the system menu, or null
+ *
+ * @exception SWTException null
+ *
+ * @exception SWTException null
+ *
+ * @exception SWTException true
if a touch-aware input device is detected, or false
otherwise
+ *
+ * @exception SWTException
+ * 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.
+ *
+ * This method is called after create
.
+ *
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.
+ *
+ *
+ * @param hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+@Override
+public void internal_dispose_GC (long hDC, GCData data) {
+ OS.ReleaseDC (0, hDC);
+}
+
+boolean isXMouseActive () {
+ /*
+ * NOTE: X-Mouse is active when bit 1 of the UserPreferencesMask is set.
+ */
+ boolean xMouseActive = false;
+ try {
+ int result = OS.readRegistryDword(OS.HKEY_CURRENT_USER, "Control Panel\\Desktop", "UserPreferencesMask");
+ xMouseActive = (result & 0x01) != 0;
+ } catch (Exception e) {
+ // Registry entry not found
+ }
+ return xMouseActive;
+}
+
+boolean isValidThread () {
+ return thread == Thread.currentThread ();
+}
+
+/**
+ * Maps a point from one coordinate system to another.
+ * When the control is null, coordinates are mapped to
+ * the display.
+ * + * 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 + * 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 + * 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 + * 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 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:
+ *
Either one of:
+ *SWT
Optional (on some platforms):
+ *SWT
+ * MouseDown, MouseUp
+ *The following fields in the Event
apply:
+ *
MouseMove
+ *The following fields in the Event
apply:
+ *
MouseWheel
+ *The following fields in the Event
apply:
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 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 () {
+ sendEvent (SWT.Dispose, new Event ());
+ Shell [] shells = getShells ();
+ for (int i=0; iSWT
.
+ *
+ * @param eventType the type of event to listen for
+ * @param listener the listener which should no longer be notified
+ *
+ * @exception IllegalArgumentException
+ * 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.
+ *
+ * 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.
+ *
+ * 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. + * @see AppUserModelID (Windows) + *
+ * 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;
+ Shell [] shells = getShells ();
+ for (int i=0; i
+ * 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 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.
+ * 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 (getMessageCount () != 0) 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);
+}
+
+/**
+ * Causes the 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 i=0; i
+ *
+ *
+ * @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) {
+ if (lastControl != null && lastHwnd == hwnd) {
+ return lastControl.windowProc (hwnd, (int)msg, wParam, lParam);
+ }
+ int index = (int)OS.GetProp (hwnd, SWT_OBJECT_INDEX) - 1;
+ if (0 <= index && index < controlTable.length) {
+ Control control = controlTable [index];
+ if (control != null) {
+ lastHwnd = hwnd;
+ lastControl = control;
+ 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;
+}
+
+}