PageRenderTime 76ms CodeModel.GetById 25ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full 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_YVIRTUALSCR

Large files files are truncated, but you can click here to view the full file