PageRenderTime 82ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Display.d

https://bitbucket.org/torhus/dwt2
D | 4714 lines | 2816 code | 269 blank | 1629 comment | 611 complexity | a821669b0ad42c1020d89f2e221b34ff MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2008 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. * Port to the D programming language:
  11. * Frank Benoit <benoit@tionex.de>
  12. *******************************************************************************/
  13. module org.eclipse.swt.widgets.Display;
  14. import org.eclipse.swt.SWT;
  15. import org.eclipse.swt.SWTError;
  16. import org.eclipse.swt.SWTException;
  17. import org.eclipse.swt.graphics.Color;
  18. import org.eclipse.swt.graphics.Cursor;
  19. import org.eclipse.swt.graphics.Device;
  20. import org.eclipse.swt.graphics.DeviceData;
  21. import org.eclipse.swt.graphics.Font;
  22. import org.eclipse.swt.graphics.GC;
  23. import org.eclipse.swt.graphics.GCData;
  24. import org.eclipse.swt.graphics.Image;
  25. import org.eclipse.swt.graphics.ImageData;
  26. import org.eclipse.swt.graphics.PaletteData;
  27. import org.eclipse.swt.graphics.Point;
  28. import org.eclipse.swt.graphics.RGB;
  29. import org.eclipse.swt.graphics.Rectangle;
  30. import org.eclipse.swt.graphics.Resource;
  31. import org.eclipse.swt.internal.ImageList;
  32. import org.eclipse.swt.internal.Library;
  33. import org.eclipse.swt.internal.win32.OS;
  34. import org.eclipse.swt.widgets.Control;
  35. import org.eclipse.swt.widgets.Dialog;
  36. import org.eclipse.swt.widgets.Tray;
  37. import org.eclipse.swt.widgets.Event;
  38. import org.eclipse.swt.widgets.EventTable;
  39. import org.eclipse.swt.widgets.Menu;
  40. import org.eclipse.swt.widgets.MenuItem;
  41. import org.eclipse.swt.widgets.Synchronizer;
  42. import org.eclipse.swt.widgets.Monitor;
  43. import org.eclipse.swt.widgets.Shell;
  44. import org.eclipse.swt.widgets.Listener;
  45. import org.eclipse.swt.widgets.Widget;
  46. import org.eclipse.swt.widgets.TrayItem;
  47. import java.lang.all;
  48. import java.lang.Thread;
  49. /**
  50. * Instances of this class are responsible for managing the
  51. * connection between SWT and the underlying operating
  52. * system. Their most important function is to implement
  53. * the SWT event loop in terms of the platform event model.
  54. * They also provide various methods for accessing information
  55. * about the operating system, and have overall control over
  56. * the operating system resources which SWT allocates.
  57. * <p>
  58. * Applications which are built with SWT will <em>almost always</em>
  59. * require only a single display. In particular, some platforms
  60. * which SWT supports will not allow more than one <em>active</em>
  61. * display. In other words, some platforms do not support
  62. * creating a new display if one already exists that has not been
  63. * sent the <code>dispose()</code> message.
  64. * <p>
  65. * In SWT, the thread which creates a <code>Display</code>
  66. * instance is distinguished as the <em>user-interface thread</em>
  67. * for that display.
  68. * </p>
  69. * The user-interface thread for a particular display has the
  70. * following special attributes:
  71. * <ul>
  72. * <li>
  73. * The event loop for that display must be run from the thread.
  74. * </li>
  75. * <li>
  76. * Some SWT API methods (notably, most of the public methods in
  77. * <code>Widget</code> and its subclasses), may only be called
  78. * from the thread. (To support multi-threaded user-interface
  79. * applications, class <code>Display</code> provides inter-thread
  80. * communication methods which allow threads other than the
  81. * user-interface thread to request that it perform operations
  82. * on their behalf.)
  83. * </li>
  84. * <li>
  85. * The thread is not allowed to construct other
  86. * <code>Display</code>s until that display has been disposed.
  87. * (Note that, this is in addition to the restriction mentioned
  88. * above concerning platform support for multiple displays. Thus,
  89. * the only way to have multiple simultaneously active displays,
  90. * even on platforms which support it, is to have multiple threads.)
  91. * </li>
  92. * </ul>
  93. * Enforcing these attributes allows SWT to be implemented directly
  94. * on the underlying operating system's event model. This has
  95. * numerous benefits including smaller footprint, better use of
  96. * resources, safer memory management, clearer program logic,
  97. * better performance, and fewer overall operating system threads
  98. * required. The down side however, is that care must be taken
  99. * (only) when constructing multi-threaded applications to use the
  100. * inter-thread communication mechanisms which this class provides
  101. * when required.
  102. * </p><p>
  103. * All SWT API methods which may only be called from the user-interface
  104. * thread are distinguished in their documentation by indicating that
  105. * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
  106. * SWT exception.
  107. * </p>
  108. * <dl>
  109. * <dt><b>Styles:</b></dt>
  110. * <dd>(none)</dd>
  111. * <dt><b>Events:</b></dt>
  112. * <dd>Close, Dispose, Settings</dd>
  113. * </dl>
  114. * <p>
  115. * IMPORTANT: This class is <em>not</em> intended to be subclassed.
  116. * </p>
  117. * @see #syncExec
  118. * @see #asyncExec
  119. * @see #wake
  120. * @see #readAndDispatch
  121. * @see #sleep
  122. * @see Device#dispose
  123. * @see <a href="http://www.eclipse.org/swt/snippets/#display">Display snippets</a>
  124. * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
  125. */
  126. public class Display : Device {
  127. /**
  128. * the handle to the OS message queue
  129. * (Warning: This field is platform dependent)
  130. * <p>
  131. * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
  132. * public API. It is marked public only so that it can be shared
  133. * within the packages provided by SWT. It is not available on all
  134. * platforms and should never be accessed from application code.
  135. * </p>
  136. */
  137. public MSG* msg;
  138. /* Windows and Events */
  139. Event [] eventQueue;
  140. //Callback windowCallback;
  141. //int windowProc_;
  142. int threadId;
  143. StringT windowClass_, windowShadowClass;
  144. static mixin(GSHARED(`int WindowClassCount;`));
  145. static const String WindowName = "SWT_Window"; //$NON-NLS-1$
  146. static const String WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$
  147. EventTable eventTable, filterTable;
  148. /* Widget Table */
  149. int freeSlot;
  150. int [] indexTable;
  151. Control lastControl, lastGetControl;
  152. HANDLE lastHwnd;
  153. HWND lastGetHwnd;
  154. Control [] controlTable;
  155. static const int GROW_SIZE = 1024;
  156. private mixin(GSHARED(`static /+const+/ int SWT_OBJECT_INDEX;`));
  157. static const bool USE_PROPERTY = !OS.IsWinCE;
  158. private mixin(GSHARED(`static bool static_this_completed = false;`));
  159. private static void static_this() {
  160. if( static_this_completed ){
  161. return;
  162. }
  163. synchronized {
  164. if( static_this_completed ){
  165. return;
  166. }
  167. static if (USE_PROPERTY) {
  168. SWT_OBJECT_INDEX = OS.GlobalAddAtom (StrToTCHARz("SWT_OBJECT_INDEX")); //$NON-NLS-1$
  169. } else {
  170. SWT_OBJECT_INDEX = 0;
  171. }
  172. static_this_StartupInfo ();
  173. static_this_DeviceFinder ();
  174. static_this_completed = true;
  175. }
  176. }
  177. /* Startup info */
  178. private static mixin(GSHARED(`STARTUPINFO* lpStartupInfo;`));
  179. private static void static_this_StartupInfo (){
  180. static if (!OS.IsWinCE) {
  181. lpStartupInfo = new STARTUPINFO ();
  182. lpStartupInfo.cb = STARTUPINFO.sizeof;
  183. OS.GetStartupInfo (lpStartupInfo);
  184. }
  185. }
  186. /* XP Themes */
  187. HTHEME hButtonTheme_, hEditTheme_, hExplorerBarTheme_, hScrollBarTheme_, hTabTheme_;
  188. static const wchar [] BUTTON = "BUTTON\0"w;
  189. static const wchar [] EDIT = "EDIT\0"w;
  190. static const wchar [] EXPLORER = "EXPLORER\0"w;
  191. static const wchar [] EXPLORERBAR = "EXPLORERBAR\0"w;
  192. static const wchar [] SCROLLBAR = "SCROLLBAR\0"w;
  193. static const wchar [] LISTVIEW = "LISTVIEW\0"w;
  194. static const wchar [] TAB = "TAB\0"w;
  195. static const wchar [] TREEVIEW = "TREEVIEW\0"w;
  196. /* Focus */
  197. int focusEvent;
  198. Control focusControl;
  199. /* Menus */
  200. Menu [] bars, popups;
  201. MenuItem [] items;
  202. /*
  203. * The start value for WM_COMMAND id's.
  204. * Windows reserves the values 0..100.
  205. *
  206. * The SmartPhone SWT resource file reserves
  207. * the values 101..107.
  208. */
  209. static const int ID_START = 108;
  210. /* Filter Hook */
  211. //Callback msgFilterCallback;
  212. //int msgFilterProc_,
  213. HHOOK filterHook;
  214. bool runDragDrop = true, dragCancelled = false;
  215. MSG* hookMsg;
  216. /* Idle Hook */
  217. //Callback foregroundIdleCallback;
  218. //int foregroundIdleProc_;
  219. HHOOK idleHook;
  220. /* Message Hook and Embedding */
  221. bool ignoreNextKey;
  222. //Callback getMsgCallback, embeddedCallback;
  223. int getMsgProc_;
  224. HHOOK msgHook;
  225. HWND embeddedHwnd;
  226. int embeddedProc_;
  227. static const String AWT_WINDOW_CLASS = "SunAwtWindow";
  228. static const short [] ACCENTS = [ cast(short) '~', '`', '\'', '^', '"'];
  229. /* Sync/Async Widget Communication */
  230. Synchronizer synchronizer;
  231. bool runMessages = true, runMessagesInIdle = false, runMessagesInMessageProc = true;
  232. static const String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
  233. static const String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "org.eclipse.swt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$
  234. Thread thread;
  235. /* Display Shutdown */
  236. Runnable [] disposeList;
  237. /* System Tray */
  238. Tray tray;
  239. int nextTrayId;
  240. /* Timers */
  241. int /*long*/ [] timerIds;
  242. Runnable [] timerList;
  243. int /*long*/ nextTimerId = SETTINGS_ID + 1;
  244. static const int SETTINGS_ID = 100;
  245. static const int SETTINGS_DELAY = 2000;
  246. /* Keyboard and Mouse */
  247. RECT* clickRect;
  248. int clickCount, lastTime, lastButton;
  249. HWND lastClickHwnd;
  250. int scrollRemainder;
  251. int lastKey, lastAscii, lastMouse;
  252. bool lastVirtual, lastNull, lastDead;
  253. ubyte [256] keyboard;
  254. bool accelKeyHit, mnemonicKeyHit;
  255. bool lockActiveWindow, captureChanged, xMouse;
  256. /* Tool Tips */
  257. int nextToolTipId;
  258. /* MDI */
  259. bool ignoreRestoreFocus;
  260. Control lastHittestControl;
  261. int lastHittest;
  262. /* Message Only Window */
  263. HWND hwndMessage;
  264. /* System Resources */
  265. LOGFONT* lfSystemFont;
  266. Font systemFont;
  267. Image errorImage, infoImage, questionImage, warningIcon;
  268. Cursor [] cursors;
  269. Resource [] resources;
  270. static const int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;
  271. /* ImageList Cache */
  272. ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList;
  273. /* Custom Colors for ChooseColor */
  274. COLORREF* lpCustColors;
  275. /* Sort Indicators */
  276. Image upArrow, downArrow;
  277. /* Table */
  278. char [] tableBuffer;
  279. NMHDR* hdr;
  280. NMLVDISPINFO* plvfi;
  281. HWND hwndParent;
  282. int columnCount;
  283. bool [] columnVisible;
  284. /* Resize and move recursion */
  285. int resizeCount;
  286. static const int RESIZE_LIMIT = 4;
  287. /* Display Data */
  288. Object data;
  289. String [] keys;
  290. Object [] values;
  291. /* Key Mappings */
  292. static const int [] [] KeyTable = [
  293. /* Keyboard and Mouse Masks */
  294. [OS.VK_MENU, SWT.ALT],
  295. [OS.VK_SHIFT, SWT.SHIFT],
  296. [OS.VK_CONTROL, SWT.CONTROL],
  297. // [OS.VK_????, SWT.COMMAND],
  298. /* NOT CURRENTLY USED */
  299. // [OS.VK_LBUTTON, SWT.BUTTON1],
  300. // [OS.VK_MBUTTON, SWT.BUTTON3],
  301. // [OS.VK_RBUTTON, SWT.BUTTON2],
  302. /* Non-Numeric Keypad Keys */
  303. [OS.VK_UP, SWT.ARROW_UP],
  304. [OS.VK_DOWN, SWT.ARROW_DOWN],
  305. [OS.VK_LEFT, SWT.ARROW_LEFT],
  306. [OS.VK_RIGHT, SWT.ARROW_RIGHT],
  307. [OS.VK_PRIOR, SWT.PAGE_UP],
  308. [OS.VK_NEXT, SWT.PAGE_DOWN],
  309. [OS.VK_HOME, SWT.HOME],
  310. [OS.VK_END, SWT.END],
  311. [OS.VK_INSERT, SWT.INSERT],
  312. /* Virtual and Ascii Keys */
  313. [OS.VK_BACK, SWT.BS],
  314. [OS.VK_RETURN, SWT.CR],
  315. [OS.VK_DELETE, SWT.DEL],
  316. [OS.VK_ESCAPE, SWT.ESC],
  317. [OS.VK_RETURN, SWT.LF],
  318. [OS.VK_TAB, SWT.TAB],
  319. /* Functions Keys */
  320. [OS.VK_F1, SWT.F1],
  321. [OS.VK_F2, SWT.F2],
  322. [OS.VK_F3, SWT.F3],
  323. [OS.VK_F4, SWT.F4],
  324. [OS.VK_F5, SWT.F5],
  325. [OS.VK_F6, SWT.F6],
  326. [OS.VK_F7, SWT.F7],
  327. [OS.VK_F8, SWT.F8],
  328. [OS.VK_F9, SWT.F9],
  329. [OS.VK_F10, SWT.F10],
  330. [OS.VK_F11, SWT.F11],
  331. [OS.VK_F12, SWT.F12],
  332. [OS.VK_F13, SWT.F13],
  333. [OS.VK_F14, SWT.F14],
  334. [OS.VK_F15, SWT.F15],
  335. /* Numeric Keypad Keys */
  336. [OS.VK_MULTIPLY, SWT.KEYPAD_MULTIPLY],
  337. [OS.VK_ADD, SWT.KEYPAD_ADD],
  338. [OS.VK_RETURN, SWT.KEYPAD_CR],
  339. [OS.VK_SUBTRACT, SWT.KEYPAD_SUBTRACT],
  340. [OS.VK_DECIMAL, SWT.KEYPAD_DECIMAL],
  341. [OS.VK_DIVIDE, SWT.KEYPAD_DIVIDE],
  342. [OS.VK_NUMPAD0, SWT.KEYPAD_0],
  343. [OS.VK_NUMPAD1, SWT.KEYPAD_1],
  344. [OS.VK_NUMPAD2, SWT.KEYPAD_2],
  345. [OS.VK_NUMPAD3, SWT.KEYPAD_3],
  346. [OS.VK_NUMPAD4, SWT.KEYPAD_4],
  347. [OS.VK_NUMPAD5, SWT.KEYPAD_5],
  348. [OS.VK_NUMPAD6, SWT.KEYPAD_6],
  349. [OS.VK_NUMPAD7, SWT.KEYPAD_7],
  350. [OS.VK_NUMPAD8, SWT.KEYPAD_8],
  351. [OS.VK_NUMPAD9, SWT.KEYPAD_9],
  352. // [OS.VK_????, SWT.KEYPAD_EQUAL],
  353. /* Other keys */
  354. [OS.VK_CAPITAL, SWT.CAPS_LOCK],
  355. [OS.VK_NUMLOCK, SWT.NUM_LOCK],
  356. [OS.VK_SCROLL, SWT.SCROLL_LOCK],
  357. [OS.VK_PAUSE, SWT.PAUSE],
  358. [OS.VK_CANCEL, SWT.BREAK],
  359. [OS.VK_SNAPSHOT, SWT.PRINT_SCREEN],
  360. // [OS.VK_????, SWT.HELP],
  361. ];
  362. /* Multiple Displays */
  363. static mixin(GSHARED(`Display Default;`));
  364. static mixin(GSHARED(`Display [] Displays;`));
  365. /* Multiple Monitors */
  366. org.eclipse.swt.widgets.Monitor.Monitor[] monitors = null;
  367. int monitorCount = 0;
  368. /* Modality */
  369. Shell [] modalShells;
  370. Dialog modalDialog;
  371. static mixin(GSHARED(`bool TrimEnabled = false;`));
  372. /* Private SWT Window Messages */
  373. static const int SWT_GETACCELCOUNT = OS.WM_APP;
  374. static const int SWT_GETACCEL = OS.WM_APP + 1;
  375. static const int SWT_KEYMSG = OS.WM_APP + 2;
  376. static const int SWT_DESTROY = OS.WM_APP + 3;
  377. static const int SWT_TRAYICONMSG = OS.WM_APP + 4;
  378. static const int SWT_NULL = OS.WM_APP + 5;
  379. static const int SWT_RUNASYNC = OS.WM_APP + 6;
  380. static mixin(GSHARED(`int SWT_TASKBARCREATED;`));
  381. static mixin(GSHARED(`int SWT_RESTORECARET;`));
  382. static mixin(GSHARED(`int DI_GETDRAGIMAGE;`));
  383. /* Workaround for Adobe Reader 7.0 */
  384. int hitCount;
  385. /* Package Name */
  386. static const String PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$
  387. /*
  388. * This code is intentionally commented. In order
  389. * to support CLDC, .class cannot be used because
  390. * it does not compile on some Java compilers when
  391. * they are targeted for CLDC.
  392. */
  393. // static {
  394. // String name = Display.class.getName ();
  395. // int index = name.lastIndexOf ('.');
  396. // PACKAGE_PREFIX = name.substring (0, index + 1);
  397. // }
  398. /*
  399. * TEMPORARY CODE. Install the runnable that
  400. * gets the current display. This code will
  401. * be removed in the future.
  402. */
  403. private static void static_this_DeviceFinder () {
  404. DeviceFinder = new class() Runnable {
  405. public void run () {
  406. Device device = getCurrent ();
  407. if (device is null) {
  408. device = getDefault ();
  409. }
  410. setDevice (device);
  411. }
  412. };
  413. }
  414. /*
  415. * TEMPORARY CODE.
  416. */
  417. static void setDevice (Device device) {
  418. static_this();
  419. CurrentDevice = device;
  420. }
  421. /**
  422. * Constructs a new instance of this class.
  423. * <p>
  424. * Note: The resulting display is marked as the <em>current</em>
  425. * display. If this is the first display which has been
  426. * constructed since the application started, it is also
  427. * marked as the <em>default</em> display.
  428. * </p>
  429. *
  430. * @exception SWTException <ul>
  431. * <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
  432. * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
  433. * </ul>
  434. *
  435. * @see #getCurrent
  436. * @see #getDefault
  437. * @see Widget#checkSubclass
  438. * @see Shell
  439. */
  440. public this () {
  441. this (null);
  442. }
  443. /**
  444. * Constructs a new instance of this class using the parameter.
  445. *
  446. * @param data the device data
  447. */
  448. public this (DeviceData data) {
  449. static_this();
  450. msg = new MSG();
  451. hookMsg = new MSG();
  452. super (data);
  453. synchronizer = new Synchronizer (this);
  454. cursors = new Cursor [SWT.CURSOR_HAND + 1];
  455. }
  456. Control _getFocusControl () {
  457. return findControl (OS.GetFocus ());
  458. }
  459. void addBar (Menu menu) {
  460. if (bars is null) bars = new Menu [4];
  461. int length_ = bars.length;
  462. for (int i=0; i<length_; i++) {
  463. if (bars [i] is menu) return;
  464. }
  465. int index = 0;
  466. while (index < length_) {
  467. if (bars [index] is null) break;
  468. index++;
  469. }
  470. if (index is length_) {
  471. Menu [] newBars = new Menu [length_ + 4];
  472. System.arraycopy (bars, 0, newBars, 0, length_);
  473. bars = newBars;
  474. }
  475. bars [index] = menu;
  476. }
  477. void addControl (HANDLE handle, Control control) {
  478. if (handle is null) return;
  479. if (freeSlot is -1) {
  480. int length_ = (freeSlot = indexTable.length) + GROW_SIZE;
  481. int [] newIndexTable = new int [length_];
  482. Control [] newControlTable = new Control [length_];
  483. System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
  484. System.arraycopy (controlTable, 0, newControlTable, 0, freeSlot);
  485. for (int i=freeSlot; i<length_-1; i++) newIndexTable [i] = i + 1;
  486. newIndexTable [length_ - 1] = -1;
  487. indexTable = newIndexTable;
  488. controlTable = newControlTable;
  489. }
  490. static if (USE_PROPERTY) {
  491. OS.SetProp (handle, cast(wchar*)SWT_OBJECT_INDEX, cast(void*) freeSlot + 1);
  492. } else {
  493. OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, freeSlot + 1);
  494. }
  495. int oldSlot = freeSlot;
  496. freeSlot = indexTable [oldSlot];
  497. indexTable [oldSlot] = -2;
  498. controlTable [oldSlot] = control;
  499. }
  500. /**
  501. * Adds the listener to the collection of listeners who will
  502. * be notified when an event of the given type occurs anywhere
  503. * in a widget. The event type is one of the event constants
  504. * defined in class <code>SWT</code>. When the event does occur,
  505. * the listener is notified by sending it the <code>handleEvent()</code>
  506. * message.
  507. * <p>
  508. * Setting the type of an event to <code>SWT.None</code> from
  509. * within the <code>handleEvent()</code> method can be used to
  510. * change the event type and stop subsequent Java listeners
  511. * from running. Because event filters run before other listeners,
  512. * event filters can both block other listeners and set arbitrary
  513. * fields within an event. For this reason, event filters are both
  514. * powerful and dangerous. They should generally be avoided for
  515. * performance, debugging and code maintenance reasons.
  516. * </p>
  517. *
  518. * @param eventType the type of event to listen for
  519. * @param listener the listener which should be notified when the event occurs
  520. *
  521. * @exception IllegalArgumentException <ul>
  522. * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
  523. * </ul>
  524. * @exception SWTException <ul>
  525. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  526. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  527. * </ul>
  528. *
  529. * @see Listener
  530. * @see SWT
  531. * @see #removeFilter
  532. * @see #removeListener
  533. *
  534. * @since 3.0
  535. */
  536. public void addFilter (int eventType, Listener listener) {
  537. checkDevice ();
  538. if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
  539. if (filterTable is null) filterTable = new EventTable ();
  540. filterTable.hook (eventType, listener);
  541. }
  542. /**
  543. * Adds the listener to the collection of listeners who will
  544. * be notified when an event of the given type occurs. The event
  545. * type is one of the event constants defined in class <code>SWT</code>.
  546. * When the event does occur in the display, the listener is notified by
  547. * sending it the <code>handleEvent()</code> message.
  548. *
  549. * @param eventType the type of event to listen for
  550. * @param listener the listener which should be notified when the event occurs
  551. *
  552. * @exception IllegalArgumentException <ul>
  553. * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
  554. * </ul>
  555. * @exception SWTException <ul>
  556. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  557. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  558. * </ul>
  559. *
  560. * @see Listener
  561. * @see SWT
  562. * @see #removeListener
  563. *
  564. * @since 2.0
  565. */
  566. public void addListener (int eventType, Listener listener) {
  567. checkDevice ();
  568. if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
  569. if (eventTable is null) eventTable = new EventTable ();
  570. eventTable.hook (eventType, listener);
  571. }
  572. void addMenuItem (MenuItem item) {
  573. if (items is null) items = new MenuItem [64];
  574. for (int i=0; i<items.length; i++) {
  575. if (items [i] is null) {
  576. item.id = i + ID_START;
  577. items [i] = item;
  578. return;
  579. }
  580. }
  581. item.id = items.length + ID_START;
  582. MenuItem [] newItems = new MenuItem [items.length + 64];
  583. newItems [items.length] = item;
  584. System.arraycopy (items, 0, newItems, 0, items.length);
  585. items = newItems;
  586. }
  587. void addPopup (Menu menu) {
  588. if (popups is null) popups = new Menu [4];
  589. int length_ = popups.length;
  590. for (int i=0; i<length_; i++) {
  591. if (popups [i] is menu) return;
  592. }
  593. int index = 0;
  594. while (index < length_) {
  595. if (popups [index] is null) break;
  596. index++;
  597. }
  598. if (index is length_) {
  599. Menu [] newPopups = new Menu [length_ + 4];
  600. System.arraycopy (popups, 0, newPopups, 0, length_);
  601. popups = newPopups;
  602. }
  603. popups [index] = menu;
  604. }
  605. int asciiKey (int key) {
  606. static if (OS.IsWinCE) return 0;
  607. /* Get the current keyboard. */
  608. for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
  609. if (!OS.GetKeyboardState (keyboard.ptr)) return 0;
  610. /* Translate the key to ASCII or UNICODE using the virtual keyboard */
  611. static if (OS.IsUnicode) {
  612. wchar result;
  613. if (OS.ToUnicode (key, key, keyboard.ptr, &result, 1, 0) is 1) return result;
  614. } else {
  615. short [] result = new short [1];
  616. if (OS.ToAscii (key, key, keyboard, result, 0) is 1) return result [0];
  617. }
  618. return 0;
  619. }
  620. /**
  621. * Causes the <code>run()</code> method of the runnable to
  622. * be invoked by the user-interface thread at the next
  623. * reasonable opportunity. The caller of this method continues
  624. * to run in parallel, and is not notified when the
  625. * runnable has completed. Specifying <code>null</code> as the
  626. * runnable simply wakes the user-interface thread when run.
  627. * <p>
  628. * Note that at the time the runnable is invoked, widgets
  629. * that have the receiver as their display may have been
  630. * disposed. Therefore, it is necessary to check for this
  631. * case inside the runnable before accessing the widget.
  632. * </p>
  633. *
  634. * @param runnable code to run on the user-interface thread or <code>null</code>
  635. *
  636. * @exception SWTException <ul>
  637. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  638. * </ul>
  639. *
  640. * @see #syncExec
  641. */
  642. public void asyncExec (Runnable runnable) {
  643. synchronized (Device.classinfo) {
  644. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  645. synchronizer.asyncExec (runnable);
  646. }
  647. }
  648. /**
  649. * Causes the system hardware to emit a short sound
  650. * (if it supports this capability).
  651. *
  652. * @exception SWTException <ul>
  653. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  654. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  655. * </ul>
  656. */
  657. public void beep () {
  658. checkDevice ();
  659. OS.MessageBeep (OS.MB_OK);
  660. }
  661. /**
  662. * Checks that this class can be subclassed.
  663. * <p>
  664. * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
  665. * </p>
  666. *
  667. * @exception SWTException <ul>
  668. * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
  669. * </ul>
  670. *
  671. * @see Widget#checkSubclass
  672. */
  673. protected void checkSubclass () {
  674. //if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
  675. }
  676. override protected void checkDevice () {
  677. if (thread is null) error (SWT.ERROR_WIDGET_DISPOSED);
  678. if (thread !is Thread.currentThread ()) {
  679. /*
  680. * Bug in IBM JVM 1.6. For some reason, under
  681. * conditions that are yet to be full understood,
  682. * Thread.currentThread() is either returning null
  683. * or a different instance from the one that was
  684. * saved when the Display was created. This is
  685. * possibly a JIT problem because modifying this
  686. * method to print logging information when the
  687. * error happens seems to fix the problem. The
  688. * fix is to use operating system calls to verify
  689. * that the current thread is not the Display thread.
  690. *
  691. * NOTE: Despite the fact that Thread.currentThread()
  692. * is used in other places, the failure has not been
  693. * observed in all places where it is called.
  694. */
  695. if (threadId !is OS.GetCurrentThreadId ()) {
  696. error (SWT.ERROR_THREAD_INVALID_ACCESS);
  697. }
  698. }
  699. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  700. }
  701. static void checkDisplay (Thread thread, bool multiple) {
  702. synchronized (Device.classinfo) {
  703. for (int i=0; i<Displays.length; i++) {
  704. if (Displays [i] !is null) {
  705. if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
  706. if (Displays [i].thread is thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
  707. }
  708. }
  709. }
  710. }
  711. void clearModal (Shell shell) {
  712. if (modalShells is null) return;
  713. int index = 0, length_ = modalShells.length;
  714. while (index < length_) {
  715. if (modalShells [index] is shell) break;
  716. if (modalShells [index] is null) return;
  717. index++;
  718. }
  719. if (index is length_) return;
  720. System.arraycopy (modalShells, index + 1, modalShells, index, --length_ - index);
  721. modalShells [length_] = null;
  722. if (index is 0 && modalShells [0] is null) modalShells = null;
  723. Shell [] shells = getShells ();
  724. for (int i=0; i<shells.length; i++) shells [i].updateModal ();
  725. }
  726. int controlKey (int key) {
  727. int upper = cast(int)OS.CharUpper (cast(wchar*) key);
  728. if (64 <= upper && upper <= 95) return upper & 0xBF;
  729. return key;
  730. }
  731. /**
  732. * Requests that the connection between SWT and the underlying
  733. * operating system be closed.
  734. *
  735. * @exception SWTException <ul>
  736. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  737. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  738. * </ul>
  739. *
  740. * @see Device#dispose
  741. *
  742. * @since 2.0
  743. */
  744. public void close () {
  745. checkDevice ();
  746. Event event = new Event ();
  747. sendEvent (SWT.Close, event);
  748. if (event.doit) dispose ();
  749. }
  750. /**
  751. * Creates the device in the operating system. If the device
  752. * does not have a handle, this method may do nothing depending
  753. * on the device.
  754. * <p>
  755. * This method is called before <code>init</code>.
  756. * </p>
  757. *
  758. * @param data the DeviceData which describes the receiver
  759. *
  760. * @see #init
  761. */
  762. override protected void create (DeviceData data) {
  763. checkSubclass ();
  764. checkDisplay (thread = Thread.currentThread (), true);
  765. createDisplay (data);
  766. register (this);
  767. if (Default is null) Default = this;
  768. }
  769. void createDisplay (DeviceData data) {
  770. }
  771. static HBITMAP create32bitDIB (Image image) {
  772. static_this();
  773. int transparentPixel = -1, alpha = -1;
  774. HBITMAP hMask;
  775. HBITMAP hBitmap;
  776. byte[] alphaData = null;
  777. switch (image.type) {
  778. case SWT.ICON:
  779. ICONINFO info;
  780. OS.GetIconInfo (image.handle, &info);
  781. hBitmap = info.hbmColor;
  782. hMask = info.hbmMask;
  783. break;
  784. case SWT.BITMAP:
  785. ImageData data = image.getImageData ();
  786. hBitmap = image.handle;
  787. alpha = data.alpha;
  788. alphaData = data.alphaData;
  789. transparentPixel = data.transparentPixel;
  790. break;
  791. default:
  792. }
  793. BITMAP bm;
  794. OS.GetObject (hBitmap, BITMAP.sizeof, &bm);
  795. int imgWidth = bm.bmWidth;
  796. int imgHeight = bm.bmHeight;
  797. auto hDC = OS.GetDC (null);
  798. auto srcHdc = OS.CreateCompatibleDC (hDC);
  799. auto oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
  800. auto memHdc = OS.CreateCompatibleDC (hDC);
  801. BITMAPINFOHEADER bmiHeader;
  802. bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
  803. bmiHeader.biWidth = imgWidth;
  804. bmiHeader.biHeight = -imgHeight;
  805. bmiHeader.biPlanes = 1;
  806. bmiHeader.biBitCount = cast(short)32;
  807. bmiHeader.biCompression = OS.BI_RGB;
  808. byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
  809. bmi[ 0 .. BITMAPINFOHEADER.sizeof ] = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof ];
  810. void* pBits;
  811. auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
  812. if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
  813. auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
  814. BITMAP dibBM;
  815. OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
  816. int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
  817. OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
  818. byte red = 0, green = 0, blue = 0;
  819. if (transparentPixel !is -1) {
  820. if (bm.bmBitsPixel <= 8) {
  821. byte [4] color;
  822. OS.GetDIBColorTable (srcHdc, transparentPixel, 1, cast(RGBQUAD*)color.ptr);
  823. blue = color [0];
  824. green = color [1];
  825. red = color [2];
  826. } else {
  827. switch (bm.bmBitsPixel) {
  828. case 16:
  829. blue = cast(byte)((transparentPixel & 0x1F) << 3);
  830. green = cast(byte)((transparentPixel & 0x3E0) >> 2);
  831. red = cast(byte)((transparentPixel & 0x7C00) >> 7);
  832. break;
  833. case 24:
  834. blue = cast(byte)((transparentPixel & 0xFF0000) >> 16);
  835. green = cast(byte)((transparentPixel & 0xFF00) >> 8);
  836. red = cast(byte)(transparentPixel & 0xFF);
  837. break;
  838. case 32:
  839. blue = cast(byte)((transparentPixel & 0xFF000000) >>> 24);
  840. green = cast(byte)((transparentPixel & 0xFF0000) >> 16);
  841. red = cast(byte)((transparentPixel & 0xFF00) >> 8);
  842. break;
  843. default:
  844. }
  845. }
  846. }
  847. byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes].dup;
  848. if (hMask !is null) {
  849. OS.SelectObject(srcHdc, hMask);
  850. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  851. for (int x = 0; x < imgWidth; ++x) {
  852. if (OS.GetPixel(srcHdc, x, y) !is 0) {
  853. srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData[dp + 3] = cast(byte)0;
  854. } else {
  855. srcData[dp + 3] = cast(byte)0xFF;
  856. }
  857. dp += 4;
  858. }
  859. }
  860. } else if (alpha !is -1) {
  861. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  862. for (int x = 0; x < imgWidth; ++x) {
  863. srcData [dp + 3] = cast(byte)alpha;
  864. if (srcData [dp + 3] is 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
  865. dp += 4;
  866. }
  867. }
  868. } else if (alphaData !is null) {
  869. for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
  870. for (int x = 0; x < imgWidth; ++x) {
  871. srcData [dp + 3] = alphaData [ap++];
  872. if (srcData [dp + 3] is 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
  873. dp += 4;
  874. }
  875. }
  876. } else if (transparentPixel !is -1) {
  877. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  878. for (int x = 0; x < imgWidth; ++x) {
  879. if (srcData [dp] is blue && srcData [dp + 1] is green && srcData [dp + 2] is red) {
  880. srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData [dp + 3] = cast(byte)0;
  881. } else {
  882. srcData [dp + 3] = cast(byte)0xFF;
  883. }
  884. dp += 4;
  885. }
  886. }
  887. } else {
  888. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  889. for (int x = 0; x < imgWidth; ++x) {
  890. srcData [dp + 3] = cast(byte)0xFF;
  891. dp += 4;
  892. }
  893. }
  894. }
  895. (cast(byte*)pBits)[ 0 .. sizeInBytes] = srcData[];
  896. OS.SelectObject (srcHdc, oldSrcBitmap);
  897. OS.SelectObject (memHdc, oldMemBitmap);
  898. OS.DeleteObject (srcHdc);
  899. OS.DeleteObject (memHdc);
  900. OS.ReleaseDC (null, hDC);
  901. if (hBitmap !is image.handle && hBitmap !is null) OS.DeleteObject (hBitmap);
  902. if (hMask !is null) OS.DeleteObject (hMask);
  903. return memDib;
  904. }
  905. static HBITMAP create32bitDIB (HBITMAP hBitmap, int alpha, byte [] alphaData, int transparentPixel) {
  906. static_this();
  907. BITMAP bm;
  908. OS.GetObject (hBitmap, BITMAP.sizeof, &bm);
  909. int imgWidth = bm.bmWidth;
  910. int imgHeight = bm.bmHeight;
  911. auto hDC = OS.GetDC (null);
  912. auto srcHdc = OS.CreateCompatibleDC (hDC);
  913. auto oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
  914. auto memHdc = OS.CreateCompatibleDC (hDC);
  915. BITMAPINFOHEADER bmiHeader;
  916. bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
  917. bmiHeader.biWidth = imgWidth;
  918. bmiHeader.biHeight = -imgHeight;
  919. bmiHeader.biPlanes = 1;
  920. bmiHeader.biBitCount = cast(short)32;
  921. bmiHeader.biCompression = OS.BI_RGB;
  922. byte [] bmi = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof];
  923. void* pBits;
  924. auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
  925. if (memDib is null) SWT.error (SWT.ERROR_NO_HANDLES);
  926. auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
  927. BITMAP dibBM;
  928. OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
  929. int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
  930. OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
  931. byte red = 0, green = 0, blue = 0;
  932. if (transparentPixel !is -1) {
  933. if (bm.bmBitsPixel <= 8) {
  934. byte [4] color;
  935. OS.GetDIBColorTable (srcHdc, transparentPixel, 1, cast(RGBQUAD*)color.ptr);
  936. blue = color [0];
  937. green = color [1];
  938. red = color [2];
  939. } else {
  940. switch (bm.bmBitsPixel) {
  941. case 16:
  942. blue = cast(byte)((transparentPixel & 0x1F) << 3);
  943. green = cast(byte)((transparentPixel & 0x3E0) >> 2);
  944. red = cast(byte)((transparentPixel & 0x7C00) >> 7);
  945. break;
  946. case 24:
  947. blue = cast(byte)((transparentPixel & 0xFF0000) >> 16);
  948. green = cast(byte)((transparentPixel & 0xFF00) >> 8);
  949. red = cast(byte)(transparentPixel & 0xFF);
  950. break;
  951. case 32:
  952. blue = cast(byte)((transparentPixel & 0xFF000000) >>> 24);
  953. green = cast(byte)((transparentPixel & 0xFF0000) >> 16);
  954. red = cast(byte)((transparentPixel & 0xFF00) >> 8);
  955. break;
  956. default:
  957. }
  958. }
  959. }
  960. OS.SelectObject (srcHdc, oldSrcBitmap);
  961. OS.SelectObject (memHdc, oldMemBitmap);
  962. OS.DeleteObject (srcHdc);
  963. OS.DeleteObject (memHdc);
  964. OS.ReleaseDC (null, hDC);
  965. byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes ].dup;
  966. if (alpha !is -1) {
  967. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  968. for (int x = 0; x < imgWidth; ++x) {
  969. srcData [dp + 3] = cast(byte)alpha;
  970. dp += 4;
  971. }
  972. }
  973. } else if (alphaData !is null) {
  974. for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
  975. for (int x = 0; x < imgWidth; ++x) {
  976. srcData [dp + 3] = alphaData [ap++];
  977. dp += 4;
  978. }
  979. }
  980. } else if (transparentPixel !is -1) {
  981. for (int y = 0, dp = 0; y < imgHeight; ++y) {
  982. for (int x = 0; x < imgWidth; ++x) {
  983. if (srcData [dp] is blue && srcData [dp + 1] is green && srcData [dp + 2] is red) {
  984. srcData [dp + 3] = cast(byte)0;
  985. } else {
  986. srcData [dp + 3] = cast(byte)0xFF;
  987. }
  988. dp += 4;
  989. }
  990. }
  991. }
  992. (cast(byte*)pBits)[ 0 .. sizeInBytes ] = srcData[];
  993. return memDib;
  994. }
  995. static Image createIcon (Image image) {
  996. static_this();
  997. Device device = image.getDevice ();
  998. ImageData data = image.getImageData ();
  999. if (data.alpha is -1 && data.alphaData is null) {
  1000. ImageData mask = data.getTransparencyMask ();
  1001. return new Image (device, data, mask);
  1002. }
  1003. int width = data.width, height = data.height;
  1004. HBITMAP hMask, hBitmap;
  1005. auto hDC = device.internal_new_GC (null);
  1006. auto dstHdc = OS.CreateCompatibleDC (hDC);
  1007. HBITMAP oldDstBitmap;
  1008. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
  1009. hBitmap = Display.create32bitDIB (image.handle, data.alpha, data.alphaData, data.transparentPixel);
  1010. hMask = OS.CreateBitmap (width, height, 1, 1, null);
  1011. oldDstBitmap = OS.SelectObject (dstHdc, hMask);
  1012. OS.PatBlt (dstHdc, 0, 0, width, height, OS.BLACKNESS);
  1013. } else {
  1014. hMask = Display.createMaskFromAlpha (data, width, height);
  1015. /* Icons need black pixels where the mask is transparent */
  1016. hBitmap = OS.CreateCompatibleBitmap (hDC, width, height);
  1017. oldDstBitmap = OS.SelectObject (dstHdc, hBitmap);
  1018. auto srcHdc = OS.CreateCompatibleDC (hDC);
  1019. auto oldSrcBitmap = OS.SelectObject (srcHdc, image.handle);
  1020. OS.PatBlt (dstHdc, 0, 0, width, height, OS.BLACKNESS);
  1021. OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCINVERT);
  1022. OS.SelectObject (srcHdc, hMask);
  1023. OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCAND);
  1024. OS.SelectObject (srcHdc, image.handle);
  1025. OS.BitBlt (dstHdc, 0, 0, width, height, srcHdc, 0, 0, OS.SRCINVERT);
  1026. OS.SelectObject (srcHdc, oldSrcBitmap);
  1027. OS.DeleteDC (srcHdc);
  1028. }
  1029. OS.SelectObject (dstHdc, oldDstBitmap);
  1030. OS.DeleteDC (dstHdc);
  1031. device.internal_dispose_GC (hDC, null);
  1032. ICONINFO info;
  1033. info.fIcon = true;
  1034. info.hbmColor = hBitmap;
  1035. info.hbmMask = hMask;
  1036. auto hIcon = OS.CreateIconIndirect (&info);
  1037. if (hIcon is null) SWT.error(SWT.ERROR_NO_HANDLES);
  1038. OS.DeleteObject (hBitmap);
  1039. OS.DeleteObject (hMask);
  1040. return Image.win32_new (device, SWT.ICON, hIcon);
  1041. }
  1042. static HBITMAP createMaskFromAlpha (ImageData data, int destWidth, int destHeight) {
  1043. static_this();
  1044. int srcWidth = data.width;
  1045. int srcHeight = data.height;
  1046. ImageData mask = ImageData.internal_new (srcWidth, srcHeight, 1,
  1047. new PaletteData([new RGB (0, 0, 0), new RGB (0xff, 0xff, 0xff)]),
  1048. 2, null, 1, null, null, -1, -1, -1, 0, 0, 0, 0);
  1049. int ap = 0;
  1050. for (int y = 0; y < mask.height; y++) {
  1051. for (int x = 0; x < mask.width; x++) {
  1052. mask.setPixel (x, y, (data.alphaData [ap++] & 0xff) <= 127 ? 1 : 0);
  1053. }
  1054. }
  1055. auto hMask = OS.CreateBitmap (srcWidth, srcHeight, 1, 1, mask.data.ptr);
  1056. if (srcWidth !is destWidth || srcHeight !is destHeight) {
  1057. auto hdc = OS.GetDC (null);
  1058. auto hdc1 = OS.CreateCompatibleDC (hdc);
  1059. OS.SelectObject (hdc1, hMask);
  1060. auto hdc2 = OS.CreateCompatibleDC (hdc);
  1061. auto hMask2 = OS.CreateBitmap (destWidth, destHeight, 1, 1, null);
  1062. OS.SelectObject (hdc2, hMask2);
  1063. static if (!OS.IsWinCE) OS.SetStretchBltMode(hdc2, OS.COLORONCOLOR);
  1064. OS.StretchBlt (hdc2, 0, 0, destWidth, destHeight, hdc1, 0, 0, srcWidth, srcHeight, OS.SRCCOPY);
  1065. OS.DeleteDC (hdc1);
  1066. OS.DeleteDC (hdc2);
  1067. OS.ReleaseDC (null, hdc);
  1068. OS.DeleteObject(hMask);
  1069. hMask = hMask2;
  1070. }
  1071. return hMask;
  1072. }
  1073. static void deregister (Display display) {
  1074. synchronized (Device.classinfo) {
  1075. for (int i=0; i<Displays.length; i++) {
  1076. if (display is Displays [i]) Displays [i] = null;
  1077. }
  1078. }
  1079. }
  1080. /**
  1081. * Destroys the device in the operating system and releases
  1082. * the device's handle. If the device does not have a handle,
  1083. * this method may do nothing depending on the device.
  1084. * <p>
  1085. * This method is called after <code>release</code>.
  1086. * </p>
  1087. * @see Device#dispose
  1088. * @see #release
  1089. */
  1090. override protected void destroy () {
  1091. if (this is Default) Default = null;
  1092. deregister (this);
  1093. destroyDisplay ();
  1094. }
  1095. void destroyDisplay () {
  1096. }
  1097. /**
  1098. * Causes the <code>run()</code> method of the runnable to
  1099. * be invoked by the user-interface thread just before the
  1100. * receiver is disposed. Specifying a <code>null</code> runnable
  1101. * is ignored.
  1102. *
  1103. * @param runnable code to run at dispose time.
  1104. *
  1105. * @exception SWTException <ul>
  1106. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1107. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1108. * </ul>
  1109. */
  1110. public void disposeExec (Runnable runnable) {
  1111. checkDevice ();
  1112. if (disposeList is null) disposeList = new Runnable [4];
  1113. for (int i=0; i<disposeList.length; i++) {
  1114. if (disposeList [i] is null) {
  1115. disposeList [i] = runnable;
  1116. return;
  1117. }
  1118. }
  1119. Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
  1120. SimpleType!(Runnable).arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
  1121. newDisposeList [disposeList.length] = runnable;
  1122. disposeList = newDisposeList;
  1123. }
  1124. void drawMenuBars () {
  1125. if (bars is null) return;
  1126. for (int i=0; i<bars.length; i++) {
  1127. Menu menu = bars [i];
  1128. if (menu !is null && !menu.isDisposed ()) menu.update ();
  1129. }
  1130. bars = null;
  1131. }
  1132. private static extern(Windows) int embeddedFunc (HWND hwnd, int msg, int wParam, int lParam) {
  1133. switch (msg) {
  1134. case SWT_KEYMSG: {
  1135. MSG* keyMsg = cast(MSG*)lParam;
  1136. OS.TranslateMessage (keyMsg);
  1137. OS.DispatchMessage (keyMsg);
  1138. auto hHeap = OS.GetProcessHeap ();
  1139. OS.HeapFree (hHeap, 0, cast(void*)lParam);
  1140. break;
  1141. }
  1142. case SWT_DESTROY: {
  1143. OS.DestroyWindow (hwnd);
  1144. //if (embeddedCallback !is null) embeddedCallback.dispose ();
  1145. //if (getMsgCallback !is null) getMsgCallback.dispose ();
  1146. //embeddedCallback = getMsgCallback = null;
  1147. //embeddedProc_ = getMsgProc_ = 0;
  1148. break;
  1149. }
  1150. default:
  1151. }
  1152. return OS.DefWindowProc (hwnd, msg, wParam, lParam);
  1153. }
  1154. /**
  1155. * Does whatever display specific cleanup is required, and then
  1156. * uses the code in <code>SWTError.error</code> to handle the error.
  1157. *
  1158. * @param code the descriptive error code
  1159. *
  1160. * @see SWT#error(int)
  1161. */
  1162. void error (int code) {
  1163. SWT.error (code);
  1164. }
  1165. bool filterEvent (Event event) {
  1166. if (filterTable !is null) filterTable.sendEvent (event);
  1167. return false;
  1168. }
  1169. bool filters (int eventType) {
  1170. if (filterTable is null) return false;
  1171. return filterTable.hooks (eventType);
  1172. }
  1173. bool filterMessage (MSG* msg) {
  1174. int message = msg.message;
  1175. if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) {
  1176. Control control = findControl (msg.hwnd);
  1177. if (control !is null) {
  1178. if (translateAccelerator (msg, control) || translateMnemonic (msg, control) || translateTraversal (msg, control)) {
  1179. lastAscii = lastKey = 0;
  1180. lastVirtual = lastNull = lastDead = false;
  1181. return true;
  1182. }
  1183. }
  1184. }
  1185. return false;
  1186. }
  1187. Control findControl (HANDLE handle) {
  1188. if (handle is null) return null;
  1189. HWND hwndOwner = null;
  1190. do {
  1191. Control control = getControl (handle);
  1192. if (control !is null) return control;
  1193. hwndOwner = OS.GetWindow (handle, OS.GW_OWNER);
  1194. handle = OS.GetParent (handle);
  1195. } while (handle !is null && handle !is hwndOwner);
  1196. return null;
  1197. }
  1198. /**
  1199. * Given the operating system handle for a widget, returns
  1200. * the instance of the <code>Widget</code> subclass which
  1201. * represents it in the currently running application, if
  1202. * such exists, or null if no matching widget can be found.
  1203. * <p>
  1204. * <b>IMPORTANT:</b> This method should not be called from
  1205. * application code. The arguments are platform-specific.
  1206. * </p>
  1207. *
  1208. * @param handle the handle for the widget
  1209. * @return the SWT widget that the handle represents
  1210. *
  1211. * @exception SWTException <ul>
  1212. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1213. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1214. * </ul>
  1215. */
  1216. public Widget findWidget (HANDLE handle) {
  1217. checkDevice ();
  1218. return getControl (handle);
  1219. }
  1220. /**
  1221. * Given the operating system handle for a widget,
  1222. * and widget-specific id, returns the instance of
  1223. * the <code>Widget</code> subclass which represents
  1224. * the handle/id pair in the currently running application,
  1225. * if such exists, or null if no matching widget can be found.
  1226. * <p>
  1227. * <b>IMPORTANT:</b> This method should not be called from
  1228. * application code. The arguments are platform-specific.
  1229. * </p>
  1230. *
  1231. * @param handle the handle for the widget
  1232. * @param id the id for the subwidget (usually an item)
  1233. * @return the SWT widget that the handle/id pair represents
  1234. *
  1235. * @exception SWTException <ul>
  1236. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1237. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1238. * </ul>
  1239. *
  1240. * @since 3.1
  1241. */
  1242. public Widget findWidget (HANDLE handle, int id) {
  1243. checkDevice ();
  1244. //TODO - should ids be long
  1245. Control control = getControl (handle);
  1246. return control !is null ? control.findItem (cast(HANDLE) id) : null;
  1247. }
  1248. /**
  1249. * Given a widget and a widget-specific id, returns the
  1250. * instance of the <code>Widget</code> subclass which represents
  1251. * the widget/id pair in the currently running application,
  1252. * if such exists, or null if no matching widget can be found.
  1253. *
  1254. * @param widget the widget
  1255. * @param id the id for the subwidget (usually an item)
  1256. * @return the SWT subwidget (usually an item) that the widget/id pair represents
  1257. *
  1258. * @exception SWTException <ul>
  1259. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1260. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1261. * </ul>
  1262. *
  1263. * @since 3.3
  1264. */
  1265. public Widget findWidget (Widget widget, int /*long*/ id) {
  1266. checkDevice ();
  1267. //TODO - should ids be long
  1268. if (cast(Control)widget) {
  1269. return findWidget ((cast(Control) widget).handle, id);
  1270. }
  1271. return null;
  1272. }
  1273. private static extern(Windows) int foregroundIdleProcFunc (int code, uint wParam, int lParam) {
  1274. auto d = Display.getCurrent();
  1275. return d.foregroundIdleProc( code, wParam, lParam );
  1276. }
  1277. int foregroundIdleProc (int code, int wParam, int lParam) {
  1278. if (code >= 0) {
  1279. if (runMessages && getMessageCount () !is 0) {
  1280. if (runMessagesInIdle) {
  1281. if (runMessagesInMessageProc) {
  1282. OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
  1283. } else {
  1284. runAsyncMessages (false);
  1285. }
  1286. }
  1287. wakeThread ();
  1288. }
  1289. }
  1290. return OS.CallNextHookEx (idleHook, code, wParam, lParam);
  1291. }
  1292. /**
  1293. * Returns the display which the given thread is the
  1294. * user-interface thread for, or null if the given thread
  1295. * is not a user-interface thread for any display. Specifying
  1296. * <code>null</code> as the thread will return <code>null</code>
  1297. * for the display.
  1298. *
  1299. * @param thread the user-interface thread
  1300. * @return the display for the given thread
  1301. */
  1302. public static Display findDisplay (Thread thread) {
  1303. static_this();
  1304. synchronized (Device.classinfo) {
  1305. for (int i=0; i<Displays.length; i++) {
  1306. Display display = Displays [i];
  1307. if (display !is null && display.thread is thread) {
  1308. return display;
  1309. }
  1310. }
  1311. return null;
  1312. }
  1313. }
  1314. /**
  1315. * Returns the currently active <code>Shell</code>, or null
  1316. * if no shell belonging to the currently running application
  1317. * is active.
  1318. *
  1319. * @return the active shell or null
  1320. *
  1321. * @exception SWTException <ul>
  1322. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1323. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1324. * </ul>
  1325. */
  1326. public Shell getActiveShell () {
  1327. checkDevice ();
  1328. Control control = findControl (OS.GetActiveWindow ());
  1329. return control !is null ? control.getShell () : null;
  1330. }
  1331. /**
  1332. * Returns a rectangle describing the receiver's size and location. Note that
  1333. * on multi-monitor systems the origin can be negative.
  1334. *
  1335. * @return the bounding rectangle
  1336. *
  1337. * @exception SWTException <ul>
  1338. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1339. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1340. * </ul>
  1341. */
  1342. override public Rectangle getBounds () {
  1343. checkDevice ();
  1344. if (OS.GetSystemMetrics (OS.SM_CMONITORS) < 2) {
  1345. int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
  1346. int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
  1347. return new Rectangle (0, 0, width, height);
  1348. }
  1349. int x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
  1350. int y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
  1351. int width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
  1352. int height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
  1353. return new Rectangle (x, y, width, height);
  1354. }
  1355. /**
  1356. * Returns the display which the currently running thread is
  1357. * the user-interface thread for, or null if the currently
  1358. * running thread is not a user-interface thread for any display.
  1359. *
  1360. * @return the current display
  1361. */
  1362. public static Display getCurrent () {
  1363. static_this();
  1364. return findDisplay (Thread.currentThread ());
  1365. }
  1366. int getClickCount (int type, int button, HWND hwnd, int lParam) {
  1367. switch (type) {
  1368. case SWT.MouseDown:
  1369. int doubleClick = OS.GetDoubleClickTime ();
  1370. if (clickRect is null) clickRect = new RECT ();
  1371. int deltaTime = Math.abs (lastTime - getLastEventTime ());
  1372. POINT pt;
  1373. OS.POINTSTOPOINT (pt, lParam);
  1374. if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (clickRect, pt)) {
  1375. clickCount++;
  1376. } else {
  1377. clickCount = 1;
  1378. }
  1379. //FALL THROUGH
  1380. case SWT.MouseDoubleClick:
  1381. lastButton = button;
  1382. lastClickHwnd = hwnd;
  1383. lastTime = getLastEventTime ();
  1384. int xInset = OS.GetSystemMetrics (OS.SM_CXDOUBLECLK) / 2;
  1385. int yInset = OS.GetSystemMetrics (OS.SM_CYDOUBLECLK) / 2;
  1386. int x = OS.GET_X_LPARAM (lParam), y = OS.GET_Y_LPARAM (lParam);
  1387. OS.SetRect (clickRect, x - xInset, y - yInset, x + xInset, y + yInset);
  1388. //FALL THROUGH
  1389. case SWT.MouseUp:
  1390. return clickCount;
  1391. default:
  1392. }
  1393. return 0;
  1394. }
  1395. /**
  1396. * Returns a rectangle which describes the area of the
  1397. * receiver which is capable of displaying data.
  1398. *
  1399. * @return the client area
  1400. *
  1401. * @exception SWTException <ul>
  1402. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1403. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1404. * </ul>
  1405. *
  1406. * @see #getBounds
  1407. */
  1408. override public Rectangle getClientArea () {
  1409. checkDevice ();
  1410. if (OS.GetSystemMetrics (OS.SM_CMONITORS) < 2) {
  1411. RECT rect;
  1412. OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
  1413. int width = rect.right - rect.left;
  1414. int height = rect.bottom - rect.top;
  1415. return new Rectangle (rect.left, rect.top, width, height);
  1416. }
  1417. int x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
  1418. int y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
  1419. int width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
  1420. int height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
  1421. return new Rectangle (x, y, width, height);
  1422. }
  1423. Control getControl (HANDLE handle) {
  1424. if (handle is null) return null;
  1425. if (lastControl !is null && lastHwnd is handle) {
  1426. return lastControl;
  1427. }
  1428. if (lastGetControl !is null && lastGetHwnd is handle) {
  1429. return lastGetControl;
  1430. }
  1431. int index;
  1432. static if (USE_PROPERTY) {
  1433. index = cast(int) OS.GetProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
  1434. } else {
  1435. index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
  1436. }
  1437. if (0 <= index && index < controlTable.length) {
  1438. Control control = controlTable [index];
  1439. /*
  1440. * Because GWL_USERDATA can be used by native widgets that
  1441. * do not belong to SWT, it is possible that GWL_USERDATA
  1442. * could return an index that is in the range of the table,
  1443. * but was not put there by SWT. Therefore, it is necessary
  1444. * to check the handle of the control that is in the table
  1445. * against the handle that provided the GWL_USERDATA.
  1446. */
  1447. if (control !is null && control.checkHandle (handle)) {
  1448. lastGetHwnd = handle;
  1449. lastGetControl = control;
  1450. return control;
  1451. }
  1452. }
  1453. return null;
  1454. }
  1455. /**
  1456. * Returns the control which the on-screen pointer is currently
  1457. * over top of, or null if it is not currently over one of the
  1458. * controls built by the currently running application.
  1459. *
  1460. * @return the control under the cursor
  1461. *
  1462. * @exception SWTException <ul>
  1463. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1464. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1465. * </ul>
  1466. */
  1467. public Control getCursorControl () {
  1468. checkDevice ();
  1469. POINT pt;
  1470. if (!OS.GetCursorPos (&pt)) return null;
  1471. return findControl (OS.WindowFromPoint (pt));
  1472. }
  1473. /**
  1474. * Returns the location of the on-screen pointer relative
  1475. * to the top left corner of the screen.
  1476. *
  1477. * @return the cursor location
  1478. *
  1479. * @exception SWTException <ul>
  1480. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1481. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1482. * </ul>
  1483. */
  1484. public Point getCursorLocation () {
  1485. checkDevice ();
  1486. POINT pt;
  1487. OS.GetCursorPos (&pt);
  1488. return new Point (pt.x, pt.y);
  1489. }
  1490. /**
  1491. * Returns an array containing the recommended cursor sizes.
  1492. *
  1493. * @return the array of cursor sizes
  1494. *
  1495. * @exception SWTException <ul>
  1496. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1497. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1498. * </ul>
  1499. *
  1500. * @since 3.0
  1501. */
  1502. public Point [] getCursorSizes () {
  1503. checkDevice ();
  1504. return [
  1505. new Point (OS.GetSystemMetrics (OS.SM_CXCURSOR), OS.GetSystemMetrics (OS.SM_CYCURSOR))];
  1506. }
  1507. /**
  1508. * Returns the default display. One is created (making the
  1509. * thread that invokes this method its user-interface thread)
  1510. * if it did not already exist.
  1511. *
  1512. * @return the default display
  1513. */
  1514. public static Display getDefault () {
  1515. static_this();
  1516. synchronized (Device.classinfo) {
  1517. if (Default is null) Default = new Display ();
  1518. return Default;
  1519. }
  1520. }
  1521. //PORTING_TODO
  1522. /+static bool isValidClass (Class clazz) {
  1523. String name = clazz.getName ();
  1524. int index = name.lastIndexOf ('.');
  1525. return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
  1526. }+/
  1527. /**
  1528. * Returns the application defined property of the receiver
  1529. * with the specified name, or null if it has not been set.
  1530. * <p>
  1531. * Applications may have associated arbitrary objects with the
  1532. * receiver in this fashion. If the objects stored in the
  1533. * properties need to be notified when the display is disposed
  1534. * of, it is the application's responsibility to provide a
  1535. * <code>disposeExec()</code> handler which does so.
  1536. * </p>
  1537. *
  1538. * @param key the name of the property
  1539. * @return the value of the property or null if it has not been set
  1540. *
  1541. * @exception SWTException <ul>
  1542. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1543. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1544. * </ul>
  1545. *
  1546. * @see #setData(String, Object)
  1547. * @see #disposeExec(Runnable)
  1548. */
  1549. public Object getData (String key) {
  1550. checkDevice ();
  1551. // SWT extension: allow null string
  1552. //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
  1553. if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) {
  1554. return new Boolean(runMessagesInIdle);
  1555. }
  1556. if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
  1557. return new Boolean (runMessagesInMessageProc);
  1558. }
  1559. if (keys.length is 0) return null;
  1560. for (int i=0; i<keys.length; i++) {
  1561. if (keys [i] ==/*eq*/key) return values [i];
  1562. }
  1563. return null;
  1564. }
  1565. /**
  1566. * Returns the application defined, display specific data
  1567. * associated with the receiver, or null if it has not been
  1568. * set. The <em>display specific data</em> is a single,
  1569. * unnamed field that is stored with every display.
  1570. * <p>
  1571. * Applications may put arbitrary objects in this field. If
  1572. * the object stored in the display specific data needs to
  1573. * be notified when the display is disposed of, it is the
  1574. * application's responsibility to provide a
  1575. * <code>disposeExec()</code> handler which does so.
  1576. * </p>
  1577. *
  1578. * @return the display specific data
  1579. *
  1580. * @exception SWTException <ul>
  1581. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1582. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1583. * </ul>
  1584. *
  1585. * @see #setData(Object)
  1586. * @see #disposeExec(Runnable)
  1587. */
  1588. public Object getData () {
  1589. checkDevice ();
  1590. return data;
  1591. }
  1592. /**
  1593. * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
  1594. * The button dismissal alignment is the ordering that should be used when positioning the
  1595. * default dismissal button for a dialog. For example, in a dialog that contains an OK and
  1596. * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
  1597. * button ordering should be OK/CANCEL. When button dismissal alignment is <code>RIGHT</code>,
  1598. * the button ordering should be CANCEL/OK.
  1599. *
  1600. * @return the button dismissal order
  1601. *
  1602. * @exception SWTException <ul>
  1603. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1604. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1605. * </ul>
  1606. *
  1607. * @since 2.1
  1608. */
  1609. public int getDismissalAlignment () {
  1610. checkDevice ();
  1611. return SWT.LEFT;
  1612. }
  1613. /**
  1614. * Returns the longest duration, in milliseconds, between
  1615. * two mouse button clicks that will be considered a
  1616. * <em>double click</em> by the underlying operating system.
  1617. *
  1618. * @return the double click time
  1619. *
  1620. * @exception SWTException <ul>
  1621. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1622. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1623. * </ul>
  1624. */
  1625. public int getDoubleClickTime () {
  1626. checkDevice ();
  1627. return OS.GetDoubleClickTime ();
  1628. }
  1629. /**
  1630. * Returns the control which currently has keyboard focus,
  1631. * or null if keyboard events are not currently going to
  1632. * any of the controls built by the currently running
  1633. * application.
  1634. *
  1635. * @return the control under the cursor
  1636. *
  1637. * @exception SWTException <ul>
  1638. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1639. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1640. * </ul>
  1641. */
  1642. public Control getFocusControl () {
  1643. checkDevice ();
  1644. if (focusControl !is null && !focusControl.isDisposed ()) {
  1645. return focusControl;
  1646. }
  1647. return _getFocusControl ();
  1648. }
  1649. String getFontName (LOGFONT* logFont) {
  1650. wchar* chars;
  1651. static if (OS.IsUnicode) {
  1652. chars = logFont.lfFaceName.ptr;
  1653. } else {
  1654. chars = new char[OS.LF_FACESIZE];
  1655. byte[] bytes = logFont.lfFaceName;
  1656. OS.MultiByteToWideChar (OS.CP_ACP, OS.MB_PRECOMPOSED, bytes, bytes.length, chars, chars.length);
  1657. }
  1658. return TCHARzToStr( chars );
  1659. }
  1660. /**
  1661. * Returns true when the high contrast mode is enabled.
  1662. * Otherwise, false is returned.
  1663. * <p>
  1664. * Note: This operation is a hint and is not supported on
  1665. * platforms that do not have this concept.
  1666. * </p>
  1667. *
  1668. * @return the high contrast mode
  1669. *
  1670. * @exception SWTException <ul>
  1671. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1672. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1673. * </ul>
  1674. *
  1675. * @since 3.0
  1676. */
  1677. public bool getHighContrast () {
  1678. checkDevice ();
  1679. static if (OS.IsWinCE) {
  1680. return false;
  1681. }
  1682. else {
  1683. HIGHCONTRAST pvParam;
  1684. pvParam.cbSize = HIGHCONTRAST.sizeof;
  1685. OS.SystemParametersInfo (OS.SPI_GETHIGHCONTRAST, 0, &pvParam, 0);
  1686. return (pvParam.dwFlags & OS.HCF_HIGHCONTRASTON) !is 0;
  1687. }
  1688. }
  1689. /**
  1690. * Returns the maximum allowed depth of icons on this display, in bits per pixel.
  1691. * On some platforms, this may be different than the actual depth of the display.
  1692. *
  1693. * @return the maximum icon depth
  1694. *
  1695. * @exception SWTException <ul>
  1696. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1697. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1698. * </ul>
  1699. *
  1700. * @see Device#getDepth
  1701. */
  1702. public int getIconDepth () {
  1703. checkDevice ();
  1704. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
  1705. if (getDepth () >= 24) return 32;
  1706. }
  1707. /* Use the character encoding for the default locale */
  1708. LPCTSTR buffer1 = StrToTCHARz( "Control Panel\\Desktop\\WindowMetrics" ); //$NON-NLS-1$
  1709. void* phkResult;
  1710. int result = OS.RegOpenKeyEx ( cast(void*)OS.HKEY_CURRENT_USER, buffer1, 0, OS.KEY_READ, &phkResult);
  1711. if (result !is 0) return 4;
  1712. int depth = 4;
  1713. uint lpcbData;
  1714. /* Use the character encoding for the default locale */
  1715. LPCTSTR buffer2 = StrToTCHARz( "Shell Icon BPP" ); //$NON-NLS-1$
  1716. result = OS.RegQueryValueEx (phkResult , buffer2, null, null, null, &lpcbData);
  1717. if (result is 0) {
  1718. ubyte[] lpData = new ubyte[ lpcbData / TCHAR.sizeof ];
  1719. lpData[] = 0;
  1720. result = OS.RegQueryValueEx (phkResult , buffer2, null, null, lpData.ptr, &lpcbData);
  1721. if (result is 0) {
  1722. try {
  1723. depth = Integer.parseInt ( cast(String) lpData );
  1724. } catch (NumberFormatException e) {}
  1725. }
  1726. }
  1727. OS.RegCloseKey (phkResult );
  1728. return depth;
  1729. }
  1730. /**
  1731. * Returns an array containing the recommended icon sizes.
  1732. *
  1733. * @return the array of icon sizes
  1734. *
  1735. * @exception SWTException <ul>
  1736. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1737. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  1738. * </ul>
  1739. *
  1740. * @see Decorations#setImages(Image[])
  1741. *
  1742. * @since 3.0
  1743. */
  1744. public Point [] getIconSizes () {
  1745. checkDevice ();
  1746. return [
  1747. new Point (OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON)),
  1748. new Point (OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON))
  1749. ];
  1750. }
  1751. ImageList getImageList (int style, int width, int height) {
  1752. if (imageList is null) imageList = new ImageList [4];
  1753. int i = 0;
  1754. int length_ = imageList.length;
  1755. while (i < length_) {
  1756. ImageList list = imageList [i];
  1757. if (list is null) break;
  1758. Point size = list.getImageSize();
  1759. if (size.x is width && size.y is height) {
  1760. if (list.getStyle () is style) {
  1761. list.addRef();
  1762. return list;
  1763. }
  1764. }
  1765. i++;
  1766. }
  1767. if (i is length_) {
  1768. ImageList [] newList = new ImageList [length_ + 4];
  1769. System.arraycopy (imageList, 0, newList, 0, length_);
  1770. imageList = newList;
  1771. }
  1772. ImageList list = new ImageList (style);
  1773. imageList [i] = list;
  1774. list.addRef();
  1775. return list;
  1776. }
  1777. ImageList getImageListToolBar (int style, int width, int height) {
  1778. if (toolImageList is null) toolImageList = new ImageList [4];
  1779. int i = 0;
  1780. int length_ = toolImageList.length;
  1781. while (i < length_) {
  1782. ImageList list = toolImageList [i];
  1783. if (list is null) break;
  1784. Point size = list.getImageSize();
  1785. if (size.x is width && size.y is height) {
  1786. if (list.getStyle () is style) {
  1787. list.addRef();
  1788. return list;
  1789. }
  1790. }
  1791. i++;
  1792. }
  1793. if (i is length_) {
  1794. ImageList [] newList = new ImageList [length_ + 4];
  1795. System.arraycopy (toolImageList, 0, newList, 0, length_);
  1796. toolImageList = newList;
  1797. }
  1798. ImageList list = new ImageList (style);
  1799. toolImageList [i] = list;
  1800. list.addRef();
  1801. return list;
  1802. }
  1803. ImageList getImageListToolBarDisabled (int style, int width, int height) {
  1804. if (toolDisabledImageList is null) toolDisabledImageList = new ImageList [4];
  1805. int i = 0;
  1806. int length_ = toolDisabledImageList.length;
  1807. while (i < length_) {
  1808. ImageList list = toolDisabledImageList [i];
  1809. if (list is null) break;
  1810. Point size = list.getImageSize();
  1811. if (size.x is width && size.y is height) {
  1812. if (list.getStyle () is style) {
  1813. list.addRef();
  1814. return list;
  1815. }
  1816. }
  1817. i++;
  1818. }
  1819. if (i is length_) {
  1820. ImageList [] newList = new ImageList [length_ + 4];
  1821. System.arraycopy (toolDisabledImageList, 0, newList, 0, length_);
  1822. toolDisabledImageList = newList;
  1823. }
  1824. ImageList list = new ImageList (style);
  1825. toolDisabledImageList [i] = list;
  1826. list.addRef();
  1827. return list;
  1828. }
  1829. ImageList getImageListToolBarHot (int style, int width, int height) {
  1830. if (toolHotImageList is null) toolHotImageList = new ImageList [4];
  1831. int i = 0;
  1832. int length_ = toolHotImageList.length;
  1833. while (i < length_) {
  1834. ImageList list = toolHotImageList [i];
  1835. if (list is null) break;
  1836. Point size = list.getImageSize();
  1837. if (size.x is width && size.y is height) {
  1838. if (list.getStyle () is style) {
  1839. list.addRef();
  1840. return list;
  1841. }
  1842. }
  1843. i++;
  1844. }
  1845. if (i is length_) {
  1846. ImageList [] newList = new ImageList [length_ + 4];
  1847. System.arraycopy (toolHotImageList, 0, newList, 0, length_);
  1848. toolHotImageList = newList;
  1849. }
  1850. ImageList list = new ImageList (style);
  1851. toolHotImageList [i] = list;
  1852. list.addRef();
  1853. return list;
  1854. }
  1855. int getLastEventTime () {
  1856. return OS.IsWinCE ? OS.GetTickCount () : OS.GetMessageTime ();
  1857. }
  1858. MenuItem getMenuItem (int id) {
  1859. if (items is null) return null;
  1860. id = id - ID_START;
  1861. if (0 <= id && id < items.length) return items [id];
  1862. return null;
  1863. }
  1864. int getMessageCount () {
  1865. return synchronizer.getMessageCount ();
  1866. }
  1867. Shell getModalShell () {
  1868. if (modalShells is null) return null;
  1869. int index = modalShells.length;
  1870. while (--index >= 0) {
  1871. Shell shell = modalShells [index];
  1872. if (shell !is null) return shell;
  1873. }
  1874. return null;
  1875. }
  1876. Dialog getModalDialog () {
  1877. return modalDialog;
  1878. }
  1879. /**
  1880. * Returns an array of monitors attached to the device.
  1881. *
  1882. * @return the array of monitors
  1883. *
  1884. * @since 3.0
  1885. */
  1886. public org.eclipse.swt.widgets.Monitor.Monitor [] getMonitors () {
  1887. checkDevice ();
  1888. if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
  1889. return [getPrimaryMonitor ()];
  1890. }
  1891. monitors = new org.eclipse.swt.widgets.Monitor.Monitor [4];
  1892. OS.EnumDisplayMonitors (null, null, &monitorEnumFunc, cast(int)cast(void*)this );
  1893. org.eclipse.swt.widgets.Monitor.Monitor [] result = new org.eclipse.swt.widgets.Monitor.Monitor [monitorCount];
  1894. System.arraycopy (monitors, 0, result, 0, monitorCount);
  1895. monitors = null;
  1896. monitorCount = 0;
  1897. return result;
  1898. }
  1899. static extern(Windows) int getMsgFunc (int code, uint wParam, int lParam) {
  1900. return Display.getCurrent().getMsgProc( code, wParam, lParam );
  1901. }
  1902. int getMsgProc (int code, int wParam, int lParam) {
  1903. if (embeddedHwnd is null) {
  1904. auto hInstance = OS.GetModuleHandle (null);
  1905. embeddedHwnd = OS.CreateWindowEx (0,
  1906. windowClass_.ptr,
  1907. null,
  1908. OS.WS_OVERLAPPED,
  1909. 0, 0, 0, 0,
  1910. null,
  1911. null,
  1912. hInstance,
  1913. null);
  1914. //embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
  1915. //embeddedProc_ = embeddedCallback.getAddress ();
  1916. //if (embeddedProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  1917. OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) &embeddedFunc);
  1918. }
  1919. if (code >= 0 && (wParam & OS.PM_REMOVE) !is 0) {
  1920. MSG* msg = cast(MSG*)lParam;
  1921. switch (msg.message) {
  1922. case OS.WM_KEYDOWN:
  1923. case OS.WM_KEYUP:
  1924. case OS.WM_SYSKEYDOWN:
  1925. case OS.WM_SYSKEYUP: {
  1926. Control control = findControl (msg.hwnd);
  1927. if (control !is null) {
  1928. auto hHeap = OS.GetProcessHeap ();
  1929. MSG* keyMsg = cast(MSG*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, MSG.sizeof);
  1930. *keyMsg = *msg;
  1931. OS.PostMessage (hwndMessage, SWT_KEYMSG, wParam, cast(int)keyMsg);
  1932. switch (msg.wParam) {
  1933. case OS.VK_SHIFT:
  1934. case OS.VK_MENU:
  1935. case OS.VK_CONTROL:
  1936. case OS.VK_CAPITAL:
  1937. case OS.VK_NUMLOCK:
  1938. case OS.VK_SCROLL:
  1939. break;
  1940. default:
  1941. msg.message = OS.WM_NULL;
  1942. //OS.MoveMemory (lParam, msg, MSG.sizeof);
  1943. }
  1944. }
  1945. default:
  1946. }
  1947. }
  1948. }
  1949. return OS.CallNextHookEx (msgHook, code, wParam, lParam);
  1950. }
  1951. /**
  1952. * Returns the primary monitor for that device.
  1953. *
  1954. * @return the primary monitor
  1955. *
  1956. * @since 3.0
  1957. */
  1958. public org.eclipse.swt.widgets.Monitor.Monitor getPrimaryMonitor () {
  1959. checkDevice ();
  1960. if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (4, 10)) {
  1961. org.eclipse.swt.widgets.Monitor.Monitor monitor = new org.eclipse.swt.widgets.Monitor.Monitor();
  1962. int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
  1963. int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
  1964. monitor.width = width;
  1965. monitor.height = height;
  1966. RECT rect;
  1967. OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0);
  1968. monitor.clientX = rect.left;
  1969. monitor.clientY = rect.top;
  1970. monitor.clientWidth = rect.right - rect.left;
  1971. monitor.clientHeight = rect.bottom - rect.top;
  1972. return monitor;
  1973. }
  1974. monitors = new org.eclipse.swt.widgets.Monitor.Monitor [4];
  1975. OS.EnumDisplayMonitors (null, null, &monitorEnumFunc, cast(int)cast(void*)this);
  1976. org.eclipse.swt.widgets.Monitor.Monitor result = null;
  1977. MONITORINFO lpmi;
  1978. lpmi.cbSize = MONITORINFO.sizeof;
  1979. for (int i = 0; i < monitorCount; i++) {
  1980. org.eclipse.swt.widgets.Monitor.Monitor monitor = monitors [i];
  1981. OS.GetMonitorInfo (monitors [i].handle, &lpmi);
  1982. if ((lpmi.dwFlags & OS.MONITORINFOF_PRIMARY) !is 0) {
  1983. result = monitor;
  1984. break;
  1985. }
  1986. }
  1987. monitors = null;
  1988. monitorCount = 0;
  1989. return result;
  1990. }
  1991. /**
  1992. * Returns a (possibly empty) array containing all shells which have
  1993. * not been disposed and have the receiver as their display.
  1994. *
  1995. * @return the receiver's shells
  1996. *
  1997. * @exception SWTException <ul>
  1998. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  1999. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2000. * </ul>
  2001. */
  2002. public Shell [] getShells () {
  2003. checkDevice ();
  2004. int index = 0;
  2005. Shell [] result = new Shell [16];
  2006. for (int i = 0; i < controlTable.length; i++) {
  2007. Control control = controlTable [i];
  2008. if (control !is null && (cast(Shell)control)) {
  2009. int j = 0;
  2010. while (j < index) {
  2011. if (result [j] is control) break;
  2012. j++;
  2013. }
  2014. if (j is index) {
  2015. if (index is result.length) {
  2016. Shell [] newResult = new Shell [index + 16];
  2017. System.arraycopy (result, 0, newResult, 0, index);
  2018. result = newResult;
  2019. }
  2020. result [index++] = cast(Shell) control;
  2021. }
  2022. }
  2023. }
  2024. if (index is result.length) return result;
  2025. Shell [] newResult = new Shell [index];
  2026. System.arraycopy (result, 0, newResult, 0, index);
  2027. return newResult;
  2028. }
  2029. Image getSortImage (int direction) {
  2030. switch (direction) {
  2031. case SWT.UP: {
  2032. if (upArrow !is null) return upArrow;
  2033. Color c1 = getSystemColor (SWT.COLOR_WIDGET_NORMAL_SHADOW);
  2034. Color c2 = getSystemColor (SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
  2035. Color c3 = getSystemColor (SWT.COLOR_WIDGET_BACKGROUND);
  2036. PaletteData palette = new PaletteData([c1.getRGB (), c2.getRGB (), c3.getRGB ()]);
  2037. ImageData imageData = new ImageData (8, 8, 4, palette);
  2038. imageData.transparentPixel = 2;
  2039. upArrow = new Image (this, imageData);
  2040. GC gc = new GC (upArrow);
  2041. gc.setBackground (c3);
  2042. gc.fillRectangle (0, 0, 8, 8);
  2043. gc.setForeground (c1);
  2044. int [] line1 = [0,6, 1,6, 1,4, 2,4, 2,2, 3,2, 3,1];
  2045. gc.drawPolyline (line1);
  2046. gc.setForeground (c2);
  2047. int [] line2 = [0,7, 7,7, 7,6, 6,6, 6,4, 5,4, 5,2, 4,2, 4,1];
  2048. gc.drawPolyline (line2);
  2049. gc.dispose ();
  2050. return upArrow;
  2051. }
  2052. case SWT.DOWN: {
  2053. if (downArrow !is null) return downArrow;
  2054. Color c1 = getSystemColor (SWT.COLOR_WIDGET_NORMAL_SHADOW);
  2055. Color c2 = getSystemColor (SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
  2056. Color c3 = getSystemColor (SWT.COLOR_WIDGET_BACKGROUND);
  2057. PaletteData palette = new PaletteData ([c1.getRGB (), c2.getRGB (), c3.getRGB ()]);
  2058. ImageData imageData = new ImageData (8, 8, 4, palette);
  2059. imageData.transparentPixel = 2;
  2060. downArrow = new Image (this, imageData);
  2061. GC gc = new GC (downArrow);
  2062. gc.setBackground (c3);
  2063. gc.fillRectangle (0, 0, 8, 8);
  2064. gc.setForeground (c1);
  2065. int [] line1 = [7,0, 0,0, 0,1, 1,1, 1,3, 2,3, 2,5, 3,5, 3,6];
  2066. gc.drawPolyline (line1);
  2067. gc.setForeground (c2);
  2068. int [] line2 = [4,6, 4,5, 5,5, 5,3, 6,3, 6,1, 7,1];
  2069. gc.drawPolyline (line2);
  2070. gc.dispose ();
  2071. return downArrow;
  2072. }
  2073. default:
  2074. }
  2075. return null;
  2076. }
  2077. /**
  2078. * Gets the synchronizer used by the display.
  2079. *
  2080. * @return the receiver's synchronizer
  2081. *
  2082. * @exception SWTException <ul>
  2083. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2084. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2085. * </ul>
  2086. *
  2087. * @since 3.4
  2088. */
  2089. public Synchronizer getSynchronizer () {
  2090. checkDevice ();
  2091. return synchronizer;
  2092. }
  2093. /**
  2094. * Returns the thread that has invoked <code>syncExec</code>
  2095. * or null if no such runnable is currently being invoked by
  2096. * the user-interface thread.
  2097. * <p>
  2098. * Note: If a runnable invoked by asyncExec is currently
  2099. * running, this method will return null.
  2100. * </p>
  2101. *
  2102. * @return the receiver's sync-interface thread
  2103. *
  2104. * @exception SWTException <ul>
  2105. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2106. * </ul>
  2107. */
  2108. public Thread getSyncThread () {
  2109. synchronized (Device.classinfo) {
  2110. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  2111. return synchronizer.syncThread;
  2112. }
  2113. }
  2114. /**
  2115. * Returns the matching standard color for the given
  2116. * constant, which should be one of the color constants
  2117. * specified in class <code>SWT</code>. Any value other
  2118. * than one of the SWT color constants which is passed
  2119. * in will result in the color black. This color should
  2120. * not be free'd because it was allocated by the system,
  2121. * not the application.
  2122. *
  2123. * @param id the color constant
  2124. * @return the matching color
  2125. *
  2126. * @exception SWTException <ul>
  2127. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2128. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2129. * </ul>
  2130. *
  2131. * @see SWT
  2132. */
  2133. override public Color getSystemColor (int id) {
  2134. checkDevice ();
  2135. int pixel = 0x00000000;
  2136. switch (id) {
  2137. case SWT.COLOR_WIDGET_DARK_SHADOW: pixel = OS.GetSysColor (OS.COLOR_3DDKSHADOW); break;
  2138. case SWT.COLOR_WIDGET_NORMAL_SHADOW: pixel = OS.GetSysColor (OS.COLOR_3DSHADOW); break;
  2139. case SWT.COLOR_WIDGET_LIGHT_SHADOW: pixel = OS.GetSysColor (OS.COLOR_3DLIGHT); break;
  2140. case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW: pixel = OS.GetSysColor (OS.COLOR_3DHIGHLIGHT); break;
  2141. case SWT.COLOR_WIDGET_BACKGROUND: pixel = OS.GetSysColor (OS.COLOR_3DFACE); break;
  2142. case SWT.COLOR_WIDGET_BORDER: pixel = OS.GetSysColor (OS.COLOR_WINDOWFRAME); break;
  2143. case SWT.COLOR_WIDGET_FOREGROUND:
  2144. case SWT.COLOR_LIST_FOREGROUND: pixel = OS.GetSysColor (OS.COLOR_WINDOWTEXT); break;
  2145. case SWT.COLOR_LIST_BACKGROUND: pixel = OS.GetSysColor (OS.COLOR_WINDOW); break;
  2146. case SWT.COLOR_LIST_SELECTION: pixel = OS.GetSysColor (OS.COLOR_HIGHLIGHT); break;
  2147. case SWT.COLOR_LIST_SELECTION_TEXT: pixel = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);break;
  2148. case SWT.COLOR_INFO_FOREGROUND: pixel = OS.GetSysColor (OS.COLOR_INFOTEXT); break;
  2149. case SWT.COLOR_INFO_BACKGROUND: pixel = OS.GetSysColor (OS.COLOR_INFOBK); break;
  2150. case SWT.COLOR_TITLE_FOREGROUND: pixel = OS.GetSysColor (OS.COLOR_CAPTIONTEXT); break;
  2151. case SWT.COLOR_TITLE_BACKGROUND: pixel = OS.GetSysColor (OS.COLOR_ACTIVECAPTION); break;
  2152. case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:
  2153. pixel = OS.GetSysColor (OS.COLOR_GRADIENTACTIVECAPTION);
  2154. if (pixel is 0) pixel = OS.GetSysColor (OS.COLOR_ACTIVECAPTION);
  2155. break;
  2156. case SWT.COLOR_TITLE_INACTIVE_FOREGROUND: pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTIONTEXT); break;
  2157. case SWT.COLOR_TITLE_INACTIVE_BACKGROUND: pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTION); break;
  2158. case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:
  2159. pixel = OS.GetSysColor (OS.COLOR_GRADIENTINACTIVECAPTION);
  2160. if (pixel is 0) pixel = OS.GetSysColor (OS.COLOR_INACTIVECAPTION);
  2161. break;
  2162. default:
  2163. return super.getSystemColor (id);
  2164. }
  2165. return Color.win32_new (this, pixel);
  2166. }
  2167. /**
  2168. * Returns the matching standard platform cursor for the given
  2169. * constant, which should be one of the cursor constants
  2170. * specified in class <code>SWT</code>. This cursor should
  2171. * not be free'd because it was allocated by the system,
  2172. * not the application. A value of <code>null</code> will
  2173. * be returned if the supplied constant is not an SWT cursor
  2174. * constant.
  2175. *
  2176. * @param id the SWT cursor constant
  2177. * @return the corresponding cursor or <code>null</code>
  2178. *
  2179. * @exception SWTException <ul>
  2180. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2181. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2182. * </ul>
  2183. *
  2184. * @see SWT#CURSOR_ARROW
  2185. * @see SWT#CURSOR_WAIT
  2186. * @see SWT#CURSOR_CROSS
  2187. * @see SWT#CURSOR_APPSTARTING
  2188. * @see SWT#CURSOR_HELP
  2189. * @see SWT#CURSOR_SIZEALL
  2190. * @see SWT#CURSOR_SIZENESW
  2191. * @see SWT#CURSOR_SIZENS
  2192. * @see SWT#CURSOR_SIZENWSE
  2193. * @see SWT#CURSOR_SIZEWE
  2194. * @see SWT#CURSOR_SIZEN
  2195. * @see SWT#CURSOR_SIZES
  2196. * @see SWT#CURSOR_SIZEE
  2197. * @see SWT#CURSOR_SIZEW
  2198. * @see SWT#CURSOR_SIZENE
  2199. * @see SWT#CURSOR_SIZESE
  2200. * @see SWT#CURSOR_SIZESW
  2201. * @see SWT#CURSOR_SIZENW
  2202. * @see SWT#CURSOR_UPARROW
  2203. * @see SWT#CURSOR_IBEAM
  2204. * @see SWT#CURSOR_NO
  2205. * @see SWT#CURSOR_HAND
  2206. *
  2207. * @since 3.0
  2208. */
  2209. public Cursor getSystemCursor (int id) {
  2210. checkDevice ();
  2211. if (!(0 <= id && id < cursors.length)) return null;
  2212. if (cursors [id] is null) {
  2213. cursors [id] = new Cursor (this, id);
  2214. }
  2215. return cursors [id];
  2216. }
  2217. /**
  2218. * Returns a reasonable font for applications to use.
  2219. * On some platforms, this will match the "default font"
  2220. * or "system font" if such can be found. This font
  2221. * should not be free'd because it was allocated by the
  2222. * system, not the application.
  2223. * <p>
  2224. * Typically, applications which want the default look
  2225. * should simply not set the font on the widgets they
  2226. * create. Widgets are always created with the correct
  2227. * default font for the class of user-interface component
  2228. * they represent.
  2229. * </p>
  2230. *
  2231. * @return a font
  2232. *
  2233. * @exception SWTException <ul>
  2234. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2235. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2236. * </ul>
  2237. */
  2238. override public Font getSystemFont () {
  2239. checkDevice ();
  2240. if (systemFont !is null) return systemFont;
  2241. HFONT hFont;
  2242. static if (!OS.IsWinCE) {
  2243. NONCLIENTMETRICS info;
  2244. info.cbSize = NONCLIENTMETRICS.sizeof;
  2245. if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
  2246. LOGFONT logFont = info.lfMessageFont;
  2247. hFont = OS.CreateFontIndirect (&logFont);
  2248. lfSystemFont = hFont !is null ? &logFont : null;
  2249. }
  2250. }
  2251. if (hFont is null) hFont = OS.GetStockObject (OS.DEFAULT_GUI_FONT);
  2252. if (hFont is null) hFont = OS.GetStockObject (OS.SYSTEM_FONT);
  2253. return systemFont = Font.win32_new (this, hFont);
  2254. }
  2255. /**
  2256. * Returns the matching standard platform image for the given
  2257. * constant, which should be one of the icon constants
  2258. * specified in class <code>SWT</code>. This image should
  2259. * not be free'd because it was allocated by the system,
  2260. * not the application. A value of <code>null</code> will
  2261. * be returned either if the supplied constant is not an
  2262. * SWT icon constant or if the platform does not define an
  2263. * image that corresponds to the constant.
  2264. *
  2265. * @param id the SWT icon constant
  2266. * @return the corresponding image or <code>null</code>
  2267. *
  2268. * @exception SWTException <ul>
  2269. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2270. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2271. * </ul>
  2272. *
  2273. * @see SWT#ICON_ERROR
  2274. * @see SWT#ICON_INFORMATION
  2275. * @see SWT#ICON_QUESTION
  2276. * @see SWT#ICON_WARNING
  2277. * @see SWT#ICON_WORKING
  2278. *
  2279. * @since 3.0
  2280. */
  2281. public Image getSystemImage (int id) {
  2282. checkDevice ();
  2283. switch (id) {
  2284. case SWT.ICON_ERROR: {
  2285. if (errorImage !is null) return errorImage;
  2286. auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_HAND, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
  2287. return errorImage = Image.win32_new (this, SWT.ICON, hIcon);
  2288. }
  2289. case SWT.ICON_WORKING:
  2290. case SWT.ICON_INFORMATION: {
  2291. if (infoImage !is null) return infoImage;
  2292. auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_INFORMATION, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
  2293. return infoImage = Image.win32_new (this, SWT.ICON, hIcon);
  2294. }
  2295. case SWT.ICON_QUESTION: {
  2296. if (questionImage !is null) return questionImage;
  2297. auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_QUES, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
  2298. return questionImage = Image.win32_new (this, SWT.ICON, hIcon);
  2299. }
  2300. case SWT.ICON_WARNING: {
  2301. if (warningIcon !is null) return warningIcon;
  2302. auto hIcon = OS.LoadImage (null, cast(wchar*)OS.OIC_BANG, OS.IMAGE_ICON, 0, 0, OS.LR_SHARED);
  2303. return warningIcon = Image.win32_new (this, SWT.ICON, hIcon);
  2304. }
  2305. default:
  2306. }
  2307. return null;
  2308. }
  2309. /**
  2310. * Returns the single instance of the system tray or null
  2311. * when there is no system tray available for the platform.
  2312. *
  2313. * @return the system tray or <code>null</code>
  2314. *
  2315. * @exception SWTException <ul>
  2316. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2317. * </ul>
  2318. *
  2319. * @since 3.0
  2320. */
  2321. public Tray getSystemTray () {
  2322. checkDevice ();
  2323. if (tray !is null) return tray;
  2324. static if (!OS.IsWinCE) tray = new Tray (this, SWT.NONE);
  2325. return tray;
  2326. }
  2327. /**
  2328. * Returns the user-interface thread for the receiver.
  2329. *
  2330. * @return the receiver's user-interface thread
  2331. *
  2332. * @exception SWTException <ul>
  2333. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2334. * </ul>
  2335. */
  2336. public Thread getThread () {
  2337. synchronized (Device.classinfo) {
  2338. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  2339. return thread;
  2340. }
  2341. }
  2342. HTHEME hButtonTheme () {
  2343. if (hButtonTheme_ !is null) return hButtonTheme_;
  2344. return hButtonTheme_ = OS.OpenThemeData (hwndMessage, BUTTON.ptr);
  2345. }
  2346. HTHEME hEditTheme () {
  2347. if (hEditTheme_ !is null) return hEditTheme_;
  2348. return hEditTheme_ = OS.OpenThemeData (hwndMessage, EDIT.ptr);
  2349. }
  2350. HTHEME hExplorerBarTheme () {
  2351. if (hExplorerBarTheme_ !is null) return hExplorerBarTheme_;
  2352. return hExplorerBarTheme_ = OS.OpenThemeData (hwndMessage, EXPLORERBAR.ptr);
  2353. }
  2354. HTHEME hScrollBarTheme () {
  2355. if (hScrollBarTheme_ !is null) return hScrollBarTheme_;
  2356. return hScrollBarTheme_ = OS.OpenThemeData (hwndMessage, SCROLLBAR.ptr);
  2357. }
  2358. HTHEME hTabTheme () {
  2359. if (hTabTheme_ !is null) return hTabTheme_;
  2360. return hTabTheme_ = OS.OpenThemeData (hwndMessage, TAB.ptr);
  2361. }
  2362. /**
  2363. * Invokes platform specific functionality to allocate a new GC handle.
  2364. * <p>
  2365. * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
  2366. * API for <code>Display</code>. It is marked public only so that it
  2367. * can be shared within the packages provided by SWT. It is not
  2368. * available on all platforms, and should never be called from
  2369. * application code.
  2370. * </p>
  2371. *
  2372. * @param data the platform specific GC data
  2373. * @return the platform specific GC handle
  2374. *
  2375. * @exception SWTException <ul>
  2376. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2377. * </ul>
  2378. * @exception SWTError <ul>
  2379. * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
  2380. * </ul>
  2381. */
  2382. override public HDC internal_new_GC (GCData data) {
  2383. if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
  2384. auto hDC = OS.GetDC (null);
  2385. if (hDC is null) SWT.error (SWT.ERROR_NO_HANDLES);
  2386. if (data !is null) {
  2387. int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
  2388. if ((data.style & mask) !is 0) {
  2389. data.layout = (data.style & SWT.RIGHT_TO_LEFT) !is 0 ? OS.LAYOUT_RTL : 0;
  2390. } else {
  2391. data.style |= SWT.LEFT_TO_RIGHT;
  2392. }
  2393. data.device = this;
  2394. data.font = getSystemFont ();
  2395. }
  2396. return hDC;
  2397. }
  2398. /**
  2399. * Initializes any internal resources needed by the
  2400. * device.
  2401. * <p>
  2402. * This method is called after <code>create</code>.
  2403. * </p>
  2404. *
  2405. * @see #create
  2406. */
  2407. override protected void init_ () {
  2408. super.init_ ();
  2409. /* Create the callbacks */
  2410. //windowCallback = new Callback (this, "windowProc", 4); //$NON-NLS-1$
  2411. //windowProc_ = windowCallback.getAddress ();
  2412. //if (windowProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  2413. /* Remember the current thread id */
  2414. threadId = OS.GetCurrentThreadId ();
  2415. /* Use the character encoding for the default locale */
  2416. windowClass_ = StrToTCHARs ( 0, WindowName ~ String_valueOf(WindowClassCount), true );
  2417. windowShadowClass = StrToTCHARs ( 0, WindowShadowName ~ String_valueOf(WindowClassCount), true );
  2418. WindowClassCount++;
  2419. /* Register the SWT window class */
  2420. auto hHeap = OS.GetProcessHeap ();
  2421. auto hInstance = OS.GetModuleHandle (null);
  2422. WNDCLASS lpWndClass;
  2423. lpWndClass.hInstance = hInstance;
  2424. lpWndClass.lpfnWndProc = &windowProcFunc;
  2425. lpWndClass.style = OS.CS_BYTEALIGNWINDOW | OS.CS_DBLCLKS;
  2426. lpWndClass.hCursor = OS.LoadCursor (null, cast(wchar*)OS.IDC_ARROW);
  2427. //DWT_TODO: Check if this can be disabled for SWT
  2428. /+
  2429. /*
  2430. * Set the default icon for the window class to IDI_APPLICATION.
  2431. * This is not necessary for native Windows applications but
  2432. * versions of Java starting at JDK 1.6 set the icon in the
  2433. * executable instead of leaving the default.
  2434. */
  2435. if (!OS.IsWinCE && Library.JAVA_VERSION >= Library.JAVA_VERSION (1, 6, 0)) {
  2436. TCHAR[] lpszFile = NewTCHARs (0, OS.MAX_PATH);
  2437. while (OS.GetModuleFileName (0, lpszFile.ptr, lpszFile.length) is lpszFile.length) {
  2438. lpszFile = NewTCHARs (0, lpszFile.length + OS.MAX_PATH);
  2439. }
  2440. if (OS.ExtractIconEx (lpszFile.ptr, -1, null, null, 1) !is 0) {
  2441. String fileName = TCHARzToStr( lpszFile.ptr );
  2442. if (fileName.endsWith ("java.exe") || fileName.endsWith ("javaw.exe")) { //$NON-NLS-1$ //$NON-NLS-2$
  2443. lpWndClass.hIcon = OS.LoadIcon (0, OS.IDI_APPLICATION);
  2444. }
  2445. }
  2446. }
  2447. +/
  2448. int byteCount = windowClass_.length * TCHAR.sizeof;
  2449. auto buf = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
  2450. lpWndClass.lpszClassName = buf;
  2451. OS.MoveMemory (buf, windowClass_.ptr, byteCount);
  2452. OS.RegisterClass (&lpWndClass);
  2453. OS.HeapFree (hHeap, 0, buf);
  2454. /* Register the SWT drop shadow window class */
  2455. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
  2456. lpWndClass.style |= OS.CS_DROPSHADOW;
  2457. }
  2458. byteCount = windowShadowClass.length * TCHAR.sizeof;
  2459. buf = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
  2460. lpWndClass.lpszClassName = buf;
  2461. OS.MoveMemory (buf, windowShadowClass.ptr, byteCount);
  2462. OS.RegisterClass (&lpWndClass);
  2463. OS.HeapFree (hHeap, 0, buf);
  2464. /* Create the message only HWND */
  2465. hwndMessage = OS.CreateWindowEx (0,
  2466. windowClass_.ptr,
  2467. null,
  2468. OS.WS_OVERLAPPED,
  2469. 0, 0, 0, 0,
  2470. null,
  2471. null,
  2472. hInstance,
  2473. null);
  2474. //messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$
  2475. //messageProc_ = messageCallback.getAddress ();
  2476. //if (messageProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  2477. OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, cast(LONG_PTR) &messageProcFunc);
  2478. /* Create the filter hook */
  2479. static if (!OS.IsWinCE) {
  2480. //msgFilterCallback = new Callback (this, "msgFilterProc", 3); //$NON-NLS-1$
  2481. //msgFilterProc_ = msgFilterCallback.getAddress ();
  2482. //if (msgFilterProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  2483. filterHook = OS.SetWindowsHookEx (OS.WH_MSGFILTER, &msgFilterProcFunc, null, threadId);
  2484. }
  2485. /* Create the idle hook */
  2486. static if (!OS.IsWinCE) {
  2487. //foregroundIdleCallback = new Callback (this, "foregroundIdleProc", 3); //$NON-NLS-1$
  2488. //foregroundIdleProc_ = foregroundIdleCallback.getAddress ();
  2489. //if (foregroundIdleProc_ is 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
  2490. idleHook = OS.SetWindowsHookEx (OS.WH_FOREGROUNDIDLE, &foregroundIdleProcFunc, null, threadId);
  2491. }
  2492. /* Register custom messages message */
  2493. SWT_TASKBARCREATED = OS.RegisterWindowMessage (StrToTCHARz ( "TaskbarCreated" ));
  2494. SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz ( "SWT_RESTORECARET"));
  2495. DI_GETDRAGIMAGE = OS.RegisterWindowMessage (StrToTCHARz ( "ShellGetDragImage")); //$NON-NLS-1$
  2496. /* Initialize OLE */
  2497. static if (!OS.IsWinCE) OS.OleInitialize (null);
  2498. /* Initialize buffered painting */
  2499. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)){
  2500. OS.BufferedPaintInit ();
  2501. }
  2502. /* Initialize the Widget Table */
  2503. indexTable = new int [GROW_SIZE];
  2504. controlTable = new Control [GROW_SIZE];
  2505. for (int i=0; i<GROW_SIZE-1; i++) indexTable [i] = i + 1;
  2506. indexTable [GROW_SIZE - 1] = -1;
  2507. }
  2508. /**
  2509. * Invokes platform specific functionality to dispose a GC handle.
  2510. * <p>
  2511. * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
  2512. * API for <code>Display</code>. It is marked public only so that it
  2513. * can be shared within the packages provided by SWT. It is not
  2514. * available on all platforms, and should never be called from
  2515. * application code.
  2516. * </p>
  2517. *
  2518. * @param hDC the platform specific GC handle
  2519. * @param data the platform specific GC data
  2520. */
  2521. override public void internal_dispose_GC (HDC hDC, GCData data) {
  2522. OS.ReleaseDC (null, hDC);
  2523. }
  2524. bool isXMouseActive () {
  2525. /*
  2526. * NOTE: X-Mouse is active when bit 1 of the UserPreferencesMask is set.
  2527. */
  2528. bool xMouseActive = false;
  2529. LPCTSTR key = StrToTCHARz( "Control Panel\\Desktop" ); //$NON-NLS-1$
  2530. void* phKey;
  2531. int result = OS.RegOpenKeyEx (cast(void*)OS.HKEY_CURRENT_USER, key, 0, OS.KEY_READ, &phKey);
  2532. if (result is 0) {
  2533. LPCTSTR lpValueName = StrToTCHARz ( "UserPreferencesMask" ); //$NON-NLS-1$
  2534. uint[4] lpcbData;
  2535. uint lpData;
  2536. result = OS.RegQueryValueEx (phKey, lpValueName, null, null, cast(ubyte*)&lpData, lpcbData.ptr);
  2537. if (result is 0) xMouseActive = (lpData & 0x01) !is 0;
  2538. OS.RegCloseKey (phKey);
  2539. }
  2540. return xMouseActive;
  2541. }
  2542. bool isValidThread () {
  2543. return thread is Thread.currentThread ();
  2544. }
  2545. /**
  2546. * Maps a point from one coordinate system to another.
  2547. * When the control is null, coordinates are mapped to
  2548. * the display.
  2549. * <p>
  2550. * NOTE: On right-to-left platforms where the coordinate
  2551. * systems are mirrored, special care needs to be taken
  2552. * when mapping coordinates from one control to another
  2553. * to ensure the result is correctly mirrored.
  2554. *
  2555. * Mapping a point that is the origin of a rectangle and
  2556. * then adding the width and height is not equivalent to
  2557. * mapping the rectangle. When one control is mirrored
  2558. * and the other is not, adding the width and height to a
  2559. * point that was mapped causes the rectangle to extend
  2560. * in the wrong direction. Mapping the entire rectangle
  2561. * instead of just one point causes both the origin and
  2562. * the corner of the rectangle to be mapped.
  2563. * </p>
  2564. *
  2565. * @param from the source <code>Control</code> or <code>null</code>
  2566. * @param to the destination <code>Control</code> or <code>null</code>
  2567. * @param point to be mapped
  2568. * @return point with mapped coordinates
  2569. *
  2570. * @exception IllegalArgumentException <ul>
  2571. * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
  2572. * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
  2573. * </ul>
  2574. * @exception SWTException <ul>
  2575. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2576. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2577. * </ul>
  2578. *
  2579. * @since 2.1.2
  2580. */
  2581. public Point map (Control from, Control to, Point point) {
  2582. checkDevice ();
  2583. if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
  2584. return map (from, to, point.x, point.y);
  2585. }
  2586. /**
  2587. * Maps a point from one coordinate system to another.
  2588. * When the control is null, coordinates are mapped to
  2589. * the display.
  2590. * <p>
  2591. * NOTE: On right-to-left platforms where the coordinate
  2592. * systems are mirrored, special care needs to be taken
  2593. * when mapping coordinates from one control to another
  2594. * to ensure the result is correctly mirrored.
  2595. *
  2596. * Mapping a point that is the origin of a rectangle and
  2597. * then adding the width and height is not equivalent to
  2598. * mapping the rectangle. When one control is mirrored
  2599. * and the other is not, adding the width and height to a
  2600. * point that was mapped causes the rectangle to extend
  2601. * in the wrong direction. Mapping the entire rectangle
  2602. * instead of just one point causes both the origin and
  2603. * the corner of the rectangle to be mapped.
  2604. * </p>
  2605. *
  2606. * @param from the source <code>Control</code> or <code>null</code>
  2607. * @param to the destination <code>Control</code> or <code>null</code>
  2608. * @param x coordinates to be mapped
  2609. * @param y coordinates to be mapped
  2610. * @return point with mapped coordinates
  2611. *
  2612. * @exception IllegalArgumentException <ul>
  2613. * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
  2614. * </ul>
  2615. * @exception SWTException <ul>
  2616. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2617. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2618. * </ul>
  2619. *
  2620. * @since 2.1.2
  2621. */
  2622. public Point map (Control from, Control to, int x, int y) {
  2623. checkDevice ();
  2624. if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
  2625. if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
  2626. if (from is to) return new Point (x, y);
  2627. auto hwndFrom = from !is null ? from.handle : null;
  2628. auto hwndTo = to !is null ? to.handle : null;
  2629. POINT point;
  2630. point.x = x;
  2631. point.y = y;
  2632. OS.MapWindowPoints (hwndFrom, hwndTo, &point, 1);
  2633. return new Point (point.x, point.y);
  2634. }
  2635. /**
  2636. * Maps a point from one coordinate system to another.
  2637. * When the control is null, coordinates are mapped to
  2638. * the display.
  2639. * <p>
  2640. * NOTE: On right-to-left platforms where the coordinate
  2641. * systems are mirrored, special care needs to be taken
  2642. * when mapping coordinates from one control to another
  2643. * to ensure the result is correctly mirrored.
  2644. *
  2645. * Mapping a point that is the origin of a rectangle and
  2646. * then adding the width and height is not equivalent to
  2647. * mapping the rectangle. When one control is mirrored
  2648. * and the other is not, adding the width and height to a
  2649. * point that was mapped causes the rectangle to extend
  2650. * in the wrong direction. Mapping the entire rectangle
  2651. * instead of just one point causes both the origin and
  2652. * the corner of the rectangle to be mapped.
  2653. * </p>
  2654. *
  2655. * @param from the source <code>Control</code> or <code>null</code>
  2656. * @param to the destination <code>Control</code> or <code>null</code>
  2657. * @param rectangle to be mapped
  2658. * @return rectangle with mapped coordinates
  2659. *
  2660. * @exception IllegalArgumentException <ul>
  2661. * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
  2662. * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
  2663. * </ul>
  2664. * @exception SWTException <ul>
  2665. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2666. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2667. * </ul>
  2668. *
  2669. * @since 2.1.2
  2670. */
  2671. public Rectangle map (Control from, Control to, Rectangle rectangle) {
  2672. checkDevice ();
  2673. if (rectangle is null) error (SWT.ERROR_NULL_ARGUMENT);
  2674. return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
  2675. }
  2676. /**
  2677. * Maps a point from one coordinate system to another.
  2678. * When the control is null, coordinates are mapped to
  2679. * the display.
  2680. * <p>
  2681. * NOTE: On right-to-left platforms where the coordinate
  2682. * systems are mirrored, special care needs to be taken
  2683. * when mapping coordinates from one control to another
  2684. * to ensure the result is correctly mirrored.
  2685. *
  2686. * Mapping a point that is the origin of a rectangle and
  2687. * then adding the width and height is not equivalent to
  2688. * mapping the rectangle. When one control is mirrored
  2689. * and the other is not, adding the width and height to a
  2690. * point that was mapped causes the rectangle to extend
  2691. * in the wrong direction. Mapping the entire rectangle
  2692. * instead of just one point causes both the origin and
  2693. * the corner of the rectangle to be mapped.
  2694. * </p>
  2695. *
  2696. * @param from the source <code>Control</code> or <code>null</code>
  2697. * @param to the destination <code>Control</code> or <code>null</code>
  2698. * @param x coordinates to be mapped
  2699. * @param y coordinates to be mapped
  2700. * @param width coordinates to be mapped
  2701. * @param height coordinates to be mapped
  2702. * @return rectangle with mapped coordinates
  2703. *
  2704. * @exception IllegalArgumentException <ul>
  2705. * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
  2706. * </ul>
  2707. * @exception SWTException <ul>
  2708. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  2709. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  2710. * </ul>
  2711. *
  2712. * @since 2.1.2
  2713. */
  2714. public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
  2715. checkDevice ();
  2716. if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
  2717. if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
  2718. if (from is to) return new Rectangle (x, y, width, height);
  2719. auto hwndFrom = from !is null ? from.handle : null;
  2720. auto hwndTo = to !is null ? to.handle : null;
  2721. RECT rect;
  2722. rect.left = x;
  2723. rect.top = y;
  2724. rect.right = x + width;
  2725. rect.bottom = y + height;
  2726. OS.MapWindowPoints (hwndFrom, hwndTo, cast(POINT*)&rect, 2);
  2727. return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
  2728. }
  2729. /*
  2730. * Returns a single character, converted from the default
  2731. * multi-byte character set (MBCS) used by the operating
  2732. * system widgets to a wide character set (WCS) used by Java.
  2733. *
  2734. * @param ch the MBCS character
  2735. * @return the WCS character
  2736. */
  2737. static wchar mbcsToWcs (int ch) {
  2738. return mbcsToWcs (ch, 0);
  2739. }
  2740. /*
  2741. * Returns a single character, converted from the specified
  2742. * multi-byte character set (MBCS) used by the operating
  2743. * system widgets to a wide character set (WCS) used by Java.
  2744. *
  2745. * @param ch the MBCS character
  2746. * @param codePage the code page used to convert the character
  2747. * @return the WCS character
  2748. */
  2749. static wchar mbcsToWcs (int ch, int codePage) {
  2750. if (OS.IsUnicode) return cast(wchar) ch;
  2751. int key = ch & 0xFFFF;
  2752. if (key <= 0x7F) return cast(wchar) ch;
  2753. CHAR[] buffer;
  2754. if (key <= 0xFF) {
  2755. buffer = new CHAR [1];
  2756. buffer [0] = cast(CHAR) key;
  2757. } else {
  2758. buffer = new CHAR [2];
  2759. buffer [0] = cast(CHAR) ((key >> 8) & 0xFF);
  2760. buffer [1] = cast(CHAR) (key & 0xFF);
  2761. }
  2762. wchar [] unicode = new wchar [1];
  2763. int cp = codePage !is 0 ? codePage : OS.CP_ACP;
  2764. int count = OS.MultiByteToWideChar (cp, OS.MB_PRECOMPOSED, buffer.ptr, buffer.length, unicode.ptr, 1);
  2765. if (count is 0) return 0;
  2766. return unicode [0];
  2767. }
  2768. private static extern(Windows) int messageProcFunc (HWND hwnd, uint msg, uint wParam, int lParam) {
  2769. Display d = Display.getCurrent();
  2770. return d.messageProc( hwnd, msg, wParam, lParam );
  2771. }
  2772. int messageProc (HWND hwnd, uint msg, uint wParam, int lParam) {
  2773. switch (msg) {
  2774. case SWT_RUNASYNC: {
  2775. if (runMessagesInIdle) runAsyncMessages (false);
  2776. break;
  2777. }
  2778. case SWT_KEYMSG: {
  2779. bool consumed = false;
  2780. MSG* keyMsg = cast(MSG*) lParam;
  2781. Control control = findControl (keyMsg.hwnd);
  2782. if (control !is null) {
  2783. /*
  2784. * Feature in Windows. When the user types an accent key such
  2785. * as ^ in order to get an accented character on a German keyboard,
  2786. * calling TranslateMessage(), ToUnicode() or ToAscii() consumes
  2787. * the key. This means that a subsequent call to TranslateMessage()
  2788. * will see a regular key rather than the accented key. The fix
  2789. * is to use MapVirtualKey() and VkKeyScan () to detect an accent
  2790. * and avoid calls to TranslateMessage().
  2791. */
  2792. bool accentKey = false;
  2793. switch (keyMsg.message) {
  2794. case OS.WM_KEYDOWN:
  2795. case OS.WM_SYSKEYDOWN: {
  2796. static if (!OS.IsWinCE) {
  2797. switch (keyMsg.wParam) {
  2798. case OS.VK_SHIFT:
  2799. case OS.VK_MENU:
  2800. case OS.VK_CONTROL:
  2801. case OS.VK_CAPITAL:
  2802. case OS.VK_NUMLOCK:
  2803. case OS.VK_SCROLL:
  2804. break;
  2805. default: {
  2806. /*
  2807. * Bug in Windows. The high bit in the result of MapVirtualKey() on
  2808. * Windows NT is bit 32 while the high bit on Windows 95 is bit 16.
  2809. * They should both be bit 32. The fix is to test the right bit.
  2810. */
  2811. int mapKey = OS.MapVirtualKey (keyMsg.wParam, 2);
  2812. if (mapKey !is 0) {
  2813. accentKey = (mapKey & (OS.IsWinNT ? 0x80000000 : 0x8000)) !is 0;
  2814. if (!accentKey) {
  2815. for (int i=0; i<ACCENTS.length; i++) {
  2816. int value = OS.VkKeyScan (ACCENTS [i]);
  2817. if (value !is -1 && (value & 0xFF) is keyMsg.wParam) {
  2818. int state = value >> 8;
  2819. if ((OS.GetKeyState (OS.VK_SHIFT) < 0) is ((state & 0x1) !is 0) &&
  2820. (OS.GetKeyState (OS.VK_CONTROL) < 0) is ((state & 0x2) !is 0) &&
  2821. (OS.GetKeyState (OS.VK_MENU) < 0) is ((state & 0x4) !is 0)) {
  2822. if ((state & 0x7) !is 0) accentKey = true;
  2823. break;
  2824. }
  2825. }
  2826. }
  2827. }
  2828. }
  2829. break;
  2830. }
  2831. }
  2832. }
  2833. break;
  2834. }
  2835. default:
  2836. }
  2837. if (!accentKey && !ignoreNextKey) {
  2838. keyMsg.hwnd = control.handle;
  2839. int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
  2840. do {
  2841. if (!(consumed |= filterMessage (keyMsg))) {
  2842. OS.TranslateMessage (keyMsg);
  2843. consumed |= OS.DispatchMessage (keyMsg) is 1;
  2844. }
  2845. } while (OS.PeekMessage (keyMsg, keyMsg.hwnd, OS.WM_KEYFIRST, OS.WM_KEYLAST, flags));
  2846. }
  2847. switch (keyMsg.message) {
  2848. case OS.WM_KEYDOWN:
  2849. case OS.WM_SYSKEYDOWN: {
  2850. switch (keyMsg.wParam) {
  2851. case OS.VK_SHIFT:
  2852. case OS.VK_MENU:
  2853. case OS.VK_CONTROL:
  2854. case OS.VK_CAPITAL:
  2855. case OS.VK_NUMLOCK:
  2856. case OS.VK_SCROLL:
  2857. break;
  2858. default: {
  2859. ignoreNextKey = accentKey;
  2860. break;
  2861. }
  2862. }
  2863. }
  2864. default:
  2865. }
  2866. }
  2867. switch (keyMsg.wParam) {
  2868. case OS.VK_SHIFT:
  2869. case OS.VK_MENU:
  2870. case OS.VK_CONTROL:
  2871. case OS.VK_CAPITAL:
  2872. case OS.VK_NUMLOCK:
  2873. case OS.VK_SCROLL:
  2874. consumed = true;
  2875. default:
  2876. }
  2877. if (consumed) {
  2878. auto hHeap = OS.GetProcessHeap ();
  2879. OS.HeapFree (hHeap, 0, cast(void*)lParam);
  2880. } else {
  2881. OS.PostMessage (embeddedHwnd, SWT_KEYMSG, wParam, lParam);
  2882. }
  2883. return 0;
  2884. }
  2885. case SWT_TRAYICONMSG: {
  2886. if (tray !is null) {
  2887. TrayItem [] items = tray.items;
  2888. for (int i=0; i<items.length; i++) {
  2889. TrayItem item = items [i];
  2890. if (item !is null && item.id is wParam) {
  2891. return item.messageProc (hwnd, msg, wParam, lParam);
  2892. }
  2893. }
  2894. }
  2895. return 0;
  2896. }
  2897. case OS.WM_ACTIVATEAPP: {
  2898. /*
  2899. * Feature in Windows. When multiple shells are
  2900. * disabled and one of the shells has an enabled
  2901. * dialog child and the user selects a disabled
  2902. * shell that does not have the enabled dialog
  2903. * child using the Task bar, Windows brings the
  2904. * disabled shell to the front. As soon as the
  2905. * user clicks on the disabled shell, the enabled
  2906. * dialog child comes to the front. This behavior
  2907. * is unspecified and seems strange. Normally, a
  2908. * disabled shell is frozen on the screen and the
  2909. * user cannot change the z-order by clicking with
  2910. * the mouse. The fix is to look for WM_ACTIVATEAPP
  2911. * and force the enabled dialog child to the front.
  2912. * This is typically what the user is expecting.
  2913. *
  2914. * NOTE: If the modal shell is disabled for any
  2915. * reason, it should not be brought to the front.
  2916. */
  2917. if (wParam !is 0) {
  2918. if (!isXMouseActive ()) {
  2919. auto hwndActive = OS.GetActiveWindow ();
  2920. if (hwndActive !is null && OS.IsWindowEnabled (hwndActive)) break;
  2921. Shell modal = modalDialog !is null ? modalDialog.parent : getModalShell ();
  2922. if (modal !is null && !modal.isDisposed ()) {
  2923. auto hwndModal = modal.handle;
  2924. if (OS.IsWindowEnabled (hwndModal)) {
  2925. modal.bringToTop ();
  2926. if (modal.isDisposed ()) break;
  2927. }
  2928. auto hwndPopup = OS.GetLastActivePopup (hwndModal);
  2929. if (hwndPopup !is null && hwndPopup !is modal.handle) {
  2930. if (getControl (hwndPopup) is null) {
  2931. if (OS.IsWindowEnabled (hwndPopup)) {
  2932. OS.SetActiveWindow (hwndPopup);
  2933. }
  2934. }
  2935. }
  2936. }
  2937. }
  2938. }
  2939. break;
  2940. }
  2941. case OS.WM_ENDSESSION: {
  2942. if (wParam !is 0) {
  2943. dispose ();
  2944. /*
  2945. * When the session is ending, no SWT program can continue
  2946. * to run. In order to avoid running code after the display
  2947. * has been disposed, exit from Java.
  2948. */
  2949. /* This code is intentionally commented */
  2950. // System.exit (0);
  2951. }
  2952. break;
  2953. }
  2954. case OS.WM_QUERYENDSESSION: {
  2955. Event event = new Event ();
  2956. sendEvent (SWT.Close, event);
  2957. if (!event.doit) return 0;
  2958. break;
  2959. }
  2960. case OS.WM_DWMCOLORIZATIONCOLORCHANGED: {
  2961. OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
  2962. break;
  2963. }
  2964. case OS.WM_SETTINGCHANGE: {
  2965. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
  2966. OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
  2967. break;
  2968. }
  2969. switch (wParam) {
  2970. case 0:
  2971. case 1:
  2972. case OS.SPI_SETHIGHCONTRAST:
  2973. OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
  2974. default:
  2975. }
  2976. break;
  2977. }
  2978. case OS.WM_THEMECHANGED: {
  2979. if (OS.COMCTL32_MAJOR >= 6) {
  2980. if (hButtonTheme_ !is null) OS.CloseThemeData (hButtonTheme_);
  2981. if (hEditTheme_ !is null) OS.CloseThemeData (hEditTheme_);
  2982. if (hExplorerBarTheme_ !is null) OS.CloseThemeData (hExplorerBarTheme_);
  2983. if (hScrollBarTheme_ !is null) OS.CloseThemeData (hScrollBarTheme_);
  2984. if (hTabTheme_ !is null) OS.CloseThemeData (hTabTheme_);
  2985. hButtonTheme_ = hEditTheme_ = hExplorerBarTheme_ = hScrollBarTheme_ = hTabTheme_ = null;
  2986. }
  2987. break;
  2988. }
  2989. case OS.WM_TIMER: {
  2990. if (wParam is SETTINGS_ID) {
  2991. OS.KillTimer (hwndMessage, SETTINGS_ID);
  2992. runSettings ();
  2993. } else {
  2994. runTimer (wParam);
  2995. }
  2996. break;
  2997. }
  2998. default: {
  2999. if (msg is SWT_TASKBARCREATED) {
  3000. if (tray !is null) {
  3001. TrayItem [] items = tray.items;
  3002. for (int i=0; i<items.length; i++) {
  3003. TrayItem item = items [i];
  3004. if (item !is null) item.recreate ();
  3005. }
  3006. }
  3007. }
  3008. }
  3009. }
  3010. return OS.DefWindowProc (hwnd, msg, wParam, lParam);
  3011. }
  3012. private static extern(Windows) int monitorEnumFunc (HMONITOR hmonitor, HDC hdc, RECT* lprcMonitor, int dwData) {
  3013. auto d = cast(Display)cast(void*)dwData;
  3014. return d.monitorEnumProc( hmonitor, hdc, lprcMonitor );
  3015. }
  3016. int monitorEnumProc (HMONITOR hmonitor, HDC hdc, RECT* lprcMonitor) {
  3017. if (monitorCount >= monitors.length) {
  3018. org.eclipse.swt.widgets.Monitor.Monitor[] newMonitors = new org.eclipse.swt.widgets.Monitor.Monitor [monitors.length + 4];
  3019. System.arraycopy (monitors, 0, newMonitors, 0, monitors.length);
  3020. monitors = newMonitors;
  3021. }
  3022. MONITORINFO lpmi;
  3023. lpmi.cbSize = MONITORINFO.sizeof;
  3024. OS.GetMonitorInfo (hmonitor, &lpmi);
  3025. org.eclipse.swt.widgets.Monitor.Monitor monitor = new org.eclipse.swt.widgets.Monitor.Monitor ();
  3026. monitor.handle = hmonitor;
  3027. monitor.x = lpmi.rcMonitor.left;
  3028. monitor.y = lpmi.rcMonitor.top;
  3029. monitor.width = lpmi.rcMonitor.right - lpmi.rcMonitor.left;
  3030. monitor.height = lpmi.rcMonitor.bottom - lpmi.rcMonitor.top;
  3031. monitor.clientX = lpmi.rcWork.left;
  3032. monitor.clientY = lpmi.rcWork.top;
  3033. monitor.clientWidth = lpmi.rcWork.right - lpmi.rcWork.left;
  3034. monitor.clientHeight = lpmi.rcWork.bottom - lpmi.rcWork.top;
  3035. monitors [monitorCount++] = monitor;
  3036. return 1;
  3037. }
  3038. private static extern(Windows) int msgFilterProcFunc (int code, uint wParam, int lParam) {
  3039. Display pThis = Display.getCurrent();
  3040. return pThis.msgFilterProc( code, wParam, lParam );
  3041. }
  3042. int msgFilterProc (int code, int wParam, int lParam) {
  3043. switch (code) {
  3044. case OS.MSGF_COMMCTRL_BEGINDRAG: {
  3045. if (!runDragDrop && !dragCancelled) {
  3046. *hookMsg = *cast(MSG*)lParam;
  3047. if (hookMsg.message is OS.WM_MOUSEMOVE) {
  3048. dragCancelled = true;
  3049. OS.SendMessage (hookMsg.hwnd, OS.WM_CANCELMODE, 0, 0);
  3050. }
  3051. }
  3052. break;
  3053. }
  3054. /*
  3055. * Feature in Windows. For some reason, when the user clicks
  3056. * a table or tree, the Windows hook WH_MSGFILTER is sent when
  3057. * an input event from a dialog box, message box, menu, or scroll
  3058. * bar did not occur, causing async messages to run at the wrong
  3059. * time. The fix is to check the message filter code.
  3060. */
  3061. case OS.MSGF_DIALOGBOX:
  3062. case OS.MSGF_MAINLOOP:
  3063. case OS.MSGF_MENU:
  3064. case OS.MSGF_MOVE:
  3065. case OS.MSGF_MESSAGEBOX:
  3066. case OS.MSGF_NEXTWINDOW:
  3067. case OS.MSGF_SCROLLBAR:
  3068. case OS.MSGF_SIZE: {
  3069. if (runMessages) {
  3070. *hookMsg = *cast(MSG*)lParam;
  3071. if (hookMsg.message is OS.WM_NULL) {
  3072. MSG msg;
  3073. int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
  3074. if (!OS.PeekMessage (&msg, null, 0, 0, flags)) {
  3075. if (runAsyncMessages (false)) wakeThread ();
  3076. }
  3077. }
  3078. }
  3079. break;
  3080. }
  3081. default:
  3082. }
  3083. return OS.CallNextHookEx (filterHook, code, wParam, lParam);
  3084. }
  3085. int numpadKey (int key) {
  3086. switch (key) {
  3087. case OS.VK_NUMPAD0: return '0';
  3088. case OS.VK_NUMPAD1: return '1';
  3089. case OS.VK_NUMPAD2: return '2';
  3090. case OS.VK_NUMPAD3: return '3';
  3091. case OS.VK_NUMPAD4: return '4';
  3092. case OS.VK_NUMPAD5: return '5';
  3093. case OS.VK_NUMPAD6: return '6';
  3094. case OS.VK_NUMPAD7: return '7';
  3095. case OS.VK_NUMPAD8: return '8';
  3096. case OS.VK_NUMPAD9: return '9';
  3097. case OS.VK_MULTIPLY: return '*';
  3098. case OS.VK_ADD: return '+';
  3099. case OS.VK_SEPARATOR: return '\0';
  3100. case OS.VK_SUBTRACT: return '-';
  3101. case OS.VK_DECIMAL: return '.';
  3102. case OS.VK_DIVIDE: return '/';
  3103. default:
  3104. }
  3105. return 0;
  3106. }
  3107. /**
  3108. * Generate a low level system event.
  3109. *
  3110. * <code>post</code> is used to generate low level keyboard
  3111. * and mouse events. The intent is to enable automated UI
  3112. * testing by simulating the input from the user. Most
  3113. * SWT applications should never need to call this method.
  3114. * <p>
  3115. * Note that this operation can fail when the operating system
  3116. * fails to generate the event for any reason. For example,
  3117. * this can happen when there is no such key or mouse button
  3118. * or when the system event queue is full.
  3119. * </p>
  3120. * <p>
  3121. * <b>Event Types:</b>
  3122. * <p>KeyDown, KeyUp
  3123. * <p>The following fields in the <code>Event</code> apply:
  3124. * <ul>
  3125. * <li>(in) type KeyDown or KeyUp</li>
  3126. * <p> Either one of:
  3127. * <li>(in) character a character that corresponds to a keyboard key</li>
  3128. * <li>(in) keyCode the key code of the key that was typed,
  3129. * as defined by the key code constants in class <code>SWT</code></li>
  3130. * </ul>
  3131. * <p>MouseDown, MouseUp</p>
  3132. * <p>The following fields in the <code>Event</code> apply:
  3133. * <ul>
  3134. * <li>(in) type MouseDown or MouseUp
  3135. * <li>(in) button the button that is pressed or released
  3136. * </ul>
  3137. * <p>MouseMove</p>
  3138. * <p>The following fields in the <code>Event</code> apply:
  3139. * <ul>
  3140. * <li>(in) type MouseMove
  3141. * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
  3142. * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
  3143. * </ul>
  3144. * </dl>
  3145. *
  3146. * @param event the event to be generated
  3147. *
  3148. * @return true if the event was generated or false otherwise
  3149. *
  3150. * @exception IllegalArgumentException <ul>
  3151. * <li>ERROR_NULL_ARGUMENT - if the event is null</li>
  3152. * </ul>
  3153. * @exception SWTException <ul>
  3154. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3155. * </ul>
  3156. *
  3157. * @since 3.0
  3158. *
  3159. */
  3160. public bool post (Event event) {
  3161. synchronized (Device.classinfo) {
  3162. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  3163. if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
  3164. int type = event.type;
  3165. switch (type){
  3166. case SWT.KeyDown:
  3167. case SWT.KeyUp: {
  3168. KEYBDINPUT inputs;
  3169. inputs.wVk = cast(short) untranslateKey (event.keyCode);
  3170. if (inputs.wVk is 0) {
  3171. char key = cast(char)event.character;
  3172. switch (key) {
  3173. case SWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
  3174. case SWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
  3175. case SWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
  3176. case SWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
  3177. case SWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break;
  3178. /*
  3179. * Since there is no LF key on the keyboard, do not attempt
  3180. * to map LF to CR or attempt to post an LF key.
  3181. */
  3182. // case SWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
  3183. case SWT.LF: return false;
  3184. default: {
  3185. static if (OS.IsWinCE) {
  3186. inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key);
  3187. } else {
  3188. inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0));
  3189. if (inputs.wVk is -1) return false;
  3190. inputs.wVk &= 0xFF;
  3191. }
  3192. }
  3193. }
  3194. }
  3195. inputs.dwFlags = type is SWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
  3196. auto hHeap = OS.GetProcessHeap ();
  3197. auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
  3198. pInputs.type = OS.INPUT_KEYBOARD;
  3199. //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
  3200. pInputs.ki = inputs;
  3201. //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
  3202. bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
  3203. OS.HeapFree (hHeap, 0, pInputs);
  3204. return result;
  3205. }
  3206. case SWT.MouseDown:
  3207. case SWT.MouseMove:
  3208. case SWT.MouseUp:
  3209. case SWT.MouseWheel: {
  3210. MOUSEINPUT inputs;
  3211. if (type is SWT.MouseMove){
  3212. inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
  3213. int x= 0, y = 0, width = 0, height = 0;
  3214. if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
  3215. inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK;
  3216. x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
  3217. y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
  3218. width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
  3219. height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
  3220. } else {
  3221. width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
  3222. height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
  3223. }
  3224. inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1);
  3225. inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1);
  3226. } else {
  3227. if (type is SWT.MouseWheel) {
  3228. if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
  3229. inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
  3230. switch (event.detail) {
  3231. case SWT.SCROLL_PAGE:
  3232. inputs.mouseData = event.count * OS.WHEEL_DELTA;
  3233. break;
  3234. case SWT.SCROLL_LINE:
  3235. int value;
  3236. OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
  3237. inputs.mouseData = event.count * OS.WHEEL_DELTA / value;
  3238. break;
  3239. default: return false;
  3240. }
  3241. } else {
  3242. switch (event.button) {
  3243. case 1: inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
  3244. case 2: inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
  3245. case 3: inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
  3246. case 4: {
  3247. if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
  3248. inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
  3249. inputs.mouseData = OS.XBUTTON1;
  3250. break;
  3251. }
  3252. case 5: {
  3253. if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
  3254. inputs.dwFlags = type is SWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
  3255. inputs.mouseData = OS.XBUTTON2;
  3256. break;
  3257. }
  3258. default: return false;
  3259. }
  3260. }
  3261. }
  3262. auto hHeap = OS.GetProcessHeap ();
  3263. auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
  3264. pInputs.type = OS.INPUT_MOUSE;
  3265. //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
  3266. pInputs.mi = inputs;
  3267. bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
  3268. OS.HeapFree (hHeap, 0, pInputs);
  3269. return result;
  3270. }
  3271. default:
  3272. }
  3273. return false;
  3274. }
  3275. }
  3276. void postEvent (Event event) {
  3277. /*
  3278. * Place the event at the end of the event queue.
  3279. * This code is always called in the Display's
  3280. * thread so it must be re-enterant but does not
  3281. * need to be synchronized.
  3282. */
  3283. if (eventQueue is null) eventQueue = new Event [4];
  3284. int index = 0;
  3285. int length_ = eventQueue.length;
  3286. while (index < length_) {
  3287. if (eventQueue [index] is null) break;
  3288. index++;
  3289. }
  3290. if (index is length_) {
  3291. Event [] newQueue = new Event [length_ + 4];
  3292. System.arraycopy (eventQueue, 0, newQueue, 0, length_);
  3293. eventQueue = newQueue;
  3294. }
  3295. eventQueue [index] = event;
  3296. }
  3297. /**
  3298. * Reads an event from the operating system's event queue,
  3299. * dispatches it appropriately, and returns <code>true</code>
  3300. * if there is potentially more work to do, or <code>false</code>
  3301. * if the caller can sleep until another event is placed on
  3302. * the event queue.
  3303. * <p>
  3304. * In addition to checking the system event queue, this method also
  3305. * checks if any inter-thread messages (created by <code>syncExec()</code>
  3306. * or <code>asyncExec()</code>) are waiting to be processed, and if
  3307. * so handles them before returning.
  3308. * </p>
  3309. *
  3310. * @return <code>false</code> if the caller can sleep upon return from this method
  3311. *
  3312. * @exception SWTException <ul>
  3313. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3314. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3315. * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
  3316. * </ul>
  3317. *
  3318. * @see #sleep
  3319. * @see #wake
  3320. */
  3321. public bool readAndDispatch () {
  3322. checkDevice ();
  3323. lpStartupInfo = null;
  3324. drawMenuBars ();
  3325. runPopups ();
  3326. if (OS.PeekMessage (msg, null, 0, 0, OS.PM_REMOVE)) {
  3327. if (!filterMessage (msg)) {
  3328. OS.TranslateMessage (msg);
  3329. OS.DispatchMessage (msg);
  3330. }
  3331. runDeferredEvents ();
  3332. return true;
  3333. }
  3334. return runMessages && runAsyncMessages (false);
  3335. }
  3336. static void register (Display display) {
  3337. static_this();
  3338. synchronized (Device.classinfo) {
  3339. for (int i=0; i<Displays.length; i++) {
  3340. if (Displays [i] is null) {
  3341. Displays [i] = display;
  3342. return;
  3343. }
  3344. }
  3345. Display [] newDisplays = new Display [Displays.length + 4];
  3346. System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
  3347. newDisplays [Displays.length] = display;
  3348. Displays = newDisplays;
  3349. }
  3350. }
  3351. /**
  3352. * Releases any internal resources back to the operating
  3353. * system and clears all fields except the device handle.
  3354. * <p>
  3355. * Disposes all shells which are currently open on the display.
  3356. * After this method has been invoked, all related related shells
  3357. * will answer <code>true</code> when sent the message
  3358. * <code>isDisposed()</code>.
  3359. * </p><p>
  3360. * When a device is destroyed, resources that were acquired
  3361. * on behalf of the programmer need to be returned to the
  3362. * operating system. For example, if the device allocated a
  3363. * font to be used as the system font, this font would be
  3364. * freed in <code>release</code>. Also,to assist the garbage
  3365. * collector and minimize the amount of memory that is not
  3366. * reclaimed when the programmer keeps a reference to a
  3367. * disposed device, all fields except the handle are zero'd.
  3368. * The handle is needed by <code>destroy</code>.
  3369. * </p>
  3370. * This method is called before <code>destroy</code>.
  3371. *
  3372. * @see Device#dispose
  3373. * @see #destroy
  3374. */
  3375. override protected void release () {
  3376. sendEvent (SWT.Dispose, new Event ());
  3377. Shell [] shells = getShells ();
  3378. for (int i=0; i<shells.length; i++) {
  3379. Shell shell = shells [i];
  3380. if (!shell.isDisposed ()) shell.dispose ();
  3381. }
  3382. if (tray !is null) tray.dispose ();
  3383. tray = null;
  3384. while (readAndDispatch ()) {}
  3385. if (disposeList !is null) {
  3386. for (int i=0; i<disposeList.length; i++) {
  3387. if (disposeList [i] !is null) disposeList [i].run ();
  3388. }
  3389. }
  3390. disposeList = null;
  3391. synchronizer.releaseSynchronizer ();
  3392. synchronizer = null;
  3393. releaseDisplay ();
  3394. super.release ();
  3395. }
  3396. void releaseDisplay () {
  3397. if (embeddedHwnd !is null) {
  3398. OS.PostMessage (embeddedHwnd, SWT_DESTROY, 0, 0);
  3399. }
  3400. /* Release XP Themes */
  3401. if (OS.COMCTL32_MAJOR >= 6) {
  3402. if (hButtonTheme_ !is null) OS.CloseThemeData (hButtonTheme_);
  3403. if (hEditTheme_ !is null) OS.CloseThemeData (hEditTheme_);
  3404. if (hExplorerBarTheme_ !is null) OS.CloseThemeData (hExplorerBarTheme_);
  3405. if (hScrollBarTheme_ !is null) OS.CloseThemeData (hScrollBarTheme_);
  3406. if (hTabTheme_ !is null) OS.CloseThemeData (hTabTheme_);
  3407. hButtonTheme_ = hEditTheme_ = hExplorerBarTheme_ = hScrollBarTheme_ = hTabTheme_ = null;
  3408. }
  3409. /* Unhook the message hook */
  3410. static if (!OS.IsWinCE) {
  3411. if (msgHook !is null) OS.UnhookWindowsHookEx (msgHook);
  3412. msgHook = null;
  3413. }
  3414. /* Unhook the filter hook */
  3415. static if (!OS.IsWinCE) {
  3416. if (filterHook !is null) OS.UnhookWindowsHookEx (filterHook);
  3417. filterHook = null;
  3418. //msgFilterCallback.dispose ();
  3419. //msgFilterCallback = null;
  3420. //msgFilterProc_ = 0;
  3421. }
  3422. /* Unhook the idle hook */
  3423. static if (!OS.IsWinCE) {
  3424. if (idleHook !is null) OS.UnhookWindowsHookEx (idleHook);
  3425. idleHook = null;
  3426. //foregroundIdleCallback.dispose ();
  3427. //foregroundIdleCallback = null;
  3428. //foregroundIdleProc_ = 0;
  3429. }
  3430. /* Destroy the message only HWND */
  3431. if (hwndMessage !is null) OS.DestroyWindow (hwndMessage);
  3432. hwndMessage = null;
  3433. //messageCallback.dispose ();
  3434. //messageCallback = null;
  3435. //messageProc_ = 0;
  3436. /* Unregister the SWT window class */
  3437. auto hHeap = OS.GetProcessHeap ();
  3438. auto hInstance = OS.GetModuleHandle (null);
  3439. OS.UnregisterClass (windowClass_.ptr, hInstance);
  3440. /* Unregister the SWT drop shadow window class */
  3441. OS.UnregisterClass (windowShadowClass.ptr, hInstance);
  3442. windowClass_ = windowShadowClass = null;
  3443. //windowCallback.dispose ();
  3444. //windowCallback = null;
  3445. //windowProc_ = 0;
  3446. /* Release the System fonts */
  3447. if (systemFont !is null) systemFont.dispose ();
  3448. systemFont = null;
  3449. lfSystemFont = null;
  3450. /* Release the System Images */
  3451. if (errorImage !is null) errorImage.dispose ();
  3452. if (infoImage !is null) infoImage.dispose ();
  3453. if (questionImage !is null) questionImage.dispose ();
  3454. if (warningIcon !is null) warningIcon.dispose ();
  3455. errorImage = infoImage = questionImage = warningIcon = null;
  3456. /* Release Sort Indicators */
  3457. if (upArrow !is null) upArrow.dispose ();
  3458. if (downArrow !is null) downArrow.dispose ();
  3459. upArrow = downArrow = null;
  3460. /* Release the System Cursors */
  3461. for (int i = 0; i < cursors.length; i++) {
  3462. if (cursors [i] !is null) cursors [i].dispose ();
  3463. }
  3464. cursors = null;
  3465. /* Release Acquired Resources */
  3466. if (resources !is null) {
  3467. for (int i=0; i<resources.length; i++) {
  3468. if (resources [i] !is null) resources [i].dispose ();
  3469. }
  3470. resources = null;
  3471. }
  3472. /* Release Custom Colors for ChooseColor */
  3473. if (lpCustColors !is null) OS.HeapFree (hHeap, 0, lpCustColors);
  3474. lpCustColors = null;
  3475. /* Uninitialize OLE */
  3476. static if (!OS.IsWinCE) OS.OleUninitialize ();
  3477. /* Uninitialize buffered painting */
  3478. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
  3479. OS.BufferedPaintUnInit ();
  3480. }
  3481. /* Release references */
  3482. thread = null;
  3483. msg = null;
  3484. hookMsg = null;
  3485. //keyboard = null;
  3486. modalDialog = null;
  3487. modalShells = null;
  3488. data = null;
  3489. keys = null;
  3490. values = null;
  3491. bars = popups = null;
  3492. indexTable = null;
  3493. timerIds = null;
  3494. controlTable = null;
  3495. lastControl = lastGetControl = lastHittestControl = null;
  3496. imageList = toolImageList = toolHotImageList = toolDisabledImageList = null;
  3497. timerList = null;
  3498. tableBuffer = null;
  3499. columnVisible = null;
  3500. eventTable = filterTable = null;
  3501. items = null;
  3502. clickRect = null;
  3503. hdr = null;
  3504. plvfi = null;
  3505. /* Release handles */
  3506. threadId = 0;
  3507. }
  3508. void releaseImageList (ImageList list) {
  3509. int i = 0;
  3510. int length_ = imageList.length;
  3511. while (i < length_) {
  3512. if (imageList [i] is list) {
  3513. if (list.removeRef () > 0) return;
  3514. list.dispose ();
  3515. System.arraycopy (imageList, i + 1, imageList, i, --length_ - i);
  3516. imageList [length_] = null;
  3517. for (int j=0; j<length_; j++) {
  3518. if (imageList [j] !is null) return;
  3519. }
  3520. imageList = null;
  3521. return;
  3522. }
  3523. i++;
  3524. }
  3525. }
  3526. void releaseToolImageList (ImageList list) {
  3527. int i = 0;
  3528. int length_ = toolImageList.length;
  3529. while (i < length_) {
  3530. if (toolImageList [i] is list) {
  3531. if (list.removeRef () > 0) return;
  3532. list.dispose ();
  3533. System.arraycopy (toolImageList, i + 1, toolImageList, i, --length_ - i);
  3534. toolImageList [length_] = null;
  3535. for (int j=0; j<length_; j++) {
  3536. if (toolImageList [j] !is null) return;
  3537. }
  3538. toolImageList = null;
  3539. return;
  3540. }
  3541. i++;
  3542. }
  3543. }
  3544. void releaseToolHotImageList (ImageList list) {
  3545. int i = 0;
  3546. int length_ = toolHotImageList.length;
  3547. while (i < length_) {
  3548. if (toolHotImageList [i] is list) {
  3549. if (list.removeRef () > 0) return;
  3550. list.dispose ();
  3551. System.arraycopy (toolHotImageList, i + 1, toolHotImageList, i, --length_ - i);
  3552. toolHotImageList [length_] = null;
  3553. for (int j=0; j<length_; j++) {
  3554. if (toolHotImageList [j] !is null) return;
  3555. }
  3556. toolHotImageList = null;
  3557. return;
  3558. }
  3559. i++;
  3560. }
  3561. }
  3562. void releaseToolDisabledImageList (ImageList list) {
  3563. int i = 0;
  3564. int length_ = toolDisabledImageList.length;
  3565. while (i < length_) {
  3566. if (toolDisabledImageList [i] is list) {
  3567. if (list.removeRef () > 0) return;
  3568. list.dispose ();
  3569. System.arraycopy (toolDisabledImageList, i + 1, toolDisabledImageList, i, --length_ - i);
  3570. toolDisabledImageList [length_] = null;
  3571. for (int j=0; j<length_; j++) {
  3572. if (toolDisabledImageList [j] !is null) return;
  3573. }
  3574. toolDisabledImageList = null;
  3575. return;
  3576. }
  3577. i++;
  3578. }
  3579. }
  3580. /**
  3581. * Removes the listener from the collection of listeners who will
  3582. * be notified when an event of the given type occurs anywhere in
  3583. * a widget. The event type is one of the event constants defined
  3584. * in class <code>SWT</code>.
  3585. *
  3586. * @param eventType the type of event to listen for
  3587. * @param listener the listener which should no longer be notified when the event occurs
  3588. *
  3589. * @exception IllegalArgumentException <ul>
  3590. * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
  3591. * </ul>
  3592. * @exception SWTException <ul>
  3593. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3594. * </ul>
  3595. *
  3596. * @see Listener
  3597. * @see SWT
  3598. * @see #addFilter
  3599. * @see #addListener
  3600. *
  3601. * @since 3.0
  3602. */
  3603. public void removeFilter (int eventType, Listener listener) {
  3604. checkDevice ();
  3605. if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
  3606. if (filterTable is null) return;
  3607. filterTable.unhook (eventType, listener);
  3608. if (filterTable.size () is 0) filterTable = null;
  3609. }
  3610. /**
  3611. * Removes the listener from the collection of listeners who will
  3612. * be notified when an event of the given type occurs. The event type
  3613. * is one of the event constants defined in class <code>SWT</code>.
  3614. *
  3615. * @param eventType the type of event to listen for
  3616. * @param listener the listener which should no longer be notified
  3617. *
  3618. * @exception IllegalArgumentException <ul>
  3619. * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
  3620. * </ul>
  3621. * @exception SWTException <ul>
  3622. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3623. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3624. * </ul>
  3625. *
  3626. * @see Listener
  3627. * @see SWT
  3628. * @see #addListener
  3629. *
  3630. * @since 2.0
  3631. */
  3632. public void removeListener (int eventType, Listener listener) {
  3633. checkDevice ();
  3634. if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
  3635. if (eventTable is null) return;
  3636. eventTable.unhook (eventType, listener);
  3637. }
  3638. void removeBar (Menu menu) {
  3639. if (bars is null) return;
  3640. for (int i=0; i<bars.length; i++) {
  3641. if (bars [i] is menu) {
  3642. bars [i] = null;
  3643. return;
  3644. }
  3645. }
  3646. }
  3647. Control removeControl (HANDLE handle) {
  3648. if (handle is null) return null;
  3649. lastControl = lastGetControl = null;
  3650. Control control = null;
  3651. int index;
  3652. static if (USE_PROPERTY) {
  3653. index = cast(int)OS.RemoveProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
  3654. } else {
  3655. index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
  3656. OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, 0);
  3657. }
  3658. if (0 <= index && index < controlTable.length) {
  3659. control = controlTable [index];
  3660. controlTable [index] = null;
  3661. indexTable [index] = freeSlot;
  3662. freeSlot = index;
  3663. }
  3664. return control;
  3665. }
  3666. void removeMenuItem (MenuItem item) {
  3667. if (items is null) return;
  3668. items [item.id - ID_START] = null;
  3669. }
  3670. void removePopup (Menu menu) {
  3671. if (popups is null) return;
  3672. for (int i=0; i<popups.length; i++) {
  3673. if (popups [i] is menu) {
  3674. popups [i] = null;
  3675. return;
  3676. }
  3677. }
  3678. }
  3679. bool runAsyncMessages (bool all) {
  3680. return synchronizer.runAsyncMessages (all);
  3681. }
  3682. bool runDeferredEvents () {
  3683. /*
  3684. * Run deferred events. This code is always
  3685. * called in the Display's thread so it must
  3686. * be re-enterant but need not be synchronized.
  3687. */
  3688. while (eventQueue !is null) {
  3689. /* Take an event off the queue */
  3690. Event event = eventQueue [0];
  3691. if (event is null) break;
  3692. int length_ = eventQueue.length;
  3693. System.arraycopy (eventQueue, 1, eventQueue, 0, --length_);
  3694. eventQueue [length_] = null;
  3695. /* Run the event */
  3696. Widget widget = event.widget;
  3697. if (widget !is null && !widget.isDisposed ()) {
  3698. Widget item = event.item;
  3699. if (item is null || !item.isDisposed ()) {
  3700. widget.sendEvent (event);
  3701. }
  3702. }
  3703. /*
  3704. * At this point, the event queue could
  3705. * be null due to a recursive invocation
  3706. * when running the event.
  3707. */
  3708. }
  3709. /* Clear the queue */
  3710. eventQueue = null;
  3711. return true;
  3712. }
  3713. bool runPopups () {
  3714. if (popups is null) return false;
  3715. bool result = false;
  3716. while (popups !is null) {
  3717. Menu menu = popups [0];
  3718. if (menu is null) break;
  3719. int length_ = popups.length;
  3720. System.arraycopy (popups, 1, popups, 0, --length_);
  3721. popups [length_] = null;
  3722. runDeferredEvents ();
  3723. if (!menu.isDisposed ()) menu._setVisible (true);
  3724. result = true;
  3725. }
  3726. popups = null;
  3727. return result;
  3728. }
  3729. void runSettings () {
  3730. Font oldFont = getSystemFont ();
  3731. saveResources ();
  3732. updateImages ();
  3733. sendEvent (SWT.Settings, null);
  3734. Font newFont = getSystemFont ();
  3735. bool sameFont = cast(bool)( oldFont ==/*eq*/ newFont );
  3736. Shell [] shells = getShells ();
  3737. for (int i=0; i<shells.length; i++) {
  3738. Shell shell = shells [i];
  3739. if (!shell.isDisposed ()) {
  3740. if (!sameFont) {
  3741. shell.updateFont (oldFont, newFont);
  3742. }
  3743. /* This code is intentionally commented */
  3744. //shell.redraw (true);
  3745. shell.layout (true, true);
  3746. }
  3747. }
  3748. }
  3749. bool runTimer (int /*long*/ id) {
  3750. if (timerList !is null && timerIds !is null) {
  3751. int index = 0;
  3752. while (index <timerIds.length) {
  3753. if (timerIds [index] is id) {
  3754. OS.KillTimer (hwndMessage, timerIds [index]);
  3755. timerIds [index] = 0;
  3756. Runnable runnable = timerList [index];
  3757. timerList [index] = null;
  3758. if (runnable !is null) runnable.run ();
  3759. return true;
  3760. }
  3761. index++;
  3762. }
  3763. }
  3764. return false;
  3765. }
  3766. void saveResources () {
  3767. int resourceCount = 0;
  3768. if (resources is null) {
  3769. resources = new Resource [RESOURCE_SIZE];
  3770. } else {
  3771. resourceCount = resources.length;
  3772. Resource [] newResources = new Resource [resourceCount + RESOURCE_SIZE];
  3773. System.arraycopy (resources, 0, newResources, 0, resourceCount);
  3774. resources = newResources;
  3775. }
  3776. if (systemFont !is null) {
  3777. static if (!OS.IsWinCE) {
  3778. NONCLIENTMETRICS info;
  3779. info.cbSize = NONCLIENTMETRICS.sizeof;
  3780. if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
  3781. LOGFONT* logFont = &info.lfMessageFont;
  3782. if (lfSystemFont is null ||
  3783. logFont.lfCharSet !is lfSystemFont.lfCharSet ||
  3784. logFont.lfHeight !is lfSystemFont.lfHeight ||
  3785. logFont.lfWidth !is lfSystemFont.lfWidth ||
  3786. logFont.lfEscapement !is lfSystemFont.lfEscapement ||
  3787. logFont.lfOrientation !is lfSystemFont.lfOrientation ||
  3788. logFont.lfWeight !is lfSystemFont.lfWeight ||
  3789. logFont.lfItalic !is lfSystemFont.lfItalic ||
  3790. logFont.lfUnderline !is lfSystemFont.lfUnderline ||
  3791. logFont.lfStrikeOut !is lfSystemFont.lfStrikeOut ||
  3792. logFont.lfCharSet !is lfSystemFont.lfCharSet ||
  3793. logFont.lfOutPrecision !is lfSystemFont.lfOutPrecision ||
  3794. logFont.lfClipPrecision !is lfSystemFont.lfClipPrecision ||
  3795. logFont.lfQuality !is lfSystemFont.lfQuality ||
  3796. logFont.lfPitchAndFamily !is lfSystemFont.lfPitchAndFamily ||
  3797. getFontName (logFont) !=/*eq*/ getFontName (lfSystemFont)) {
  3798. resources [resourceCount++] = systemFont;
  3799. lfSystemFont = logFont;
  3800. systemFont = null;
  3801. }
  3802. }
  3803. }
  3804. }
  3805. if (errorImage !is null) resources [resourceCount++] = errorImage;
  3806. if (infoImage !is null) resources [resourceCount++] = infoImage;
  3807. if (questionImage !is null) resources [resourceCount++] = questionImage;
  3808. if (warningIcon !is null) resources [resourceCount++] = warningIcon;
  3809. errorImage = infoImage = questionImage = warningIcon = null;
  3810. for (int i=0; i<cursors.length; i++) {
  3811. if (cursors [i] !is null) resources [resourceCount++] = cursors [i];
  3812. cursors [i] = null;
  3813. }
  3814. if (resourceCount < RESOURCE_SIZE) {
  3815. Resource [] newResources = new Resource [resourceCount];
  3816. System.arraycopy (resources, 0, newResources, 0, resourceCount);
  3817. resources = newResources;
  3818. }
  3819. }
  3820. void sendEvent (int eventType, Event event) {
  3821. if (eventTable is null && filterTable is null) {
  3822. return;
  3823. }
  3824. if (event is null) event = new Event ();
  3825. event.display = this;
  3826. event.type = eventType;
  3827. if (event.time is 0) event.time = getLastEventTime ();
  3828. if (!filterEvent (event)) {
  3829. if (eventTable !is null) eventTable.sendEvent (event);
  3830. }
  3831. }
  3832. /**
  3833. * Sets the location of the on-screen pointer relative to the top left corner
  3834. * of the screen. <b>Note: It is typically considered bad practice for a
  3835. * program to move the on-screen pointer location.</b>
  3836. *
  3837. * @param x the new x coordinate for the cursor
  3838. * @param y the new y coordinate for the cursor
  3839. *
  3840. * @exception SWTException <ul>
  3841. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3842. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3843. * </ul>
  3844. *
  3845. * @since 2.1
  3846. */
  3847. public void setCursorLocation (int x, int y) {
  3848. checkDevice ();
  3849. OS.SetCursorPos (x, y);
  3850. }
  3851. /**
  3852. * Sets the location of the on-screen pointer relative to the top left corner
  3853. * of the screen. <b>Note: It is typically considered bad practice for a
  3854. * program to move the on-screen pointer location.</b>
  3855. *
  3856. * @param point new position
  3857. *
  3858. * @exception SWTException <ul>
  3859. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3860. * <li>ERROR_NULL_ARGUMENT - if the point is null
  3861. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3862. * </ul>
  3863. *
  3864. * @since 2.0
  3865. */
  3866. public void setCursorLocation (Point point) {
  3867. checkDevice ();
  3868. if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
  3869. setCursorLocation (point.x, point.y);
  3870. }
  3871. /**
  3872. * Sets the application defined property of the receiver
  3873. * with the specified name to the given argument.
  3874. * <p>
  3875. * Applications may have associated arbitrary objects with the
  3876. * receiver in this fashion. If the objects stored in the
  3877. * properties need to be notified when the display is disposed
  3878. * of, it is the application's responsibility provide a
  3879. * <code>disposeExec()</code> handler which does so.
  3880. * </p>
  3881. *
  3882. * @param key the name of the property
  3883. * @param value the new value for the property
  3884. *
  3885. * @exception SWTException <ul>
  3886. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3887. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3888. * </ul>
  3889. *
  3890. * @see #getData(String)
  3891. * @see #disposeExec(Runnable)
  3892. */
  3893. public void setData (String key, Object value) {
  3894. checkDevice ();
  3895. // SWT extension: allow null string
  3896. //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
  3897. if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) {
  3898. auto data = cast(Boolean) value;
  3899. runMessagesInIdle = data !is null && data.value;
  3900. return;
  3901. }
  3902. if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
  3903. Boolean data = cast(Boolean) value;
  3904. runMessagesInMessageProc = data !is null && data.booleanValue ();
  3905. return;
  3906. }
  3907. /* Remove the key/value pair */
  3908. if (value is null) {
  3909. if (keys is null) return;
  3910. int index = 0;
  3911. while (index < keys.length && keys [index]!=/*eq*/key) index++;
  3912. if (index is keys.length) return;
  3913. if (keys.length is 1) {
  3914. keys = null;
  3915. values = null;
  3916. } else {
  3917. String [] newKeys = new String [keys.length - 1];
  3918. Object [] newValues = new Object [values.length - 1];
  3919. System.arraycopy (keys, 0, newKeys, 0, index);
  3920. System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
  3921. System.arraycopy (values, 0, newValues, 0, index);
  3922. System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
  3923. keys = newKeys;
  3924. values = newValues;
  3925. }
  3926. return;
  3927. }
  3928. /* Add the key/value pair */
  3929. if (keys is null) {
  3930. keys.length = 1;
  3931. values.length = 1;
  3932. keys[0] = key;
  3933. values[0] = value;
  3934. return;
  3935. }
  3936. for (int i=0; i<keys.length; i++) {
  3937. if (keys [i] ==/*eq*/key ) {
  3938. values [i] = value;
  3939. return;
  3940. }
  3941. }
  3942. String [] newKeys = new String [keys.length + 1];
  3943. Object [] newValues = new Object [values.length + 1];
  3944. System.arraycopy (keys, 0, newKeys, 0, keys.length);
  3945. System.arraycopy (values, 0, newValues, 0, values.length);
  3946. newKeys [keys.length] = key;
  3947. newValues [values.length] = value;
  3948. keys = newKeys;
  3949. values = newValues;
  3950. }
  3951. /**
  3952. * Sets the application defined, display specific data
  3953. * associated with the receiver, to the argument.
  3954. * The <em>display specific data</em> is a single,
  3955. * unnamed field that is stored with every display.
  3956. * <p>
  3957. * Applications may put arbitrary objects in this field. If
  3958. * the object stored in the display specific data needs to
  3959. * be notified when the display is disposed of, it is the
  3960. * application's responsibility provide a
  3961. * <code>disposeExec()</code> handler which does so.
  3962. * </p>
  3963. *
  3964. * @param data the new display specific data
  3965. *
  3966. * @exception SWTException <ul>
  3967. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  3968. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  3969. * </ul>
  3970. *
  3971. * @see #getData()
  3972. * @see #disposeExec(Runnable)
  3973. */
  3974. public void setData (Object data) {
  3975. checkDevice ();
  3976. this.data = data;
  3977. }
  3978. /**
  3979. * On platforms which support it, sets the application name
  3980. * to be the argument. On Motif, for example, this can be used
  3981. * to set the name used for resource lookup. Specifying
  3982. * <code>null</code> for the name clears it.
  3983. *
  3984. * @param name the new app name or <code>null</code>
  3985. */
  3986. public static void setAppName (String name) {
  3987. /* Do nothing */
  3988. }
  3989. void setModalDialog (Dialog modalDailog) {
  3990. this.modalDialog = modalDailog;
  3991. Shell [] shells = getShells ();
  3992. for (int i=0; i<shells.length; i++) shells [i].updateModal ();
  3993. }
  3994. void setModalShell (Shell shell) {
  3995. if (modalShells is null) modalShells = new Shell [4];
  3996. int index = 0, length_ = modalShells.length;
  3997. while (index < length_) {
  3998. if (modalShells [index] is shell) return;
  3999. if (modalShells [index] is null) break;
  4000. index++;
  4001. }
  4002. if (index is length_) {
  4003. Shell [] newModalShells = new Shell [length_ + 4];
  4004. System.arraycopy (modalShells, 0, newModalShells, 0, length_);
  4005. modalShells = newModalShells;
  4006. }
  4007. modalShells [index] = shell;
  4008. Shell [] shells = getShells ();
  4009. for (int i=0; i<shells.length; i++) shells [i].updateModal ();
  4010. }
  4011. /**
  4012. * Sets the synchronizer used by the display to be
  4013. * the argument, which can not be null.
  4014. *
  4015. * @param synchronizer the new synchronizer for the display (must not be null)
  4016. *
  4017. * @exception IllegalArgumentException <ul>
  4018. * <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
  4019. * </ul>
  4020. * @exception SWTException <ul>
  4021. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  4022. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4023. * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
  4024. * </ul>
  4025. */
  4026. public void setSynchronizer (Synchronizer synchronizer) {
  4027. checkDevice ();
  4028. if (synchronizer is null) error (SWT.ERROR_NULL_ARGUMENT);
  4029. if (synchronizer is this.synchronizer) return;
  4030. Synchronizer oldSynchronizer;
  4031. synchronized (Device.classinfo) {
  4032. oldSynchronizer = this.synchronizer;
  4033. this.synchronizer = synchronizer;
  4034. }
  4035. if (oldSynchronizer !is null) {
  4036. oldSynchronizer.runAsyncMessages(true);
  4037. }
  4038. }
  4039. int shiftedKey (int key) {
  4040. static if (OS.IsWinCE) return 0;
  4041. /* Clear the virtual keyboard and press the shift key */
  4042. for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
  4043. keyboard [OS.VK_SHIFT] |= 0x80;
  4044. /* Translate the key to ASCII or UNICODE using the virtual keyboard */
  4045. static if (OS.IsUnicode) {
  4046. wchar result;
  4047. if (OS.ToUnicode (key, key, keyboard.ptr, &result, 1, 0) is 1) return result;
  4048. } else {
  4049. wchar result;
  4050. if (OS.ToAscii (key, key, keyboard.ptr, &result, 0) is 1) return result;
  4051. }
  4052. return 0;
  4053. }
  4054. /**
  4055. * Causes the user-interface thread to <em>sleep</em> (that is,
  4056. * to be put in a state where it does not consume CPU cycles)
  4057. * until an event is received or it is otherwise awakened.
  4058. *
  4059. * @return <code>true</code> if an event requiring dispatching was placed on the queue.
  4060. *
  4061. * @exception SWTException <ul>
  4062. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  4063. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4064. * </ul>
  4065. *
  4066. * @see #wake
  4067. */
  4068. public bool sleep () {
  4069. checkDevice ();
  4070. if (runMessages && getMessageCount () !is 0) return true;
  4071. static if (OS.IsWinCE) {
  4072. OS.MsgWaitForMultipleObjectsEx (0, null, OS.INFINITE, OS.QS_ALLINPUT, OS.MWMO_INPUTAVAILABLE);
  4073. return true;
  4074. }
  4075. return cast(bool) OS.WaitMessage ();
  4076. }
  4077. /**
  4078. * Causes the <code>run()</code> method of the runnable to
  4079. * be invoked by the user-interface thread at the next
  4080. * reasonable opportunity. The thread which calls this method
  4081. * is suspended until the runnable completes. Specifying <code>null</code>
  4082. * as the runnable simply wakes the user-interface thread.
  4083. * <p>
  4084. * Note that at the time the runnable is invoked, widgets
  4085. * that have the receiver as their display may have been
  4086. * disposed. Therefore, it is necessary to check for this
  4087. * case inside the runnable before accessing the widget.
  4088. * </p>
  4089. *
  4090. * @param runnable code to run on the user-interface thread or <code>null</code>
  4091. *
  4092. * @exception SWTException <ul>
  4093. * <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
  4094. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4095. * </ul>
  4096. *
  4097. * @see #asyncExec
  4098. */
  4099. public void syncExec (Runnable runnable) {
  4100. Synchronizer synchronizer;
  4101. synchronized (Device.classinfo) {
  4102. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  4103. synchronizer = this.synchronizer;
  4104. }
  4105. synchronizer.syncExec (runnable);
  4106. }
  4107. /**
  4108. * Causes the <code>run()</code> method of the runnable to
  4109. * be invoked by the user-interface thread after the specified
  4110. * number of milliseconds have elapsed. If milliseconds is less
  4111. * than zero, the runnable is not executed.
  4112. * <p>
  4113. * Note that at the time the runnable is invoked, widgets
  4114. * that have the receiver as their display may have been
  4115. * disposed. Therefore, it is necessary to check for this
  4116. * case inside the runnable before accessing the widget.
  4117. * </p>
  4118. *
  4119. * @param milliseconds the delay before running the runnable
  4120. * @param runnable code to run on the user-interface thread
  4121. *
  4122. * @exception IllegalArgumentException <ul>
  4123. * <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
  4124. * </ul>
  4125. * @exception SWTException <ul>
  4126. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  4127. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4128. * </ul>
  4129. *
  4130. * @see #asyncExec
  4131. */
  4132. public void timerExec (int milliseconds, Runnable runnable) {
  4133. checkDevice ();
  4134. if (runnable is null) error (SWT.ERROR_NULL_ARGUMENT);
  4135. assert( runnable );
  4136. if (timerList is null) timerList = new Runnable [4];
  4137. if (timerIds is null) timerIds = new int /*long*/ [4];
  4138. int index = 0;
  4139. while (index < timerList.length) {
  4140. if (timerList [index] is runnable) break;
  4141. index++;
  4142. }
  4143. int /*long*/ timerId = 0;
  4144. if (index !is timerList.length) {
  4145. timerId = timerIds [index];
  4146. if (milliseconds < 0) {
  4147. OS.KillTimer (hwndMessage, timerId);
  4148. timerList [index] = null;
  4149. timerIds [index] = 0;
  4150. return;
  4151. }
  4152. } else {
  4153. if (milliseconds < 0) return;
  4154. index = 0;
  4155. while (index < timerList.length) {
  4156. if (timerList [index] is null) break;
  4157. index++;
  4158. }
  4159. timerId = nextTimerId++;
  4160. if (index is timerList.length) {
  4161. Runnable [] newTimerList = new Runnable [timerList.length + 4];
  4162. SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
  4163. timerList = newTimerList;
  4164. int /*long*/ [] newTimerIds = new int /*long*/ [timerIds.length + 4];
  4165. System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
  4166. timerIds = newTimerIds;
  4167. }
  4168. }
  4169. int newTimerID = OS.SetTimer (hwndMessage, timerId, milliseconds, null);
  4170. if (newTimerID !is 0) {
  4171. timerList [index] = runnable;
  4172. timerIds [index] = newTimerID;
  4173. }
  4174. }
  4175. bool translateAccelerator (MSG* msg, Control control) {
  4176. accelKeyHit = true;
  4177. bool result = control.translateAccelerator (msg);
  4178. accelKeyHit = false;
  4179. return result;
  4180. }
  4181. static int translateKey (int key) {
  4182. for (int i=0; i<KeyTable.length; i++) {
  4183. if (KeyTable [i] [0] is key) return KeyTable [i] [1];
  4184. }
  4185. return 0;
  4186. }
  4187. bool translateMnemonic (MSG* msg, Control control) {
  4188. switch (msg.message) {
  4189. case OS.WM_CHAR:
  4190. case OS.WM_SYSCHAR:
  4191. return control.translateMnemonic (msg);
  4192. default:
  4193. }
  4194. return false;
  4195. }
  4196. bool translateTraversal (MSG* msg, Control control) {
  4197. switch (msg.message) {
  4198. case OS.WM_KEYDOWN:
  4199. switch (msg.wParam) {
  4200. case OS.VK_RETURN:
  4201. case OS.VK_ESCAPE:
  4202. case OS.VK_TAB:
  4203. case OS.VK_UP:
  4204. case OS.VK_DOWN:
  4205. case OS.VK_LEFT:
  4206. case OS.VK_RIGHT:
  4207. case OS.VK_PRIOR:
  4208. case OS.VK_NEXT:
  4209. return control.translateTraversal (msg);
  4210. default:
  4211. }
  4212. break;
  4213. case OS.WM_SYSKEYDOWN:
  4214. switch (msg.wParam) {
  4215. case OS.VK_MENU:
  4216. return control.translateTraversal (msg);
  4217. default:
  4218. }
  4219. break;
  4220. default:
  4221. }
  4222. return false;
  4223. }
  4224. static int untranslateKey (int key) {
  4225. for (int i=0; i<KeyTable.length; i++) {
  4226. if (KeyTable [i] [1] is key) return KeyTable [i] [0];
  4227. }
  4228. return 0;
  4229. }
  4230. /**
  4231. * Forces all outstanding paint requests for the display
  4232. * to be processed before this method returns.
  4233. *
  4234. * @exception SWTException <ul>
  4235. * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  4236. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4237. * </ul>
  4238. *
  4239. * @see Control#update()
  4240. */
  4241. public void update() {
  4242. checkDevice ();
  4243. /*
  4244. * Feature in Windows. When an application does not remove
  4245. * events from the event queue for some time, Windows assumes
  4246. * the application is not responding and no longer sends paint
  4247. * events to the application. The fix is to detect that the
  4248. * application is not responding and call PeekMessage() with
  4249. * PM_REMOVE to tell Windows that the application is ready
  4250. * to dispatch events. Note that the message does not have
  4251. * to be found or dispatched in order to wake Windows up.
  4252. *
  4253. * NOTE: This allows other cross thread messages to be delivered,
  4254. * most notably WM_ACTIVATE.
  4255. */
  4256. if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
  4257. if (OS.IsHungAppWindow (hwndMessage)) {
  4258. MSG msg;
  4259. int flags = OS.PM_REMOVE | OS.PM_NOYIELD;
  4260. OS.PeekMessage (&msg, hwndMessage, SWT_NULL, SWT_NULL, flags);
  4261. }
  4262. }
  4263. Shell[] shells = getShells ();
  4264. for (int i=0; i<shells.length; i++) {
  4265. Shell shell = shells [i];
  4266. if (!shell.isDisposed ()) shell.update (true);
  4267. }
  4268. }
  4269. void updateImages () {
  4270. if (upArrow !is null) upArrow.dispose ();
  4271. if (downArrow !is null) downArrow.dispose ();
  4272. upArrow = downArrow = null;
  4273. for (int i=0; i<controlTable.length; i++) {
  4274. Control control = controlTable [i];
  4275. if (control !is null) control.updateImages ();
  4276. }
  4277. }
  4278. /**
  4279. * If the receiver's user-interface thread was <code>sleep</code>ing,
  4280. * causes it to be awakened and start running again. Note that this
  4281. * method may be called from any thread.
  4282. *
  4283. * @exception SWTException <ul>
  4284. * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
  4285. * </ul>
  4286. *
  4287. * @see #sleep
  4288. */
  4289. public void wake () {
  4290. synchronized (Device.classinfo) {
  4291. if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
  4292. if (thread is Thread.currentThread ()) return;
  4293. wakeThread ();
  4294. }
  4295. }
  4296. void wakeThread () {
  4297. static if (OS.IsWinCE) {
  4298. OS.PostMessage (hwndMessage, OS.WM_NULL, 0, 0);
  4299. } else {
  4300. OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
  4301. }
  4302. }
  4303. /*
  4304. * Returns a single character, converted from the wide
  4305. * character set (WCS) used by Java to the specified
  4306. * multi-byte character set used by the operating system
  4307. * widgets.
  4308. *
  4309. * @param ch the WCS character
  4310. * @param codePage the code page used to convert the character
  4311. * @return the MBCS character
  4312. */
  4313. static int wcsToMbcs (wchar ch, int codePage) {
  4314. if (OS.IsUnicode) return ch;
  4315. if (ch <= 0x7F) return ch;
  4316. wchar[1] wc;
  4317. wc[0] = ch;
  4318. auto r = StrToMBCSs( String_valueOf(wc), codePage );
  4319. return r[0];
  4320. }
  4321. /*
  4322. * Returns a single character, converted from the wide
  4323. * character set (WCS) used by Java to the default
  4324. * multi-byte character set used by the operating system
  4325. * widgets.
  4326. *
  4327. * @param ch the WCS character
  4328. * @return the MBCS character
  4329. */
  4330. static int wcsToMbcs (wchar ch) {
  4331. return wcsToMbcs (ch, 0);
  4332. }
  4333. private static extern(Windows) int windowProcFunc (HWND hwnd, uint msg, uint wParam, int lParam) {
  4334. auto d = Display.getCurrent();
  4335. return d.windowProc( hwnd, msg, wParam, lParam );
  4336. }
  4337. int windowProc(){
  4338. return cast(int)&windowProcFunc;
  4339. }
  4340. int windowProc (HWND hwnd, uint msg, uint wParam, int lParam) {
  4341. /*
  4342. * Feature in Windows. On Vista only, it is faster to
  4343. * compute and answer the data for the visible columns
  4344. * of a table when scrolling, rather than just return
  4345. * the data for each column when asked.
  4346. */
  4347. if (columnVisible !is null) {
  4348. if (msg is OS.WM_NOTIFY && hwndParent is hwnd) {
  4349. OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
  4350. switch (hdr.code) {
  4351. case OS.LVN_GETDISPINFOA:
  4352. case OS.LVN_GETDISPINFOW: {
  4353. OS.MoveMemory (plvfi, lParam, OS.NMLVDISPINFO_sizeof);
  4354. if (0 <= plvfi.item.iSubItem && plvfi.item.iSubItem < columnCount) {
  4355. if (!columnVisible [plvfi.item.iSubItem]) return 0;
  4356. }
  4357. break;
  4358. }
  4359. default:
  4360. }
  4361. }
  4362. }
  4363. /*
  4364. * Bug in Adobe Reader 7.0. For some reason, when Adobe
  4365. * Reader 7.0 is deactivated from within Internet Explorer,
  4366. * it sends thousands of consecutive WM_NCHITTEST messages
  4367. * to the control that is under the cursor. It seems that
  4368. * if the control takes some time to respond to the message,
  4369. * Adobe stops sending them. The fix is to detect this case
  4370. * and sleep.
  4371. *
  4372. * NOTE: Under normal circumstances, Windows will never send
  4373. * consecutive WM_NCHITTEST messages to the same control without
  4374. * another message (normally WM_SETCURSOR) in between.
  4375. */
  4376. if (msg is OS.WM_NCHITTEST) {
  4377. if (hitCount++ >= 1024) {
  4378. try {Thread.sleep (1);} catch (Exception t) {}
  4379. }
  4380. } else {
  4381. hitCount = 0;
  4382. }
  4383. if (lastControl !is null && lastHwnd is hwnd) {
  4384. return lastControl.windowProc (hwnd, msg, wParam, lParam);
  4385. }
  4386. int index;
  4387. static if (USE_PROPERTY) {
  4388. index = cast(int)OS.GetProp (hwnd, cast(wchar*)SWT_OBJECT_INDEX) - 1;
  4389. } else {
  4390. index = OS.GetWindowLongPtr (hwnd, OS.GWLP_USERDATA) - 1;
  4391. }
  4392. if (0 <= index && index < controlTable.length) {
  4393. Control control = controlTable [index];
  4394. if (control !is null) {
  4395. lastHwnd = hwnd;
  4396. lastControl = control;
  4397. return control.windowProc (hwnd, msg, wParam, lParam);
  4398. }
  4399. }
  4400. return OS.DefWindowProc (hwnd, msg, wParam, lParam);
  4401. }
  4402. static String withCrLf (String string) {
  4403. /* If the string is empty, return the string. */
  4404. int length_ = string.length;
  4405. if (length_ is 0) return string;
  4406. /*
  4407. * Check for an LF or CR/LF and assume the rest of
  4408. * the string is formated that way. This will not
  4409. * work if the string contains mixed delimiters.
  4410. */
  4411. int i = string.indexOf ('\n', 0);
  4412. if (i is -1) return string;
  4413. if (i > 0 && string.charAt (i - 1) is '\r') {
  4414. return string;
  4415. }
  4416. /*
  4417. * The string is formatted with LF. Compute the
  4418. * number of lines and the size of the buffer
  4419. * needed to hold the result
  4420. */
  4421. i++;
  4422. int count = 1;
  4423. while (i < length_) {
  4424. if ((i = string.indexOf ('\n', i)) is -1) break;
  4425. count++; i++;
  4426. }
  4427. count += length_;
  4428. /* Create a new string with the CR/LF line terminator. */
  4429. i = 0;
  4430. StringBuffer result = new StringBuffer (count);
  4431. while (i < length_) {
  4432. int j = string.indexOf ('\n', i);
  4433. if (j is -1) j = length_;
  4434. result.append (string.substring (i, j));
  4435. if ((i = j) < length_) {
  4436. result.append ("\r\n"); //$NON-NLS-1$
  4437. i++;
  4438. }
  4439. }
  4440. return result.toString ();
  4441. }
  4442. String windowClass(){
  4443. return TCHARsToStr( windowClass_ );
  4444. }
  4445. }