0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2006 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.widgets;
0011:
0012: import org.eclipse.swt.internal.*;
0013: import org.eclipse.swt.internal.carbon.CFRange;
0014: import org.eclipse.swt.internal.carbon.OS;
0015: import org.eclipse.swt.internal.carbon.CGPoint;
0016: import org.eclipse.swt.internal.carbon.CGRect;
0017: import org.eclipse.swt.internal.carbon.GDevice;
0018: import org.eclipse.swt.internal.carbon.HICommand;
0019: import org.eclipse.swt.internal.carbon.Rect;
0020: import org.eclipse.swt.internal.carbon.RGBColor;
0021:
0022: import org.eclipse.swt.*;
0023: import org.eclipse.swt.graphics.*;
0024:
0025: // GOOGLE: special hacks to allow Browser to function normally
0026: import org.eclipse.swt.browser.Browser;
0027:
0028: /**
0029: * Instances of this class are responsible for managing the
0030: * connection between SWT and the underlying operating
0031: * system. Their most important function is to implement
0032: * the SWT event loop in terms of the platform event model.
0033: * They also provide various methods for accessing information
0034: * about the operating system, and have overall control over
0035: * the operating system resources which SWT allocates.
0036: * <p>
0037: * Applications which are built with SWT will <em>almost always</em>
0038: * require only a single display. In particular, some platforms
0039: * which SWT supports will not allow more than one <em>active</em>
0040: * display. In other words, some platforms do not support
0041: * creating a new display if one already exists that has not been
0042: * sent the <code>dispose()</code> message.
0043: * <p>
0044: * In SWT, the thread which creates a <code>Display</code>
0045: * instance is distinguished as the <em>user-interface thread</em>
0046: * for that display.
0047: * </p>
0048: * The user-interface thread for a particular display has the
0049: * following special attributes:
0050: * <ul>
0051: * <li>
0052: * The event loop for that display must be run from the thread.
0053: * </li>
0054: * <li>
0055: * Some SWT API methods (notably, most of the public methods in
0056: * <code>Widget</code> and its subclasses), may only be called
0057: * from the thread. (To support multi-threaded user-interface
0058: * applications, class <code>Display</code> provides inter-thread
0059: * communication methods which allow threads other than the
0060: * user-interface thread to request that it perform operations
0061: * on their behalf.)
0062: * </li>
0063: * <li>
0064: * The thread is not allowed to construct other
0065: * <code>Display</code>s until that display has been disposed.
0066: * (Note that, this is in addition to the restriction mentioned
0067: * above concerning platform support for multiple displays. Thus,
0068: * the only way to have multiple simultaneously active displays,
0069: * even on platforms which support it, is to have multiple threads.)
0070: * </li>
0071: * </ul>
0072: * Enforcing these attributes allows SWT to be implemented directly
0073: * on the underlying operating system's event model. This has
0074: * numerous benefits including smaller footprint, better use of
0075: * resources, safer memory management, clearer program logic,
0076: * better performance, and fewer overall operating system threads
0077: * required. The down side however, is that care must be taken
0078: * (only) when constructing multi-threaded applications to use the
0079: * inter-thread communication mechanisms which this class provides
0080: * when required.
0081: * </p><p>
0082: * All SWT API methods which may only be called from the user-interface
0083: * thread are distinguished in their documentation by indicating that
0084: * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
0085: * SWT exception.
0086: * </p>
0087: * <dl>
0088: * <dt><b>Styles:</b></dt>
0089: * <dd>(none)</dd>
0090: * <dt><b>Events:</b></dt>
0091: * <dd>Close, Dispose</dd>
0092: * </dl>
0093: * <p>
0094: * IMPORTANT: This class is <em>not</em> intended to be subclassed.
0095: * </p>
0096: * @see #syncExec
0097: * @see #asyncExec
0098: * @see #wake
0099: * @see #readAndDispatch
0100: * @see #sleep
0101: * @see Device#dispose
0102: */
0103: public class Display extends Device {
0104:
0105: /* Windows and Events */
0106: static final int WAKE_CLASS = 'S' << 24 | 'W' << 16 | 'T' << 8
0107: | '-';
0108: static final int WAKE_KIND = 1;
0109: Event[] eventQueue;
0110: Callback actionCallback, appleEventCallback, commandCallback,
0111: controlCallback, accessibilityCallback, appearanceCallback;
0112: Callback drawItemCallback, itemDataCallback,
0113: itemNotificationCallback, itemCompareCallback;
0114: Callback hitTestCallback, keyboardCallback, menuCallback,
0115: mouseHoverCallback, helpCallback;
0116: Callback mouseCallback, trackingCallback, windowCallback,
0117: colorCallback, textInputCallback;
0118: int actionProc, appleEventProc, commandProc, controlProc,
0119: appearanceProc, accessibilityProc;
0120: int drawItemProc, itemDataProc, itemNotificationProc,
0121: itemCompareProc, helpProc;
0122: int hitTestProc, keyboardProc, menuProc, mouseHoverProc;
0123: int mouseProc, trackingProc, windowProc, colorProc, textInputProc;
0124: EventTable eventTable, filterTable;
0125: int queue, lastModifiers;
0126: boolean closing;
0127:
0128: boolean inPaint, needsPaint;
0129:
0130: /* GC */
0131: int gcWindow;
0132:
0133: /* Deferred dispose window */
0134: int disposeWindow;
0135: int[] disposeWindowList;
0136:
0137: /* Sync/Async Widget Communication */
0138: Synchronizer synchronizer = new Synchronizer(this );
0139: Thread thread;
0140:
0141: /* Widget Table */
0142: int freeSlot;
0143: int[] indexTable, property;
0144: Widget[] widgetTable;
0145: static final int GROW_SIZE = 1024;
0146: static final int SWT0 = ('s' << 24) + ('w' << 16) + ('t' << 8)
0147: + '0';
0148:
0149: /* Focus */
0150: int focusEvent;
0151: Control focusControl;
0152: Combo focusCombo;
0153: boolean ignoreFocus;
0154:
0155: /* Menus */
0156: Menu menuBar;
0157: Menu[] menus, popups;
0158: static final int ID_TEMPORARY = 1000;
0159: static final int ID_START = 1001;
0160:
0161: /* Display Shutdown */
0162: Runnable[] disposeList;
0163:
0164: /* System Tray */
0165: Tray tray;
0166:
0167: /* Timers */
0168: int[] timerIds;
0169: Runnable[] timerList;
0170: Callback timerCallback;
0171: int timerProc;
0172: boolean allowTimers = true;
0173:
0174: /* Current caret */
0175: Caret currentCaret;
0176: Callback caretCallback;
0177: int caretID, caretProc;
0178:
0179: /* Grabs */
0180: Control grabControl, mouseUpControl;
0181: boolean grabbing;
0182:
0183: /* Hover Help */
0184: int helpString;
0185: Widget helpWidget;
0186: int lastHelpX, lastHelpY;
0187:
0188: /* Mouse DoubleClick */
0189: int clickCount, clickCountButton;
0190:
0191: /* Mouse Enter/Exit/Hover */
0192: Control currentControl;
0193: int mouseHoverID;
0194: org.eclipse.swt.internal.carbon.Point dragMouseStart = null;
0195: boolean dragging, mouseMoved;
0196:
0197: /* Insets */
0198: Rect buttonInset, tabFolderNorthInset, tabFolderSouthInset,
0199: comboInset, editTextInset;
0200:
0201: /* Fonts */
0202: boolean smallFonts;
0203: boolean noFocusRing;
0204:
0205: /* Keyboard */
0206: int kchrPtr;
0207: int[] kchrState = new int[1];
0208:
0209: /* System Resources */
0210: Image errorImage, infoImage, warningImage;
0211: Cursor[] cursors = new Cursor[SWT.CURSOR_HAND + 1];
0212:
0213: /* System Settings */
0214: boolean runSettings;
0215: RGBColor highlightColor;
0216:
0217: /* Dock icon */
0218: int dockImage, dockImageData;
0219:
0220: /* Key Mappings. */
0221: static int[][] KeyTable = {
0222:
0223: /* Keyboard and Mouse Masks */
0224: { 58, SWT.ALT },
0225: { 56, SWT.SHIFT },
0226: { 59, SWT.CONTROL },
0227: { 55, SWT.COMMAND },
0228:
0229: /* Non-Numeric Keypad Keys */
0230: { 126, SWT.ARROW_UP },
0231: { 125, SWT.ARROW_DOWN },
0232: { 123, SWT.ARROW_LEFT },
0233: { 124, SWT.ARROW_RIGHT },
0234: { 116, SWT.PAGE_UP },
0235: { 121, SWT.PAGE_DOWN },
0236: { 115, SWT.HOME },
0237: { 119, SWT.END },
0238: // {??, SWT.INSERT},
0239:
0240: /* Virtual and Ascii Keys */
0241: { 51, SWT.BS }, { 36, SWT.CR }, { 117, SWT.DEL },
0242: { 53, SWT.ESC }, { 76, SWT.LF }, { 48, SWT.TAB },
0243:
0244: /* Functions Keys */
0245: { 122, SWT.F1 }, { 120, SWT.F2 }, { 99, SWT.F3 },
0246: { 118, SWT.F4 }, { 96, SWT.F5 }, { 97, SWT.F6 },
0247: { 98, SWT.F7 }, { 100, SWT.F8 }, { 101, SWT.F9 },
0248: { 109, SWT.F10 }, { 103, SWT.F11 }, { 111, SWT.F12 },
0249: { 105, SWT.F13 }, { 107, SWT.F14 }, { 113, SWT.F15 },
0250:
0251: /* Numeric Keypad Keys */
0252: { 67, SWT.KEYPAD_MULTIPLY }, { 69, SWT.KEYPAD_ADD },
0253: { 76, SWT.KEYPAD_CR }, { 78, SWT.KEYPAD_SUBTRACT },
0254: { 65, SWT.KEYPAD_DECIMAL }, { 75, SWT.KEYPAD_DIVIDE },
0255: { 82, SWT.KEYPAD_0 }, { 83, SWT.KEYPAD_1 },
0256: { 84, SWT.KEYPAD_2 }, { 85, SWT.KEYPAD_3 },
0257: { 86, SWT.KEYPAD_4 }, { 87, SWT.KEYPAD_5 },
0258: { 88, SWT.KEYPAD_6 }, { 89, SWT.KEYPAD_7 },
0259: { 91, SWT.KEYPAD_8 }, { 92, SWT.KEYPAD_9 },
0260: { 81, SWT.KEYPAD_EQUAL },
0261:
0262: /* Other keys */
0263: // {??, SWT.CAPS_LOCK},
0264: { 71, SWT.NUM_LOCK },
0265: // {??, SWT.SCROLL_LOCK},
0266: // {??, SWT.PAUSE},
0267: // {??, SWT.BREAK},
0268: // {??, SWT.PRINT_SCREEN},
0269: { 114, SWT.HELP },
0270:
0271: };
0272:
0273: static String APP_NAME = "SWT";
0274: static final String ADD_WIDGET_KEY = "org.eclipse.swt.internal.addWidget";
0275:
0276: /* Multiple Displays. */
0277: static Display Default;
0278: static Display[] Displays = new Display[4];
0279:
0280: /* Package Name */
0281: static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets.";
0282:
0283: /* Display Data */
0284: Object data;
0285: String[] keys;
0286: Object[] values;
0287:
0288: /*
0289: * TEMPORARY CODE. Install the runnable that
0290: * gets the current display. This code will
0291: * be removed in the future.
0292: */
0293: static {
0294: DeviceFinder = new Runnable() {
0295: public void run() {
0296: Device device = getCurrent();
0297: if (device == null) {
0298: device = getDefault();
0299: }
0300: setDevice(device);
0301: }
0302: };
0303: }
0304:
0305: /*
0306: * TEMPORARY CODE.
0307: */
0308: static void setDevice(Device device) {
0309: CurrentDevice = device;
0310: }
0311:
0312: static byte[] ascii(String name) {
0313: int length = name.length();
0314: char[] chars = new char[length];
0315: name.getChars(0, length, chars, 0);
0316: byte[] buffer = new byte[length + 1];
0317: for (int i = 0; i < length; i++) {
0318: buffer[i] = (byte) chars[i];
0319: }
0320: return buffer;
0321: }
0322:
0323: static int translateKey(int key) {
0324: for (int i = 0; i < KeyTable.length; i++) {
0325: if (KeyTable[i][0] == key)
0326: return KeyTable[i][1];
0327: }
0328: return 0;
0329: }
0330:
0331: static int untranslateKey(int key) {
0332: for (int i = 0; i < KeyTable.length; i++) {
0333: if (KeyTable[i][1] == key)
0334: return KeyTable[i][0];
0335: }
0336: return 0;
0337: }
0338:
0339: int actionProc(int theControl, int partCode) {
0340: Widget widget = getWidget(theControl);
0341: if (widget != null)
0342: return widget.actionProc(theControl, partCode);
0343: return OS.noErr;
0344: }
0345:
0346: int appearanceProc(int theAppleEvent, int reply, int handlerRefcon) {
0347: runSettings = true;
0348: wakeThread();
0349: return OS.eventNotHandledErr;
0350: }
0351:
0352: int appleEventProc(int nextHandler, int theEvent, int userData) {
0353: int eventClass = OS.GetEventClass(theEvent);
0354: int eventKind = OS.GetEventKind(theEvent);
0355: switch (eventClass) {
0356: case OS.kEventClassApplication:
0357: switch (eventKind) {
0358: case OS.kEventAppAvailableWindowBoundsChanged: {
0359: /* Reset the dock image in case the dock has been restarted */
0360: if (dockImage != 0) {
0361: int[] reason = new int[1];
0362: OS.GetEventParameter(theEvent,
0363: OS.kEventParamReason, OS.typeUInt32, null,
0364: 4, null, reason);
0365: if (reason[0] == OS.kAvailBoundsChangedForDock) {
0366: OS.SetApplicationDockTileImage(dockImage);
0367: }
0368: }
0369: break;
0370: }
0371: }
0372: break;
0373: case OS.kEventClassAppleEvent:
0374: int[] aeEventID = new int[1];
0375: if (OS.GetEventParameter(theEvent, OS.kEventParamAEEventID,
0376: OS.typeType, null, 4, null, aeEventID) == OS.noErr) {
0377: if (aeEventID[0] == OS.kAEQuitApplication) {
0378: Event event = new Event();
0379: sendEvent(SWT.Close, event);
0380: if (event.doit) {
0381: /*
0382: * When the application is closing, no SWT program can continue
0383: * to run. In order to avoid running code after the display has
0384: * been disposed, exit from Java.
0385: */
0386: dispose();
0387: System.exit(0);
0388: }
0389: return OS.userCanceledErr;
0390: }
0391: }
0392: break;
0393: }
0394: return OS.eventNotHandledErr;
0395: }
0396:
0397: /**
0398: * Adds the listener to the collection of listeners who will
0399: * be notified when an event of the given type occurs anywhere
0400: * in a widget. The event type is one of the event constants
0401: * defined in class <code>SWT</code>. When the event does occur,
0402: * the listener is notified by sending it the <code>handleEvent()</code>
0403: * message.
0404: * <p>
0405: * Setting the type of an event to <code>SWT.None</code> from
0406: * within the <code>handleEvent()</code> method can be used to
0407: * change the event type and stop subsequent Java listeners
0408: * from running. Because event filters run before other listeners,
0409: * event filters can both block other listeners and set arbitrary
0410: * fields within an event. For this reason, event filters are both
0411: * powerful and dangerous. They should generally be avoided for
0412: * performance, debugging and code maintenance reasons.
0413: * </p>
0414: *
0415: * @param eventType the type of event to listen for
0416: * @param listener the listener which should be notified when the event occurs
0417: *
0418: * @exception IllegalArgumentException <ul>
0419: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0420: * </ul>
0421: * @exception SWTException <ul>
0422: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
0423: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
0424: * </ul>
0425: *
0426: * @see Listener
0427: * @see SWT
0428: * @see #removeFilter
0429: * @see #removeListener
0430: *
0431: * @since 3.0
0432: */
0433: public void addFilter(int eventType, Listener listener) {
0434: checkDevice();
0435: if (listener == null)
0436: error(SWT.ERROR_NULL_ARGUMENT);
0437: if (filterTable == null)
0438: filterTable = new EventTable();
0439: filterTable.hook(eventType, listener);
0440: }
0441:
0442: /**
0443: * Adds the listener to the collection of listeners who will
0444: * be notified when an event of the given type occurs. The event
0445: * type is one of the event constants defined in class <code>SWT</code>.
0446: * When the event does occur in the display, the listener is notified by
0447: * sending it the <code>handleEvent()</code> message.
0448: *
0449: * @param eventType the type of event to listen for
0450: * @param listener the listener which should be notified when the event occurs
0451: *
0452: * @exception IllegalArgumentException <ul>
0453: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
0454: * </ul>
0455: * @exception SWTException <ul>
0456: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
0457: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
0458: * </ul>
0459: *
0460: * @see Listener
0461: * @see SWT
0462: * @see #removeListener
0463: *
0464: * @since 2.0
0465: */
0466: public void addListener(int eventType, Listener listener) {
0467: checkDevice();
0468: if (listener == null)
0469: error(SWT.ERROR_NULL_ARGUMENT);
0470: if (eventTable == null)
0471: eventTable = new EventTable();
0472: eventTable.hook(eventType, listener);
0473: }
0474:
0475: void addMenu(Menu menu) {
0476: if (menus == null)
0477: menus = new Menu[12];
0478: for (int i = 0; i < menus.length; i++) {
0479: if (menus[i] == null) {
0480: menu.id = (short) (ID_START + i);
0481: menus[i] = menu;
0482: return;
0483: }
0484: }
0485: Menu[] newMenus = new Menu[menus.length + 12];
0486: menu.id = (short) (ID_START + menus.length);
0487: newMenus[menus.length] = menu;
0488: System.arraycopy(menus, 0, newMenus, 0, menus.length);
0489: menus = newMenus;
0490: }
0491:
0492: void addPopup(Menu menu) {
0493: if (popups == null)
0494: popups = new Menu[4];
0495: int length = popups.length;
0496: for (int i = 0; i < length; i++) {
0497: if (popups[i] == menu)
0498: return;
0499: }
0500: int index = 0;
0501: while (index < length) {
0502: if (popups[index] == null)
0503: break;
0504: index++;
0505: }
0506: if (index == length) {
0507: Menu[] newPopups = new Menu[length + 4];
0508: System.arraycopy(popups, 0, newPopups, 0, length);
0509: popups = newPopups;
0510: }
0511: popups[index] = menu;
0512: }
0513:
0514: void addToDisposeWindow(int control) {
0515: int[] root = new int[1];
0516: if (disposeWindow == 0) {
0517: int[] outWindow = new int[1];
0518: OS.CreateNewWindow(OS.kOverlayWindowClass, 0, new Rect(),
0519: outWindow);
0520: disposeWindow = outWindow[0];
0521: OS.CreateRootControl(disposeWindow, root);
0522: } else {
0523: OS.GetRootControl(disposeWindow, root);
0524: }
0525: OS.EmbedControl(control, root[0]);
0526: }
0527:
0528: void addWidget(int handle, Widget widget) {
0529: if (handle == 0)
0530: return;
0531: if (freeSlot == -1) {
0532: int length = (freeSlot = indexTable.length) + GROW_SIZE;
0533: int[] newIndexTable = new int[length];
0534: Widget[] newWidgetTable = new Widget[length];
0535: System.arraycopy(indexTable, 0, newIndexTable, 0, freeSlot);
0536: System.arraycopy(widgetTable, 0, newWidgetTable, 0,
0537: freeSlot);
0538: for (int i = freeSlot; i < length - 1; i++) {
0539: newIndexTable[i] = i + 1;
0540: }
0541: newIndexTable[length - 1] = -1;
0542: indexTable = newIndexTable;
0543: widgetTable = newWidgetTable;
0544: }
0545: property[0] = freeSlot + 1;
0546: OS.SetControlProperty(handle, SWT0, SWT0, 4, property);
0547: int oldSlot = freeSlot;
0548: freeSlot = indexTable[oldSlot];
0549: indexTable[oldSlot] = -2;
0550: widgetTable[oldSlot] = widget;
0551: }
0552:
0553: void addDisposeWindow(int window) {
0554: if (disposeWindowList == null)
0555: disposeWindowList = new int[4];
0556: int length = disposeWindowList.length;
0557: for (int i = 0; i < length; i++) {
0558: if (disposeWindowList[i] == window)
0559: return;
0560: }
0561: int index = 0;
0562: while (index < length) {
0563: if (disposeWindowList[index] == 0)
0564: break;
0565: index++;
0566: }
0567: if (index == length) {
0568: int[] newList = new int[length + 4];
0569: System.arraycopy(disposeWindowList, 0, newList, 0, length);
0570: disposeWindowList = newList;
0571: }
0572: disposeWindowList[index] = window;
0573: }
0574:
0575: /**
0576: * Causes the <code>run()</code> method of the runnable to
0577: * be invoked by the user-interface thread at the next
0578: * reasonable opportunity. The caller of this method continues
0579: * to run in parallel, and is not notified when the
0580: * runnable has completed. Specifying <code>null</code> as the
0581: * runnable simply wakes the user-interface thread when run.
0582: * <p>
0583: * Note that at the time the runnable is invoked, widgets
0584: * that have the receiver as their display may have been
0585: * disposed. Therefore, it is necessary to check for this
0586: * case inside the runnable before accessing the widget.
0587: * </p>
0588: *
0589: * @param runnable code to run on the user-interface thread or <code>null</code>
0590: *
0591: * @exception SWTException <ul>
0592: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
0593: * </ul>
0594: *
0595: * @see #syncExec
0596: */
0597: public void asyncExec(Runnable runnable) {
0598: if (isDisposed())
0599: error(SWT.ERROR_DEVICE_DISPOSED);
0600: synchronizer.asyncExec(runnable);
0601: }
0602:
0603: /**
0604: * Causes the system hardware to emit a short sound
0605: * (if it supports this capability).
0606: *
0607: * @exception SWTException <ul>
0608: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
0609: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
0610: * </ul>
0611: */
0612: public void beep() {
0613: checkDevice();
0614: OS.SysBeep((short) 100);
0615: }
0616:
0617: int caretProc(int id, int clientData) {
0618: if (currentCaret == null || currentCaret.isDisposed())
0619: return 0;
0620: if (currentCaret.blinkCaret()) {
0621: int blinkRate = currentCaret.blinkRate;
0622: if (blinkRate == 0)
0623: return 0;
0624: OS.SetEventLoopTimerNextFireTime(id, blinkRate / 1000.0);
0625: } else {
0626: currentCaret = null;
0627: }
0628: return 0;
0629: }
0630:
0631: protected void checkDevice() {
0632: if (thread == null)
0633: error(SWT.ERROR_WIDGET_DISPOSED);
0634: if (thread != Thread.currentThread())
0635: error(SWT.ERROR_THREAD_INVALID_ACCESS);
0636: if (isDisposed())
0637: error(SWT.ERROR_DEVICE_DISPOSED);
0638: }
0639:
0640: /**
0641: * Checks that this class can be subclassed.
0642: * <p>
0643: * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
0644: * </p>
0645: *
0646: * @exception SWTException <ul>
0647: * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
0648: * </ul>
0649: *
0650: * @see Widget#checkSubclass
0651: */
0652: protected void checkSubclass() {
0653: if (!Display.isValidClass(getClass()))
0654: error(SWT.ERROR_INVALID_SUBCLASS);
0655: }
0656:
0657: int[] createImage(int type) {
0658: int[] ref = new int[1];
0659: int result = OS.GetIconRef(OS.kOnSystemDisk,
0660: OS.kSystemIconsCreator, type, ref);
0661: if (result != OS.noErr)
0662: return null;
0663: int[] family = new int[1];
0664: result = OS.IconRefToIconFamily(ref[0],
0665: OS.kSelectorAlLAvailableData, family);
0666: OS.ReleaseIconRef(ref[0]);
0667: if (result != OS.noErr)
0668: return null;
0669: int[] image = createImageFromFamily(family[0],
0670: OS.kLarge32BitData, OS.kLarge8BitMask, 32, 32);
0671: OS.DisposeHandle(family[0]);
0672: return image;
0673: }
0674:
0675: int[] createImageFromFamily(int family, int type, int maskType,
0676: int width, int height) {
0677: int dataHandle = OS.NewHandle(0);
0678: int result = OS.GetIconFamilyData(family, type, dataHandle);
0679: if (result != OS.noErr) {
0680: OS.DisposeHandle(dataHandle);
0681: return null;
0682: }
0683: int maskHandle = OS.NewHandle(0);
0684: result = OS.GetIconFamilyData(family, maskType, maskHandle);
0685: if (result != OS.noErr) {
0686: OS.DisposeHandle(maskHandle);
0687: OS.DisposeHandle(dataHandle);
0688: return null;
0689: }
0690: int bpr = width * 4;
0691: int dataSize = OS.GetHandleSize(dataHandle);
0692: int data = OS.NewPtrClear(dataSize);
0693: if (data == 0) {
0694: OS.DisposeHandle(maskHandle);
0695: OS.DisposeHandle(dataHandle);
0696: return null;
0697: }
0698: OS.HLock(dataHandle);
0699: OS.HLock(maskHandle);
0700: int[] iconPtr = new int[1];
0701: int[] maskPtr = new int[1];
0702: OS.memcpy(iconPtr, dataHandle, 4);
0703: OS.memcpy(maskPtr, maskHandle, 4);
0704: OS.memcpy(data, iconPtr[0], dataSize);
0705: int pixelCount = dataSize / 4;
0706: for (int i = 0; i < pixelCount; i++) {
0707: OS.memcpy(data + (i * 4), maskPtr[0] + i, 1);
0708: }
0709: OS.HUnlock(maskHandle);
0710: OS.HUnlock(dataHandle);
0711: OS.DisposeHandle(maskHandle);
0712: OS.DisposeHandle(dataHandle);
0713:
0714: int provider = OS.CGDataProviderCreateWithData(0, data,
0715: dataSize, 0);
0716: if (provider == 0) {
0717: OS.DisposePtr(data);
0718: return null;
0719: }
0720: int colorspace = OS.CGColorSpaceCreateDeviceRGB();
0721: if (colorspace == 0) {
0722: OS.CGDataProviderRelease(provider);
0723: OS.DisposePtr(data);
0724: return null;
0725: }
0726: int cgImage = OS.CGImageCreate(width, height, 8, 32, bpr,
0727: colorspace, OS.kCGImageAlphaFirst, provider, null,
0728: true, 0);
0729: OS.CGColorSpaceRelease(colorspace);
0730: OS.CGDataProviderRelease(provider);
0731:
0732: return new int[] { cgImage, data };
0733: }
0734:
0735: int createOverlayWindow() {
0736: int gdevice = OS.GetMainDevice();
0737: int[] ptr = new int[1];
0738: OS.memcpy(ptr, gdevice, 4);
0739: GDevice device = new GDevice();
0740: OS.memcpy(device, ptr[0], GDevice.sizeof);
0741: Rect rect = new Rect();
0742: OS.SetRect(rect, device.left, device.top, device.right,
0743: device.bottom);
0744: int[] outWindow = new int[1];
0745: OS.CreateNewWindow(OS.kOverlayWindowClass, 0, rect, outWindow);
0746: if (outWindow[0] == 0)
0747: SWT.error(SWT.ERROR_NO_HANDLES);
0748: return outWindow[0];
0749: }
0750:
0751: /**
0752: * Constructs a new instance of this class.
0753: * <p>
0754: * Note: The resulting display is marked as the <em>current</em>
0755: * display. If this is the first display which has been
0756: * constructed since the application started, it is also
0757: * marked as the <em>default</em> display.
0758: * </p>
0759: *
0760: * @exception SWTException <ul>
0761: * <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
0762: * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
0763: * </ul>
0764: *
0765: * @see #getCurrent
0766: * @see #getDefault
0767: * @see Widget#checkSubclass
0768: * @see Shell
0769: */
0770: public Display() {
0771: this (null);
0772: }
0773:
0774: /**
0775: * Constructs a new instance of this class using the parameter.
0776: *
0777: * @param data the device data
0778: */
0779: public Display(DeviceData data) {
0780: super (data);
0781: }
0782:
0783: static synchronized void checkDisplay(Thread thread,
0784: boolean multiple) {
0785: for (int i = 0; i < Displays.length; i++) {
0786: if (Displays[i] != null) {
0787: if (!multiple)
0788: SWT.error(SWT.ERROR_NOT_IMPLEMENTED, null,
0789: " [multiple displays]");
0790: if (Displays[i].thread == thread)
0791: SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
0792: }
0793: }
0794: }
0795:
0796: int colorProc(int inControl, int inMessage, int inDrawDepth,
0797: int inDrawInColor) {
0798: Widget widget = getWidget(inControl);
0799: if (widget != null)
0800: return widget.colorProc(inControl, inMessage, inDrawDepth,
0801: inDrawInColor);
0802: return OS.eventNotHandledErr;
0803: }
0804:
0805: int commandProc(int nextHandler, int theEvent, int userData) {
0806: int eventKind = OS.GetEventKind(theEvent);
0807: HICommand command = new HICommand();
0808: OS
0809: .GetEventParameter(theEvent,
0810: OS.kEventParamDirectObject, OS.typeHICommand,
0811: null, HICommand.sizeof, null, command);
0812: switch (eventKind) {
0813: case OS.kEventProcessCommand: {
0814: if (command.commandID == OS.kAEQuitApplication) {
0815: if (!closing)
0816: close();
0817: return OS.noErr;
0818: }
0819: if ((command.attributes & OS.kHICommandFromMenu) != 0) {
0820: if (userData != 0) {
0821: Widget widget = getWidget(userData);
0822: if (widget != null)
0823: return widget.commandProc(nextHandler,
0824: theEvent, userData);
0825: } else {
0826: int result = OS.eventNotHandledErr;
0827: int menuRef = command.menu_menuRef;
0828: short menuID = OS.GetMenuID(menuRef);
0829: Menu menu = getMenu(menuID);
0830: if (menu != null) {
0831: /*
0832: * Feature in the Macintosh. When a menu item is selected by the
0833: * user, the Macintosh sends kEventMenuOpening, remembers the index
0834: * of the item the user selected, sends kEventMenuClosed and then
0835: * sends kEventProcessCommand. If application code modifies the menu
0836: * inside of kEventMenuClosed by adding or removing items, the index
0837: * of the item that the user selected is invalid. The fix is to detect
0838: * that a menu has been modified during kEventMenuClosed and use the
0839: * last target item remembered kEventMenuTargetItem.
0840: */
0841: MenuItem item = null;
0842: if (menu.closed && menu.modified) {
0843: item = menu.lastTarget;
0844: } else {
0845: item = menu
0846: .getItem(command.menu_menuItemIndex - 1);
0847: }
0848: if (item != null) {
0849: result = item.kEventProcessCommand(
0850: nextHandler, theEvent, userData);
0851: }
0852: }
0853: OS.HiliteMenu((short) 0);
0854: return result;
0855: }
0856: }
0857: }
0858: }
0859: return OS.eventNotHandledErr;
0860: }
0861:
0862: Rect computeInset(int control) {
0863: int tempRgn = OS.NewRgn();
0864: Rect rect = new Rect();
0865: OS.GetControlRegion(control,
0866: (short) OS.kControlStructureMetaPart, tempRgn);
0867: OS.GetControlBounds(control, rect);
0868: Rect rgnRect = new Rect();
0869: OS.GetRegionBounds(tempRgn, rgnRect);
0870: OS.DisposeRgn(tempRgn);
0871: rect.left -= rgnRect.left;
0872: rect.top -= rgnRect.top;
0873: rect.right = (short) (rgnRect.right - rect.right);
0874: rect.bottom = (short) (rgnRect.bottom - rect.bottom);
0875: return rect;
0876: }
0877:
0878: int controlProc(int nextHandler, int theEvent, int userData) {
0879: Widget widget = getWidget(userData);
0880: if (widget != null)
0881: return widget.controlProc(nextHandler, theEvent, userData);
0882: return OS.eventNotHandledErr;
0883: }
0884:
0885: int accessibilityProc(int nextHandler, int theEvent, int userData) {
0886: Widget widget = getWidget(userData);
0887: if (widget != null)
0888: return widget.accessibilityProc(nextHandler, theEvent,
0889: userData);
0890: return OS.eventNotHandledErr;
0891: }
0892:
0893: static String convertToLf(String text) {
0894: char Cr = '\r';
0895: char Lf = '\n';
0896: int length = text.length();
0897: if (length == 0)
0898: return text;
0899:
0900: /* Check for an LF or CR/LF. Assume the rest of the string
0901: * is formated that way. This will not work if the string
0902: * contains mixed delimiters. */
0903: int i = text.indexOf(Lf, 0);
0904: if (i == -1 || i == 0)
0905: return text;
0906: if (text.charAt(i - 1) != Cr)
0907: return text;
0908:
0909: /* The string is formatted with CR/LF.
0910: * Create a new string with the LF line delimiter. */
0911: i = 0;
0912: StringBuffer result = new StringBuffer();
0913: while (i < length) {
0914: int j = text.indexOf(Cr, i);
0915: if (j == -1)
0916: j = length;
0917: String s = text.substring(i, j);
0918: result.append(s);
0919: i = j + 2;
0920: result.append(Lf);
0921: }
0922: return result.toString();
0923: }
0924:
0925: void clearMenuFlags() {
0926: if (menus == null)
0927: return;
0928: for (int i = 0; i < menus.length; i++) {
0929: Menu menu = menus[i];
0930: if (menu != null) {
0931: menu.modified = menu.closed = false;
0932: menu.lastTarget = null;
0933: }
0934: }
0935: }
0936:
0937: /**
0938: * Requests that the connection between SWT and the underlying
0939: * operating system be closed.
0940: *
0941: * @exception SWTException <ul>
0942: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
0943: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
0944: * </ul>
0945: *
0946: * @see Device#dispose
0947: *
0948: * @since 2.0
0949: */
0950: public void close() {
0951: checkDevice();
0952: closing = true;
0953: Event event = new Event();
0954: sendEvent(SWT.Close, event);
0955: if (event.doit)
0956: dispose();
0957: }
0958:
0959: /**
0960: * Creates the device in the operating system. If the device
0961: * does not have a handle, this method may do nothing depending
0962: * on the device.
0963: * <p>
0964: * This method is called before <code>init</code>.
0965: * </p>
0966: *
0967: * @param data the DeviceData which describes the receiver
0968: *
0969: * @see #init
0970: */
0971: protected void create(DeviceData data) {
0972: checkSubclass();
0973: checkDisplay(thread = Thread.currentThread(), false);
0974: createDisplay(data);
0975: register(this );
0976: if (Default == null)
0977: Default = this ;
0978: }
0979:
0980: void createDisplay(DeviceData data) {
0981: /*
0982: * Feature in the Macintosh. On OS 10.2, it is necessary
0983: * to explicitly check in with the Process Manager and set
0984: * the current process to be the front process in order for
0985: * windows to come to the front by default. The fix is call
0986: * both GetCurrentProcess() and SetFrontProcess().
0987: *
0988: * NOTE: It is not actually necessary to use the process
0989: * serial number returned by GetCurrentProcess() in the
0990: * call to SetFrontProcess() (ie. kCurrentProcess can be
0991: * used) but both functions must be called in order for
0992: * windows to come to the front.
0993: */
0994: int[] psn = new int[2];
0995: if (OS.GetCurrentProcess(psn) == OS.noErr) {
0996: int pid = OS.getpid();
0997: byte[] buffer = null;
0998: int ptr = OS.getenv(ascii("APP_NAME_" + pid));
0999: if (ptr != 0) {
1000: buffer = new byte[OS.strlen(ptr) + 1];
1001: OS.memcpy(buffer, ptr, buffer.length);
1002: } else {
1003: if (APP_NAME != null) {
1004: char[] chars = new char[APP_NAME.length()];
1005: APP_NAME.getChars(0, chars.length, chars, 0);
1006: int cfstring = OS
1007: .CFStringCreateWithCharacters(
1008: OS.kCFAllocatorDefault, chars,
1009: chars.length);
1010: if (cfstring != 0) {
1011: CFRange range = new CFRange();
1012: range.length = chars.length;
1013: int encoding = OS.CFStringGetSystemEncoding();
1014: int[] size = new int[1];
1015: int numChars = OS.CFStringGetBytes(cfstring,
1016: range, encoding, (byte) '?', true,
1017: null, 0, size);
1018: if (numChars != 0) {
1019: buffer = new byte[size[0] + 1];
1020: numChars = OS.CFStringGetBytes(cfstring,
1021: range, encoding, (byte) '?', true,
1022: buffer, size[0], size);
1023: }
1024: OS.CFRelease(cfstring);
1025: }
1026: }
1027: }
1028: if (buffer != null)
1029: OS.CPSSetProcessName(psn, buffer);
1030: OS.CPSEnableForegroundOperation(psn, 0x03, 0x3C, 0x2C,
1031: 0x1103);
1032: OS.SetFrontProcess(psn);
1033: ptr = OS.getenv(ascii("APP_ICON_" + pid));
1034: if (ptr != 0) {
1035: int[] image = readImageRef(ptr);
1036: if (image != null) {
1037: dockImage = image[0];
1038: dockImageData = image[1];
1039: OS.SetApplicationDockTileImage(dockImage);
1040: }
1041: }
1042: }
1043: /*
1044: * Feature in the Macintosh. In order to get the standard
1045: * application menu to appear on the menu bar, an application
1046: * must manipulate the menu bar. If the application does not
1047: * install a menu bar, the application menu will not appear.
1048: * The fix is to use ClearMenuBar() to manipulate the menu
1049: * bar before any application has had a chance install a menu
1050: * bar.
1051: */
1052: OS.ClearMenuBar();
1053: queue = OS.GetCurrentEventQueue();
1054: OS.TXNInitTextension(0, 0, 0);
1055:
1056: /* Save the current highlight color */
1057: OS.RegisterAppearanceClient();
1058: highlightColor = new RGBColor();
1059: OS.GetThemeBrushAsColor(
1060: (short) OS.kThemeBrushPrimaryHighlightColor,
1061: (short) getDepth(), true, highlightColor);
1062: }
1063:
1064: synchronized static void deregister(Display display) {
1065: for (int i = 0; i < Displays.length; i++) {
1066: if (display == Displays[i])
1067: Displays[i] = null;
1068: }
1069: }
1070:
1071: /**
1072: * Destroys the device in the operating system and releases
1073: * the device's handle. If the device does not have a handle,
1074: * this method may do nothing depending on the device.
1075: * <p>
1076: * This method is called after <code>release</code>.
1077: * </p>
1078: * @see Device#dispose
1079: * @see #release
1080: */
1081: protected void destroy() {
1082: if (this == Default)
1083: Default = null;
1084: deregister(this );
1085: destroyDisplay();
1086: }
1087:
1088: void destroyDisplay() {
1089: }
1090:
1091: /**
1092: * Causes the <code>run()</code> method of the runnable to
1093: * be invoked by the user-interface thread just before the
1094: * receiver is disposed. Specifying a <code>null</code> runnable
1095: * is ignored.
1096: *
1097: * @param runnable code to run at dispose time.
1098: *
1099: * @exception SWTException <ul>
1100: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1101: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1102: * </ul>
1103: */
1104: public void disposeExec(Runnable runnable) {
1105: checkDevice();
1106: if (disposeList == null)
1107: disposeList = new Runnable[4];
1108: for (int i = 0; i < disposeList.length; i++) {
1109: if (disposeList[i] == null) {
1110: disposeList[i] = runnable;
1111: return;
1112: }
1113: }
1114: Runnable[] newDisposeList = new Runnable[disposeList.length + 4];
1115: System.arraycopy(disposeList, 0, newDisposeList, 0,
1116: disposeList.length);
1117: newDisposeList[disposeList.length] = runnable;
1118: disposeList = newDisposeList;
1119: }
1120:
1121: void dragDetect(Control control) {
1122: if (!dragging && control.hooks(SWT.DragDetect)
1123: && dragMouseStart != null) {
1124: if (OS.WaitMouseMoved(dragMouseStart)) {
1125: dragging = true;
1126: Rect rect = new Rect();
1127: int window = OS.GetControlOwner(control.handle);
1128: int x, y;
1129: if (OS.HIVIEW) {
1130: CGPoint pt = new CGPoint();
1131: pt.x = dragMouseStart.h;
1132: pt.y = dragMouseStart.v;
1133: OS.HIViewConvertPoint(pt, 0, control.handle);
1134: x = (int) pt.x;
1135: y = (int) pt.y;
1136: OS.GetWindowBounds(window,
1137: (short) OS.kWindowStructureRgn, rect);
1138: } else {
1139: OS.GetControlBounds(control.handle, rect);
1140: x = dragMouseStart.h - rect.left;
1141: y = dragMouseStart.v - rect.top;
1142: OS.GetWindowBounds(window,
1143: (short) OS.kWindowContentRgn, rect);
1144: }
1145: x -= rect.left;
1146: y -= rect.top;
1147: control.sendDragEvent(x, y);
1148: dragMouseStart = null;
1149: }
1150: }
1151: }
1152:
1153: int drawItemProc(int browser, int item, int property,
1154: int itemState, int theRect, int gdDepth, int colorDevice) {
1155: Widget widget = getWidget(browser);
1156: if (widget != null)
1157: return widget.drawItemProc(browser, item, property,
1158: itemState, theRect, gdDepth, colorDevice);
1159: return OS.noErr;
1160: }
1161:
1162: void disposeWindows() {
1163: if (disposeWindow != 0) {
1164: OS.DisposeWindow(disposeWindow);
1165: disposeWindow = 0;
1166: }
1167: if (disposeWindowList != null) {
1168: for (int i = 0; i < disposeWindowList.length; i++) {
1169: if (disposeWindowList[i] != 0) {
1170: OS.DisposeWindow(disposeWindowList[i]);
1171: }
1172: }
1173: disposeWindowList = null;
1174: }
1175: }
1176:
1177: void error(int code) {
1178: SWT.error(code);
1179: }
1180:
1181: boolean filterEvent(Event event) {
1182: if (filterTable != null)
1183: filterTable.sendEvent(event);
1184: return false;
1185: }
1186:
1187: boolean filters(int eventType) {
1188: if (filterTable == null)
1189: return false;
1190: return filterTable.hooks(eventType);
1191: }
1192:
1193: /**
1194: * Given the operating system handle for a widget, returns
1195: * the instance of the <code>Widget</code> subclass which
1196: * represents it in the currently running application, if
1197: * such exists, or null if no matching widget can be found.
1198: * <p>
1199: * <b>IMPORTANT:</b> This method should not be called from
1200: * application code. The arguments are platform-specific.
1201: * </p>
1202: *
1203: * @param handle the handle for the widget
1204: * @return the SWT widget that the handle represents
1205: *
1206: * @exception SWTException <ul>
1207: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1208: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1209: * </ul>
1210: */
1211: public Widget findWidget(int handle) {
1212: checkDevice();
1213: return getWidget(handle);
1214: }
1215:
1216: /**
1217: * Given the operating system handle for a widget,
1218: * and widget-specific id, returns the instance of
1219: * the <code>Widget</code> subclass which represents
1220: * the handle/id pair in the currently running application,
1221: * if such exists, or null if no matching widget can be found.
1222: * <p>
1223: * <b>IMPORTANT:</b> This method should not be called from
1224: * application code. The arguments are platform-specific.
1225: * </p>
1226: *
1227: * @param handle the handle for the widget
1228: * @param id the id for the subwidget (usually an item)
1229: * @return the SWT widget that the handle/id pair represents
1230: *
1231: * @exception SWTException <ul>
1232: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1233: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1234: * </ul>
1235: *
1236: * @since 3.1
1237: */
1238: public Widget findWidget(int handle, int id) {
1239: return null;
1240: }
1241:
1242: /**
1243: * Returns the display which the given thread is the
1244: * user-interface thread for, or null if the given thread
1245: * is not a user-interface thread for any display. Specifying
1246: * <code>null</code> as the thread will return <code>null</code>
1247: * for the display.
1248: *
1249: * @param thread the user-interface thread
1250: * @return the display for the given thread
1251: */
1252: public static synchronized Display findDisplay(Thread thread) {
1253: for (int i = 0; i < Displays.length; i++) {
1254: Display display = Displays[i];
1255: if (display != null && display.thread == thread) {
1256: return display;
1257: }
1258: }
1259: return null;
1260: }
1261:
1262: /**
1263: * Returns the currently active <code>Shell</code>, or null
1264: * if no shell belonging to the currently running application
1265: * is active.
1266: *
1267: * @return the active shell or null
1268: *
1269: * @exception SWTException <ul>
1270: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1271: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1272: * </ul>
1273: */
1274: public Shell getActiveShell() {
1275: checkDevice();
1276: for (int i = 0; i < widgetTable.length; i++) {
1277: Widget widget = widgetTable[i];
1278: if (widget != null && widget instanceof Shell) {
1279: Shell shell = (Shell) widget;
1280: if (OS.IsWindowActive(shell.shellHandle))
1281: return shell;
1282: }
1283: }
1284: return null;
1285: }
1286:
1287: /**
1288: * Returns a rectangle describing the receiver's size and location.
1289: *
1290: * @return the bounding rectangle
1291: *
1292: * @exception SWTException <ul>
1293: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1294: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1295: * </ul>
1296: */
1297: public Rectangle getBounds() {
1298: checkDevice();
1299: int gdevice = OS.GetDeviceList();
1300: if (gdevice == 0 || OS.GetNextDevice(gdevice) == 0) {
1301: return super .getBounds();
1302: }
1303: Monitor[] monitors = getMonitors();
1304: Rectangle rect = monitors[0].getBounds();
1305: for (int i = 1; i < monitors.length; i++) {
1306: rect = rect.union(monitors[i].getBounds());
1307: }
1308: return rect;
1309: }
1310:
1311: /**
1312: * Returns the display which the currently running thread is
1313: * the user-interface thread for, or null if the currently
1314: * running thread is not a user-interface thread for any display.
1315: *
1316: * @return the current display
1317: */
1318: public static synchronized Display getCurrent() {
1319: return findDisplay(Thread.currentThread());
1320: }
1321:
1322: int getCaretBlinkTime() {
1323: // checkDevice ();
1324: return OS.GetCaretTime() * 1000 / 60;
1325: }
1326:
1327: /**
1328: * Returns a rectangle which describes the area of the
1329: * receiver which is capable of displaying data.
1330: *
1331: * @return the client area
1332: *
1333: * @exception SWTException <ul>
1334: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1335: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1336: * </ul>
1337: *
1338: * @see #getBounds
1339: */
1340: public Rectangle getClientArea() {
1341: checkDevice();
1342: int gdevice = OS.GetDeviceList();
1343: if (gdevice == 0 || OS.GetNextDevice(gdevice) == 0) {
1344: return super .getClientArea();
1345: }
1346: Monitor[] monitors = getMonitors();
1347: Rectangle rect = monitors[0].getBounds();
1348: for (int i = 1; i < monitors.length; i++) {
1349: rect = rect.union(monitors[i].getBounds());
1350: }
1351: return rect;
1352: }
1353:
1354: /**
1355: * Returns the control which the on-screen pointer is currently
1356: * over top of, or null if it is not currently over one of the
1357: * controls built by the currently running application.
1358: *
1359: * @return the control under the cursor
1360: *
1361: * @exception SWTException <ul>
1362: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1363: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1364: * </ul>
1365: */
1366: public Control getCursorControl() {
1367: org.eclipse.swt.internal.carbon.Point where = new org.eclipse.swt.internal.carbon.Point();
1368: OS.GetGlobalMouse(where);
1369: int[] theWindow = new int[1];
1370: if (OS.FindWindow(where, theWindow) != OS.inContent)
1371: return null;
1372: if (theWindow[0] == 0)
1373: return null;
1374: Rect rect = new Rect();
1375: OS.GetWindowBounds(theWindow[0], (short) OS.kWindowContentRgn,
1376: rect);
1377: CGPoint inPoint = new CGPoint();
1378: inPoint.x = where.h - rect.left;
1379: inPoint.y = where.v - rect.top;
1380: int[] theRoot = new int[1];
1381: OS.GetRootControl(theWindow[0], theRoot);
1382: int[] theControl = new int[1];
1383: OS.HIViewGetSubviewHit(theRoot[0], inPoint, true, theControl);
1384: while (theControl[0] != 0
1385: && !OS.IsControlEnabled(theControl[0])) {
1386: OS.GetSuperControl(theControl[0], theControl);
1387: }
1388: if (theControl[0] != 0) {
1389: do {
1390: Widget widget = getWidget(theControl[0]);
1391: if (widget != null) {
1392: if (widget instanceof Control) {
1393: Control control = (Control) widget;
1394: if (control.isEnabled()) {
1395: return control.isEnabledModal() ? control
1396: : null;
1397: }
1398: }
1399: }
1400: OS.GetSuperControl(theControl[0], theControl);
1401: } while (theControl[0] != 0);
1402: }
1403: Widget widget = getWidget(theRoot[0]);
1404: if (widget != null && widget instanceof Control)
1405: return (Control) widget;
1406: return null;
1407: }
1408:
1409: /**
1410: * Returns the location of the on-screen pointer relative
1411: * to the top left corner of the screen.
1412: *
1413: * @return the cursor location
1414: *
1415: * @exception SWTException <ul>
1416: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1417: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1418: * </ul>
1419: */
1420: public Point getCursorLocation() {
1421: checkDevice();
1422: org.eclipse.swt.internal.carbon.Point pt = new org.eclipse.swt.internal.carbon.Point();
1423: OS.GetGlobalMouse(pt);
1424: return new Point(pt.h, pt.v);
1425: }
1426:
1427: /**
1428: * Returns an array containing the recommended cursor sizes.
1429: *
1430: * @return the array of cursor sizes
1431: *
1432: * @exception SWTException <ul>
1433: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1434: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1435: * </ul>
1436: *
1437: * @since 3.0
1438: */
1439: public Point[] getCursorSizes() {
1440: checkDevice();
1441: return new Point[] { new Point(16, 16) };
1442: }
1443:
1444: /**
1445: * Returns the default display. One is created (making the
1446: * thread that invokes this method its user-interface thread)
1447: * if it did not already exist.
1448: *
1449: * @return the default display
1450: */
1451: public static synchronized Display getDefault() {
1452: if (Default == null)
1453: Default = new Display();
1454: return Default;
1455: }
1456:
1457: /**
1458: * Returns the application defined property of the receiver
1459: * with the specified name, or null if it has not been set.
1460: * <p>
1461: * Applications may have associated arbitrary objects with the
1462: * receiver in this fashion. If the objects stored in the
1463: * properties need to be notified when the display is disposed
1464: * of, it is the application's responsibility to provide a
1465: * <code>disposeExec()</code> handler which does so.
1466: * </p>
1467: *
1468: * @param key the name of the property
1469: * @return the value of the property or null if it has not been set
1470: *
1471: * @exception IllegalArgumentException <ul>
1472: * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
1473: * </ul>
1474: * @exception SWTException <ul>
1475: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1476: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1477: * </ul>
1478: *
1479: * @see #setData(String, Object)
1480: * @see #disposeExec(Runnable)
1481: */
1482: public Object getData(String key) {
1483: checkDevice();
1484: if (key == null)
1485: error(SWT.ERROR_NULL_ARGUMENT);
1486: if (keys == null)
1487: return null;
1488: for (int i = 0; i < keys.length; i++) {
1489: if (keys[i].equals(key))
1490: return values[i];
1491: }
1492: return null;
1493: }
1494:
1495: /**
1496: * Returns the application defined, display specific data
1497: * associated with the receiver, or null if it has not been
1498: * set. The <em>display specific data</em> is a single,
1499: * unnamed field that is stored with every display.
1500: * <p>
1501: * Applications may put arbitrary objects in this field. If
1502: * the object stored in the display specific data needs to
1503: * be notified when the display is disposed of, it is the
1504: * application's responsibility to provide a
1505: * <code>disposeExec()</code> handler which does so.
1506: * </p>
1507: *
1508: * @return the display specific data
1509: *
1510: * @exception SWTException <ul>
1511: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1512: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1513: * </ul>
1514: *
1515: * @see #setData(Object)
1516: * @see #disposeExec(Runnable)
1517: */
1518: public Object getData() {
1519: checkDevice();
1520: return data;
1521: }
1522:
1523: /**
1524: * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
1525: * The button dismissal alignment is the ordering that should be used when positioning the
1526: * default dismissal button for a dialog. For example, in a dialog that contains an OK and
1527: * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
1528: * button ordering should be OK/CANCEL. When button dismissal alignment is <code>RIGHT</code>,
1529: * the button ordering should be CANCEL/OK.
1530: *
1531: * @return the button dismissal order
1532: *
1533: * @exception SWTException <ul>
1534: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1535: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1536: * </ul>
1537: *
1538: * @since 2.1
1539: */
1540: public int getDismissalAlignment() {
1541: checkDevice();
1542: return SWT.RIGHT;
1543: }
1544:
1545: /**
1546: * Returns the longest duration, in milliseconds, between
1547: * two mouse button clicks that will be considered a
1548: * <em>double click</em> by the underlying operating system.
1549: *
1550: * @return the double click time
1551: *
1552: * @exception SWTException <ul>
1553: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1554: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1555: * </ul>
1556: */
1557: public int getDoubleClickTime() {
1558: checkDevice();
1559: return OS.GetDblTime() * 1000 / 60;
1560: }
1561:
1562: /**
1563: * Returns the control which currently has keyboard focus,
1564: * or null if keyboard events are not currently going to
1565: * any of the controls built by the currently running
1566: * application.
1567: *
1568: * @return the control under the cursor
1569: *
1570: * @exception SWTException <ul>
1571: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1572: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1573: * </ul>
1574: */
1575: public Control getFocusControl() {
1576: checkDevice();
1577: if (focusControl != null && !focusControl.isDisposed()) {
1578: return focusControl;
1579: }
1580: int theWindow = OS.GetUserFocusWindow();
1581: if (theWindow == 0)
1582: return null;
1583: return getFocusControl(theWindow);
1584: }
1585:
1586: Control getFocusControl(int window) {
1587: int[] theControl = new int[1];
1588: OS.GetKeyboardFocus(window, theControl);
1589: if (theControl[0] == 0)
1590: return null;
1591: do {
1592: Widget widget = getWidget(theControl[0]);
1593: if (widget != null && widget instanceof Control) {
1594: Control control = (Control) widget;
1595: return control.isEnabled() ? control : null;
1596: }
1597: OS.GetSuperControl(theControl[0], theControl);
1598: } while (theControl[0] != 0);
1599: return null;
1600: }
1601:
1602: /**
1603: * Returns true when the high contrast mode is enabled.
1604: * Otherwise, false is returned.
1605: * <p>
1606: * Note: This operation is a hint and is not supported on
1607: * platforms that do not have this concept.
1608: * </p>
1609: *
1610: * @return the high contrast mode
1611: *
1612: * @exception SWTException <ul>
1613: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1614: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1615: * </ul>
1616: *
1617: * @since 3.0
1618: */
1619: public boolean getHighContrast() {
1620: checkDevice();
1621: return false;
1622: }
1623:
1624: /**
1625: * Returns the maximum allowed depth of icons on this display, in bits per pixel.
1626: * On some platforms, this may be different than the actual depth of the display.
1627: *
1628: * @return the maximum icon depth
1629: *
1630: * @exception SWTException <ul>
1631: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1632: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1633: * </ul>
1634: *
1635: * @see Device#getDepth
1636: */
1637: public int getIconDepth() {
1638: return getDepth();
1639: }
1640:
1641: /**
1642: * Returns an array containing the recommended icon sizes.
1643: *
1644: * @return the array of icon sizes
1645: *
1646: * @exception SWTException <ul>
1647: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1648: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1649: * </ul>
1650: *
1651: * @see Decorations#setImages(Image[])
1652: *
1653: * @since 3.0
1654: */
1655: public Point[] getIconSizes() {
1656: checkDevice();
1657: return new Point[] { new Point(16, 16), new Point(32, 32),
1658: new Point(64, 64), new Point(128, 128) };
1659: }
1660:
1661: int getLastEventTime() {
1662: /*
1663: * This code is intentionally commented. Event time is
1664: * in seconds and we need an accurate time in milliseconds.
1665: */
1666: // return (int) (OS.GetLastUserEventTime () * 1000.0);
1667: return (int) System.currentTimeMillis();
1668: }
1669:
1670: Menu[] getMenus(Decorations shell) {
1671: if (menus == null)
1672: return new Menu[0];
1673: int count = 0;
1674: for (int i = 0; i < menus.length; i++) {
1675: Menu menu = menus[i];
1676: if (menu != null && menu.parent == shell)
1677: count++;
1678: }
1679: int index = 0;
1680: Menu[] result = new Menu[count];
1681: for (int i = 0; i < menus.length; i++) {
1682: Menu menu = menus[i];
1683: if (menu != null && menu.parent == shell) {
1684: result[index++] = menu;
1685: }
1686: }
1687: return result;
1688: }
1689:
1690: Menu getMenu(int id) {
1691: if (menus == null)
1692: return null;
1693: int index = id - ID_START;
1694: if (0 <= index && index < menus.length)
1695: return menus[index];
1696: return null;
1697: }
1698:
1699: Menu getMenuBar() {
1700: return menuBar;
1701: }
1702:
1703: int getMessageCount() {
1704: return synchronizer.getMessageCount();
1705: }
1706:
1707: /**
1708: * Returns an array of monitors attached to the device.
1709: *
1710: * @return the array of monitors
1711: *
1712: * @since 3.0
1713: */
1714: public Monitor[] getMonitors() {
1715: checkDevice();
1716: int count = 0;
1717: Monitor[] monitors = new Monitor[1];
1718: Rect rect = new Rect();
1719: GDevice device = new GDevice();
1720: int gdevice = OS.GetDeviceList();
1721: while (gdevice != 0) {
1722: if (count >= monitors.length) {
1723: Monitor[] newMonitors = new Monitor[monitors.length + 4];
1724: System.arraycopy(monitors, 0, newMonitors, 0,
1725: monitors.length);
1726: monitors = newMonitors;
1727: }
1728: Monitor monitor = new Monitor();
1729: monitor.handle = gdevice;
1730: int[] ptr = new int[1];
1731: OS.memcpy(ptr, gdevice, 4);
1732: OS.memcpy(device, ptr[0], GDevice.sizeof);
1733: monitor.x = device.left;
1734: monitor.y = device.top;
1735: monitor.width = device.right - device.left;
1736: monitor.height = device.bottom - device.top;
1737: OS.GetAvailableWindowPositioningBounds(gdevice, rect);
1738: monitor.clientX = rect.left;
1739: monitor.clientY = rect.top;
1740: monitor.clientWidth = rect.right - rect.left;
1741: monitor.clientHeight = rect.bottom - rect.top;
1742: monitors[count++] = monitor;
1743: gdevice = OS.GetNextDevice(gdevice);
1744: }
1745: if (count < monitors.length) {
1746: Monitor[] newMonitors = new Monitor[count];
1747: System.arraycopy(monitors, 0, newMonitors, 0, count);
1748: monitors = newMonitors;
1749: }
1750: return monitors;
1751: }
1752:
1753: /**
1754: * Returns the primary monitor for that device.
1755: *
1756: * @return the primary monitor
1757: *
1758: * @since 3.0
1759: */
1760: public Monitor getPrimaryMonitor() {
1761: checkDevice();
1762: int gdevice = OS.GetMainDevice();
1763: Monitor monitor = new Monitor();
1764: monitor.handle = gdevice;
1765: int[] ptr = new int[1];
1766: OS.memcpy(ptr, gdevice, 4);
1767: GDevice device = new GDevice();
1768: OS.memcpy(device, ptr[0], GDevice.sizeof);
1769: monitor.x = device.left;
1770: monitor.y = device.top;
1771: monitor.width = device.right - device.left;
1772: monitor.height = device.bottom - device.top;
1773: Rect rect = new Rect();
1774: OS.GetAvailableWindowPositioningBounds(gdevice, rect);
1775: monitor.clientX = rect.left;
1776: monitor.clientY = rect.top;
1777: monitor.clientWidth = rect.right - rect.left;
1778: monitor.clientHeight = rect.bottom - rect.top;
1779: return monitor;
1780: }
1781:
1782: /**
1783: * Returns a (possibly empty) array containing all shells which have
1784: * not been disposed and have the receiver as their display.
1785: *
1786: * @return the receiver's shells
1787: *
1788: * @exception SWTException <ul>
1789: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1790: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1791: * </ul>
1792: */
1793: public Shell[] getShells() {
1794: checkDevice();
1795: int index = 0;
1796: Shell[] result = new Shell[16];
1797: for (int i = 0; i < widgetTable.length; i++) {
1798: Widget widget = widgetTable[i];
1799: if (widget != null && widget instanceof Shell) {
1800: int j = 0;
1801: while (j < index) {
1802: if (result[j] == widget)
1803: break;
1804: j++;
1805: }
1806: if (j == index) {
1807: if (index == result.length) {
1808: Shell[] newResult = new Shell[index + 16];
1809: System
1810: .arraycopy(result, 0, newResult, 0,
1811: index);
1812: result = newResult;
1813: }
1814: result[index++] = (Shell) widget;
1815: }
1816: }
1817: }
1818: if (index == result.length)
1819: return result;
1820: Shell[] newResult = new Shell[index];
1821: System.arraycopy(result, 0, newResult, 0, index);
1822: return newResult;
1823: }
1824:
1825: /**
1826: * Returns the thread that has invoked <code>syncExec</code>
1827: * or null if no such runnable is currently being invoked by
1828: * the user-interface thread.
1829: * <p>
1830: * Note: If a runnable invoked by asyncExec is currently
1831: * running, this method will return null.
1832: * </p>
1833: *
1834: * @return the receiver's sync-interface thread
1835: *
1836: * @exception SWTException <ul>
1837: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1838: * </ul>
1839: */
1840: public Thread getSyncThread() {
1841: if (isDisposed())
1842: error(SWT.ERROR_DEVICE_DISPOSED);
1843: return synchronizer.syncThread;
1844: }
1845:
1846: /**
1847: * Returns the matching standard color for the given
1848: * constant, which should be one of the color constants
1849: * specified in class <code>SWT</code>. Any value other
1850: * than one of the SWT color constants which is passed
1851: * in will result in the color black. This color should
1852: * not be free'd because it was allocated by the system,
1853: * not the application.
1854: *
1855: * @param id the color constant
1856: * @return the matching color
1857: *
1858: * @exception SWTException <ul>
1859: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1860: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1861: * </ul>
1862: *
1863: * @see SWT
1864: */
1865: public Color getSystemColor(int id) {
1866: checkDevice();
1867: RGBColor rgb = new RGBColor();
1868: switch (id) {
1869: case SWT.COLOR_INFO_FOREGROUND:
1870: return super .getSystemColor(SWT.COLOR_BLACK);
1871: case SWT.COLOR_INFO_BACKGROUND:
1872: return Color.carbon_new(this , new float[] { 0xFF / 255f,
1873: 0xFF / 255f, 0xE1 / 255f, 1 });
1874: case SWT.COLOR_TITLE_FOREGROUND:
1875: OS
1876: .GetThemeTextColor(
1877: (short) OS.kThemeTextColorDocumentWindowTitleActive,
1878: (short) getDepth(), true, rgb);
1879: break;
1880: case SWT.COLOR_TITLE_BACKGROUND:
1881: OS.GetThemeBrushAsColor(
1882: (short) -5/*undocumented darker highlight color*/,
1883: (short) getDepth(), true, rgb);
1884: break;
1885: case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:
1886: OS.GetThemeBrushAsColor(
1887: (short) OS.kThemeBrushPrimaryHighlightColor,
1888: (short) getDepth(), true, rgb);
1889: break;
1890: case SWT.COLOR_TITLE_INACTIVE_FOREGROUND:
1891: OS
1892: .GetThemeTextColor(
1893: (short) OS.kThemeTextColorDocumentWindowTitleInactive,
1894: (short) getDepth(), true, rgb);
1895: break;
1896: case SWT.COLOR_TITLE_INACTIVE_BACKGROUND:
1897: OS.GetThemeBrushAsColor(
1898: (short) OS.kThemeBrushSecondaryHighlightColor,
1899: (short) getDepth(), true, rgb);
1900: break;
1901: case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:
1902: OS.GetThemeBrushAsColor(
1903: (short) OS.kThemeBrushSecondaryHighlightColor,
1904: (short) getDepth(), true, rgb);
1905: break;
1906: case SWT.COLOR_WIDGET_DARK_SHADOW:
1907: return Color.carbon_new(this , new float[] { 0x33 / 255f,
1908: 0x33 / 255f, 0x33 / 255f, 1 });
1909: case SWT.COLOR_WIDGET_NORMAL_SHADOW:
1910: return Color.carbon_new(this , new float[] { 0x66 / 255f,
1911: 0x66 / 255f, 0x66 / 255f, 1 });
1912: case SWT.COLOR_WIDGET_LIGHT_SHADOW:
1913: return Color.carbon_new(this , new float[] { 0x99 / 255f,
1914: 0x99 / 255f, 0x99 / 255f, 1 });
1915: case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW:
1916: return Color.carbon_new(this , new float[] { 0xCC / 255f,
1917: 0xCC / 255f, 0xCC / 255f, 1 });
1918: case SWT.COLOR_WIDGET_BACKGROUND:
1919: OS.GetThemeBrushAsColor(
1920: (short) OS.kThemeBrushButtonFaceActive,
1921: (short) getDepth(), true, rgb);
1922: break;
1923: case SWT.COLOR_WIDGET_FOREGROUND:
1924: OS.GetThemeTextColor(
1925: (short) OS.kThemeTextColorPushButtonActive,
1926: (short) getDepth(), true, rgb);
1927: break;
1928: case SWT.COLOR_WIDGET_BORDER:
1929: return super .getSystemColor(SWT.COLOR_BLACK);
1930: case SWT.COLOR_LIST_FOREGROUND:
1931: OS.GetThemeTextColor((short) OS.kThemeTextColorListView,
1932: (short) getDepth(), true, rgb);
1933: break;
1934: case SWT.COLOR_LIST_BACKGROUND:
1935: OS.GetThemeBrushAsColor(
1936: (short) OS.kThemeBrushListViewBackground,
1937: (short) getDepth(), true, rgb);
1938: break;
1939: case SWT.COLOR_LIST_SELECTION_TEXT:
1940: OS.GetThemeTextColor((short) OS.kThemeTextColorListView,
1941: (short) getDepth(), true, rgb);
1942: break;
1943: case SWT.COLOR_LIST_SELECTION:
1944: OS.GetThemeBrushAsColor(
1945: (short) OS.kThemeBrushPrimaryHighlightColor,
1946: (short) getDepth(), true, rgb);
1947: break;
1948: default:
1949: return super .getSystemColor(id);
1950: }
1951: float red = ((rgb.red >> 8) & 0xFF) / 255f;
1952: float green = ((rgb.green >> 8) & 0xFF) / 255f;
1953: float blue = ((rgb.blue >> 8) & 0xFF) / 255f;
1954: return Color.carbon_new(this ,
1955: new float[] { red, green, blue, 1 });
1956: }
1957:
1958: /**
1959: * Returns the matching standard platform cursor for the given
1960: * constant, which should be one of the cursor constants
1961: * specified in class <code>SWT</code>. This cursor should
1962: * not be free'd because it was allocated by the system,
1963: * not the application. A value of <code>null</code> will
1964: * be returned if the supplied constant is not an SWT cursor
1965: * constant.
1966: *
1967: * @param id the SWT cursor constant
1968: * @return the corresponding cursor or <code>null</code>
1969: *
1970: * @exception SWTException <ul>
1971: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1972: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1973: * </ul>
1974: *
1975: * @see SWT#CURSOR_ARROW
1976: * @see SWT#CURSOR_WAIT
1977: * @see SWT#CURSOR_CROSS
1978: * @see SWT#CURSOR_APPSTARTING
1979: * @see SWT#CURSOR_HELP
1980: * @see SWT#CURSOR_SIZEALL
1981: * @see SWT#CURSOR_SIZENESW
1982: * @see SWT#CURSOR_SIZENS
1983: * @see SWT#CURSOR_SIZENWSE
1984: * @see SWT#CURSOR_SIZEWE
1985: * @see SWT#CURSOR_SIZEN
1986: * @see SWT#CURSOR_SIZES
1987: * @see SWT#CURSOR_SIZEE
1988: * @see SWT#CURSOR_SIZEW
1989: * @see SWT#CURSOR_SIZENE
1990: * @see SWT#CURSOR_SIZESE
1991: * @see SWT#CURSOR_SIZESW
1992: * @see SWT#CURSOR_SIZENW
1993: * @see SWT#CURSOR_UPARROW
1994: * @see SWT#CURSOR_IBEAM
1995: * @see SWT#CURSOR_NO
1996: * @see SWT#CURSOR_HAND
1997: *
1998: * @since 3.0
1999: */
2000: public Cursor getSystemCursor(int id) {
2001: checkDevice();
2002: if (!(0 <= id && id < cursors.length))
2003: return null;
2004: if (cursors[id] == null) {
2005: cursors[id] = new Cursor(this , id);
2006: }
2007: return cursors[id];
2008: }
2009:
2010: /**
2011: * Returns the matching standard platform image for the given
2012: * constant, which should be one of the icon constants
2013: * specified in class <code>SWT</code>. This image should
2014: * not be free'd because it was allocated by the system,
2015: * not the application. A value of <code>null</code> will
2016: * be returned either if the supplied constant is not an
2017: * SWT icon constant or if the platform does not define an
2018: * image that corresponds to the constant.
2019: *
2020: * @param id the SWT icon constant
2021: * @return the corresponding image or <code>null</code>
2022: *
2023: * @exception SWTException <ul>
2024: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2025: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2026: * </ul>
2027: *
2028: * @see SWT#ICON_ERROR
2029: * @see SWT#ICON_INFORMATION
2030: * @see SWT#ICON_QUESTION
2031: * @see SWT#ICON_WARNING
2032: * @see SWT#ICON_WORKING
2033: *
2034: * @since 3.0
2035: */
2036: public Image getSystemImage(int id) {
2037: checkDevice();
2038: switch (id) {
2039: case SWT.ICON_ERROR: {
2040: if (errorImage != null)
2041: return errorImage;
2042: int[] image = createImage(OS.kAlertStopIcon);
2043: if (image == null)
2044: break;
2045: return errorImage = Image.carbon_new(this , SWT.ICON,
2046: image[0], image[1]);
2047: }
2048: case SWT.ICON_INFORMATION:
2049: case SWT.ICON_QUESTION:
2050: case SWT.ICON_WORKING: {
2051: if (infoImage != null)
2052: return infoImage;
2053: int[] image = createImage(OS.kAlertNoteIcon);
2054: if (image == null)
2055: break;
2056: return infoImage = Image.carbon_new(this , SWT.ICON,
2057: image[0], image[1]);
2058: }
2059: case SWT.ICON_WARNING: {
2060: if (warningImage != null)
2061: return warningImage;
2062: int[] image = createImage(OS.kAlertCautionIcon);
2063: if (image == null)
2064: break;
2065: return warningImage = Image.carbon_new(this , SWT.ICON,
2066: image[0], image[1]);
2067: }
2068: }
2069: return null;
2070: }
2071:
2072: /**
2073: * Returns the single instance of the system tray or null
2074: * when there is no system tray available for the platform.
2075: *
2076: * @return the system tray or <code>null</code>
2077: *
2078: * @exception SWTException <ul>
2079: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2080: * </ul>
2081: *
2082: * @since 3.0
2083: */
2084: public Tray getSystemTray() {
2085: checkDevice();
2086: return null;
2087: }
2088:
2089: /**
2090: * Returns the user-interface thread for the receiver.
2091: *
2092: * @return the receiver's user-interface thread
2093: *
2094: * @exception SWTException <ul>
2095: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2096: * </ul>
2097: */
2098: public Thread getThread() {
2099: if (isDisposed())
2100: error(SWT.ERROR_DEVICE_DISPOSED);
2101: return thread;
2102: }
2103:
2104: Widget getWidget(int handle) {
2105: if (handle == 0)
2106: return null;
2107: property[0] = 0;
2108: OS.GetControlProperty(handle, SWT0, SWT0, 4, null, property);
2109: int index = property[0] - 1;
2110: if (0 <= index && index < widgetTable.length)
2111: return widgetTable[index];
2112: return null;
2113: }
2114:
2115: int helpProc(int inControl, int inGlobalMouse, int inRequest,
2116: int outContentProvided, int ioHelpContent) {
2117: Widget widget = getWidget(inControl);
2118: if (widget != null)
2119: return widget.helpProc(inControl, inGlobalMouse, inRequest,
2120: outContentProvided, ioHelpContent);
2121: return OS.eventNotHandledErr;
2122: }
2123:
2124: int hitTestProc(int browser, int item, int property, int theRect,
2125: int mouseRect) {
2126: Widget widget = getWidget(browser);
2127: if (widget != null)
2128: return widget.hitTestProc(browser, item, property, theRect,
2129: mouseRect);
2130: return OS.noErr;
2131: }
2132:
2133: /**
2134: * Initializes any internal resources needed by the
2135: * device.
2136: * <p>
2137: * This method is called after <code>create</code>.
2138: * </p>
2139: *
2140: * @see #create
2141: */
2142: protected void init() {
2143: super .init();
2144: initializeCallbacks();
2145: initializeInsets();
2146: initializeWidgetTable();
2147: initializeFonts();
2148: }
2149:
2150: void initializeCallbacks() {
2151: /* Create Callbacks */
2152: actionCallback = new Callback(this , "actionProc", 2);
2153: actionProc = actionCallback.getAddress();
2154: if (actionProc == 0)
2155: error(SWT.ERROR_NO_MORE_CALLBACKS);
2156: appleEventCallback = new Callback(this , "appleEventProc", 3);
2157: appleEventProc = appleEventCallback.getAddress();
2158: if (appleEventProc == 0)
2159: error(SWT.ERROR_NO_MORE_CALLBACKS);
2160: caretCallback = new Callback(this , "caretProc", 2);
2161: caretProc = caretCallback.getAddress();
2162: if (caretProc == 0)
2163: error(SWT.ERROR_NO_MORE_CALLBACKS);
2164: commandCallback = new Callback(this , "commandProc", 3);
2165: commandProc = commandCallback.getAddress();
2166: if (commandProc == 0)
2167: error(SWT.ERROR_NO_MORE_CALLBACKS);
2168: controlCallback = new Callback(this , "controlProc", 3);
2169: controlProc = controlCallback.getAddress();
2170: if (controlProc == 0)
2171: error(SWT.ERROR_NO_MORE_CALLBACKS);
2172: accessibilityCallback = new Callback(this , "accessibilityProc",
2173: 3);
2174: accessibilityProc = accessibilityCallback.getAddress();
2175: if (accessibilityProc == 0)
2176: error(SWT.ERROR_NO_MORE_CALLBACKS);
2177: drawItemCallback = new Callback(this , "drawItemProc", 7);
2178: drawItemProc = drawItemCallback.getAddress();
2179: if (drawItemProc == 0)
2180: error(SWT.ERROR_NO_MORE_CALLBACKS);
2181: itemCompareCallback = new Callback(this , "itemCompareProc", 4);
2182: itemCompareProc = itemCompareCallback.getAddress();
2183: if (itemCompareProc == 0)
2184: error(SWT.ERROR_NO_MORE_CALLBACKS);
2185: itemDataCallback = new Callback(this , "itemDataProc", 5);
2186: itemDataProc = itemDataCallback.getAddress();
2187: if (itemDataProc == 0)
2188: error(SWT.ERROR_NO_MORE_CALLBACKS);
2189: itemNotificationCallback = new Callback(this ,
2190: "itemNotificationProc", 3);
2191: itemNotificationProc = itemNotificationCallback.getAddress();
2192: if (itemNotificationProc == 0)
2193: error(SWT.ERROR_NO_MORE_CALLBACKS);
2194: helpCallback = new Callback(this , "helpProc", 5);
2195: helpProc = helpCallback.getAddress();
2196: if (helpProc == 0)
2197: error(SWT.ERROR_NO_MORE_CALLBACKS);
2198: hitTestCallback = new Callback(this , "hitTestProc", 5);
2199: hitTestProc = hitTestCallback.getAddress();
2200: if (hitTestProc == 0)
2201: error(SWT.ERROR_NO_MORE_CALLBACKS);
2202: keyboardCallback = new Callback(this , "keyboardProc", 3);
2203: keyboardProc = keyboardCallback.getAddress();
2204: if (keyboardProc == 0)
2205: error(SWT.ERROR_NO_MORE_CALLBACKS);
2206: menuCallback = new Callback(this , "menuProc", 3);
2207: menuProc = menuCallback.getAddress();
2208: if (menuProc == 0)
2209: error(SWT.ERROR_NO_MORE_CALLBACKS);
2210: mouseHoverCallback = new Callback(this , "mouseHoverProc", 2);
2211: mouseHoverProc = mouseHoverCallback.getAddress();
2212: if (mouseHoverProc == 0)
2213: error(SWT.ERROR_NO_MORE_CALLBACKS);
2214: mouseCallback = new Callback(this , "mouseProc", 3);
2215: mouseProc = mouseCallback.getAddress();
2216: if (mouseProc == 0)
2217: error(SWT.ERROR_NO_MORE_CALLBACKS);
2218: timerCallback = new Callback(this , "timerProc", 2);
2219: timerProc = timerCallback.getAddress();
2220: if (timerProc == 0)
2221: error(SWT.ERROR_NO_MORE_CALLBACKS);
2222: trackingCallback = new Callback(this , "trackingProc", 6);
2223: trackingProc = trackingCallback.getAddress();
2224: if (trackingProc == 0)
2225: error(SWT.ERROR_NO_MORE_CALLBACKS);
2226: windowCallback = new Callback(this , "windowProc", 3);
2227: windowProc = windowCallback.getAddress();
2228: if (windowProc == 0)
2229: error(SWT.ERROR_NO_MORE_CALLBACKS);
2230: colorCallback = new Callback(this , "colorProc", 4);
2231: colorProc = colorCallback.getAddress();
2232: if (colorProc == 0)
2233: error(SWT.ERROR_NO_MORE_CALLBACKS);
2234: textInputCallback = new Callback(this , "textInputProc", 3);
2235: textInputProc = textInputCallback.getAddress();
2236: if (textInputProc == 0)
2237: error(SWT.ERROR_NO_MORE_CALLBACKS);
2238: appearanceCallback = new Callback(this , "appearanceProc", 3);
2239: appearanceProc = appearanceCallback.getAddress();
2240: if (appearanceProc == 0)
2241: error(SWT.ERROR_NO_MORE_CALLBACKS);
2242:
2243: /* Install Event Handlers */
2244: int[] mask1 = new int[] { OS.kEventClassCommand,
2245: OS.kEventProcessCommand, };
2246: int appTarget = OS.GetApplicationEventTarget();
2247: OS.InstallEventHandler(appTarget, commandProc,
2248: mask1.length / 2, mask1, 0, null);
2249: int[] mask2 = new int[] {
2250: OS.kEventClassMouse,
2251: OS.kEventMouseDown,
2252: OS.kEventClassMouse,
2253: OS.kEventMouseDragged,
2254: // OS.kEventClassMouse, OS.kEventMouseEntered,
2255: // OS.kEventClassMouse, OS.kEventMouseExited,
2256: OS.kEventClassMouse, OS.kEventMouseMoved,
2257: OS.kEventClassMouse, OS.kEventMouseUp,
2258: OS.kEventClassMouse, OS.kEventMouseWheelMoved, };
2259: OS.InstallEventHandler(appTarget, mouseProc, mask2.length / 2,
2260: mask2, 0, null);
2261: int[] mask3 = new int[] { OS.kEventClassApplication,
2262: OS.kEventAppAvailableWindowBoundsChanged,
2263: OS.kEventClassAppleEvent, OS.kEventAppleEvent, };
2264: OS.InstallEventHandler(appTarget, appleEventProc,
2265: mask3.length / 2, mask3, 0, null);
2266: int[] mask4 = new int[] { OS.kEventClassKeyboard,
2267: OS.kEventRawKeyDown, OS.kEventClassKeyboard,
2268: OS.kEventRawKeyModifiersChanged,
2269: OS.kEventClassKeyboard, OS.kEventRawKeyRepeat,
2270: OS.kEventClassKeyboard, OS.kEventRawKeyUp, };
2271: int focusTarget = OS.GetUserFocusEventTarget();
2272: OS.InstallEventHandler(focusTarget, keyboardProc,
2273: mask4.length / 2, mask4, 0, null);
2274: int[] mask5 = new int[] { OS.kEventClassTextInput,
2275: OS.kEventTextInputUnicodeForKeyEvent, };
2276: OS.InstallEventHandler(focusTarget, textInputProc,
2277: mask5.length / 2, mask5, 0, null);
2278: OS.AEInstallEventHandler(OS.kAppearanceEventClass,
2279: OS.kAEAppearanceChanged, appearanceProc, 0, false);
2280: OS.AEInstallEventHandler(OS.kAppearanceEventClass,
2281: OS.kAESmallSystemFontChanged, appearanceProc, 0, false);
2282: OS.AEInstallEventHandler(OS.kAppearanceEventClass,
2283: OS.kAESystemFontChanged, appearanceProc, 0, false);
2284: OS.AEInstallEventHandler(OS.kAppearanceEventClass,
2285: OS.kAEViewsFontChanged, appearanceProc, 0, false);
2286: }
2287:
2288: void initializeFonts() {
2289: //TEMPORARY CODE
2290: smallFonts = System
2291: .getProperty("org.eclipse.swt.internal.carbon.smallFonts") != null;
2292: noFocusRing = System
2293: .getProperty("org.eclipse.swt.internal.carbon.noFocusRing") != null;
2294: }
2295:
2296: void initializeInsets() {
2297: int[] outControl = new int[1];
2298: Rect rect = new Rect();
2299: rect.right = rect.bottom = (short) 200;
2300:
2301: OS.CreatePushButtonControl(0, rect, 0, outControl);
2302: buttonInset = computeInset(outControl[0]);
2303: OS.DisposeControl(outControl[0]);
2304:
2305: OS.CreateTabsControl(0, rect, (short) OS.kControlTabSizeLarge,
2306: (short) OS.kControlTabDirectionNorth, (short) 0, 0,
2307: outControl);
2308: tabFolderNorthInset = computeInset(outControl[0]);
2309: OS.DisposeControl(outControl[0]);
2310:
2311: OS.CreateTabsControl(0, rect, (short) OS.kControlTabSizeLarge,
2312: (short) OS.kControlTabDirectionSouth, (short) 0, 0,
2313: outControl);
2314: tabFolderSouthInset = computeInset(outControl[0]);
2315: OS.DisposeControl(outControl[0]);
2316:
2317: /* For some reason, this code calculates insets too big. */
2318: // OS.CreateEditUnicodeTextControl (0, rect, 0, false, null, outControl);
2319: // editTextInset = computeInset (outControl [0]);
2320: // OS.DisposeControl (outControl [0]);
2321: editTextInset = new Rect();
2322: int[] outMetric = new int[1];
2323: OS.GetThemeMetric(OS.kThemeMetricFocusRectOutset, outMetric);
2324: int inset = outMetric[0];
2325: OS
2326: .GetThemeMetric(OS.kThemeMetricEditTextFrameOutset,
2327: outMetric);
2328: inset += outMetric[0];
2329: editTextInset.left = editTextInset.top = editTextInset.right = editTextInset.bottom = (short) inset;
2330:
2331: CGRect cgRect = new CGRect();
2332: cgRect.width = cgRect.height = 200;
2333: int inAttributes = OS.kHIComboBoxAutoCompletionAttribute
2334: | OS.kHIComboBoxAutoSizeListAttribute;
2335: OS.HIComboBoxCreate(cgRect, 0, null, 0, inAttributes,
2336: outControl);
2337: comboInset = computeInset(outControl[0]);
2338: //FIXME -
2339: comboInset.bottom = comboInset.top;
2340: OS.DisposeControl(outControl[0]);
2341: }
2342:
2343: void initializeWidgetTable() {
2344: property = new int[1];
2345: indexTable = new int[GROW_SIZE];
2346: widgetTable = new Widget[GROW_SIZE];
2347: for (int i = 0; i < GROW_SIZE - 1; i++)
2348: indexTable[i] = i + 1;
2349: indexTable[GROW_SIZE - 1] = -1;
2350: }
2351:
2352: /**
2353: * Invokes platform specific functionality to allocate a new GC handle.
2354: * <p>
2355: * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2356: * API for <code>Display</code>. It is marked public only so that it
2357: * can be shared within the packages provided by SWT. It is not
2358: * available on all platforms, and should never be called from
2359: * application code.
2360: * </p>
2361: *
2362: * @param data the platform specific GC data
2363: * @return the platform specific GC handle
2364: *
2365: * @exception SWTException <ul>
2366: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2367: * </ul>
2368: * @exception SWTError <ul>
2369: * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
2370: * </ul>
2371: */
2372: public int internal_new_GC(GCData data) {
2373: if (isDisposed())
2374: SWT.error(SWT.ERROR_DEVICE_DISPOSED);
2375: //TODO - multiple monitors
2376: int window = gcWindow;
2377: if (window == 0) {
2378: window = gcWindow = createOverlayWindow();
2379: } else {
2380: int gdevice = OS.GetMainDevice();
2381: int[] ptr = new int[1];
2382: OS.memcpy(ptr, gdevice, 4);
2383: GDevice device = new GDevice();
2384: OS.memcpy(device, ptr[0], GDevice.sizeof);
2385: Rect rect = new Rect();
2386: OS.SetRect(rect, device.left, device.top, device.right,
2387: device.bottom);
2388: OS.SetWindowBounds(window, (short) OS.kWindowStructureRgn,
2389: rect);
2390: }
2391: int port = OS.GetWindowPort(window);
2392: int[] buffer = new int[1];
2393: OS.CreateCGContextForPort(port, buffer);
2394: int context = buffer[0];
2395: if (context == 0)
2396: SWT.error(SWT.ERROR_NO_HANDLES);
2397: Rect portRect = new Rect();
2398: OS.GetPortBounds(port, portRect);
2399: OS.CGContextScaleCTM(context, 1, -1);
2400: OS.CGContextTranslateCTM(context, 0, portRect.top
2401: - portRect.bottom);
2402: if (data != null) {
2403: int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
2404: if ((data.style & mask) == 0) {
2405: data.style |= SWT.LEFT_TO_RIGHT;
2406: }
2407: data.device = this ;
2408: data.window = window;
2409: data.background = getSystemColor(SWT.COLOR_WHITE).handle;
2410: data.foreground = getSystemColor(SWT.COLOR_BLACK).handle;
2411: data.font = getSystemFont();
2412: data.updateClip = true;
2413: } else {
2414: OS.ShowWindow(window);
2415: }
2416: return context;
2417: }
2418:
2419: /**
2420: * Invokes platform specific functionality to dispose a GC handle.
2421: * <p>
2422: * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2423: * API for <code>Display</code>. It is marked public only so that it
2424: * can be shared within the packages provided by SWT. It is not
2425: * available on all platforms, and should never be called from
2426: * application code.
2427: * </p>
2428: *
2429: * @param hDC the platform specific GC handle
2430: * @param data the platform specific GC data
2431: */
2432: public void internal_dispose_GC(int context, GCData data) {
2433: if (isDisposed())
2434: SWT.error(SWT.ERROR_DEVICE_DISPOSED);
2435: if (data != null) {
2436: int window = data.window;
2437: if (gcWindow == window) {
2438: OS.HideWindow(window);
2439: } else {
2440: OS.DisposeWindow(window);
2441: }
2442: data.window = 0;
2443: }
2444:
2445: /*
2446: * This code is intentionaly commented. Use CGContextSynchronize
2447: * instead of CGContextFlush to improve performance.
2448: */
2449: // OS.CGContextFlush (context);
2450: OS.CGContextSynchronize(context);
2451: OS.CGContextRelease(context);
2452: }
2453:
2454: static boolean isValidClass(Class clazz) {
2455: String name = clazz.getName();
2456: int index = name.lastIndexOf('.');
2457: return name.substring(0, index + 1).equals(PACKAGE_PREFIX);
2458: }
2459:
2460: boolean isValidThread() {
2461: return thread == Thread.currentThread();
2462: }
2463:
2464: int itemCompareProc(int browser, int itemOne, int itemTwo,
2465: int sortProperty) {
2466: Widget widget = getWidget(browser);
2467: if (widget != null)
2468: return widget.itemCompareProc(browser, itemOne, itemTwo,
2469: sortProperty);
2470: return OS.noErr;
2471: }
2472:
2473: int itemDataProc(int browser, int item, int property, int itemData,
2474: int setValue) {
2475: Widget widget = getWidget(browser);
2476: if (widget != null)
2477: return widget.itemDataProc(browser, item, property,
2478: itemData, setValue);
2479: return OS.noErr;
2480: }
2481:
2482: int itemNotificationProc(int browser, int item, int message) {
2483: Widget widget = getWidget(browser);
2484: if (widget != null)
2485: return widget.itemNotificationProc(browser, item, message);
2486: return OS.noErr;
2487: }
2488:
2489: int keyboardProc(int nextHandler, int theEvent, int userData) {
2490: int theWindow = OS.GetUserFocusWindow();
2491: if (theWindow != 0) {
2492: int[] theControl = new int[1];
2493: OS.GetKeyboardFocus(theWindow, theControl);
2494: Widget widget = getWidget(theControl[0]);
2495: if (widget != null)
2496: return widget.keyboardProc(nextHandler, theEvent,
2497: userData);
2498: }
2499: return OS.eventNotHandledErr;
2500: }
2501:
2502: /**
2503: * Generate a low level system event.
2504: *
2505: * <code>post</code> is used to generate low level keyboard
2506: * and mouse events. The intent is to enable automated UI
2507: * testing by simulating the input from the user. Most
2508: * SWT applications should never need to call this method.
2509: * <p>
2510: * Note that this operation can fail when the operating system
2511: * fails to generate the event for any reason. For example,
2512: * this can happen when there is no such key or mouse button
2513: * or when the system event queue is full.
2514: * </p>
2515: * <p>
2516: * <b>Event Types:</b>
2517: * <p>KeyDown, KeyUp
2518: * <p>The following fields in the <code>Event</code> apply:
2519: * <ul>
2520: * <li>(in) type KeyDown or KeyUp</li>
2521: * <p> Either one of:
2522: * <li>(in) character a character that corresponds to a keyboard key</li>
2523: * <li>(in) keyCode the key code of the key that was typed,
2524: * as defined by the key code constants in class <code>SWT</code></li>
2525: * </ul>
2526: * <p>MouseDown, MouseUp</p>
2527: * <p>The following fields in the <code>Event</code> apply:
2528: * <ul>
2529: * <li>(in) type MouseDown or MouseUp
2530: * <li>(in) button the button that is pressed or released
2531: * </ul>
2532: * <p>MouseMove</p>
2533: * <p>The following fields in the <code>Event</code> apply:
2534: * <ul>
2535: * <li>(in) type MouseMove
2536: * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
2537: * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
2538: * </ul>
2539: * </dl>
2540: *
2541: * @param event the event to be generated
2542: *
2543: * @return true if the event was generated or false otherwise
2544: *
2545: * @exception IllegalArgumentException <ul>
2546: * <li>ERROR_NULL_ARGUMENT - if the event is null</li>
2547: * </ul>
2548: * @exception SWTException <ul>
2549: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2550: * </ul>
2551: *
2552: * @since 3.0
2553: *
2554: */
2555: public boolean post(Event event) {
2556: if (isDisposed())
2557: error(SWT.ERROR_DEVICE_DISPOSED);
2558: if (event == null)
2559: error(SWT.ERROR_NULL_ARGUMENT);
2560: int type = event.type;
2561: switch (type) {
2562: case SWT.KeyDown:
2563: case SWT.KeyUp: {
2564: int vKey = Display.untranslateKey(event.keyCode);
2565: if (vKey != 0) {
2566: return OS.CGPostKeyboardEvent(0, vKey,
2567: type == SWT.KeyDown) == 0;
2568: } else {
2569: vKey = -1;
2570: int kchrPtr = OS
2571: .GetScriptManagerVariable((short) OS.smKCHRCache);
2572: int key = -1;
2573: int[] state = new int[1];
2574: int[] encoding = new int[1];
2575: short keyScript = (short) OS
2576: .GetScriptManagerVariable((short) OS.smKeyScript);
2577: short regionCode = (short) OS
2578: .GetScriptManagerVariable((short) OS.smRegionCode);
2579: if (OS.UpgradeScriptInfoToTextEncoding(keyScript,
2580: (short) OS.kTextLanguageDontCare, regionCode,
2581: null, encoding) == OS.paramErr) {
2582: if (OS.UpgradeScriptInfoToTextEncoding(keyScript,
2583: (short) OS.kTextLanguageDontCare,
2584: (short) OS.kTextRegionDontCare, null,
2585: encoding) == OS.paramErr) {
2586: encoding[0] = OS.kTextEncodingMacRoman;
2587: }
2588: }
2589: int[] encodingInfo = new int[1];
2590: OS.CreateUnicodeToTextInfoByEncoding(encoding[0],
2591: encodingInfo);
2592: if (encodingInfo[0] != 0) {
2593: char[] input = { event.character };
2594: byte[] buffer = new byte[2];
2595: OS.ConvertFromUnicodeToPString(encodingInfo[0], 2,
2596: input, buffer);
2597: OS.DisposeUnicodeToTextInfo(encodingInfo);
2598: key = buffer[1] & 0x7f;
2599: }
2600: if (key == -1)
2601: return false;
2602: for (int i = 0; i <= 0x7F; i++) {
2603: int result1 = OS.KeyTranslate(kchrPtr,
2604: (short) (i | 512), state);
2605: int result2 = OS.KeyTranslate(kchrPtr, (short) i,
2606: state);
2607: if ((result1 & 0x7f) == key
2608: || (result2 & 0x7f) == key) {
2609: vKey = i;
2610: break;
2611: }
2612: }
2613: if (vKey == -1)
2614: return false;
2615: return OS.CGPostKeyboardEvent(key, vKey,
2616: type == SWT.KeyDown) == 0;
2617: }
2618: }
2619: case SWT.MouseDown:
2620: case SWT.MouseMove:
2621: case SWT.MouseUp: {
2622: CGPoint mouseCursorPosition = new CGPoint();
2623: int chord = OS.GetCurrentEventButtonState();
2624: if (type == SWT.MouseMove) {
2625: mouseCursorPosition.x = event.x;
2626: mouseCursorPosition.y = event.y;
2627: return OS.CGPostMouseEvent(mouseCursorPosition, true,
2628: 3, (chord & 0x1) != 0, (chord & 0x2) != 0,
2629: (chord & 0x4) != 0) == 0;
2630: } else {
2631: int button = event.button;
2632: if (button < 1 || button > 3)
2633: return false;
2634: boolean button1 = false, button2 = false, button3 = false;
2635: switch (button) {
2636: case 1: {
2637: button1 = type == SWT.MouseDown;
2638: button2 = (chord & 0x4) != 0;
2639: button3 = (chord & 0x2) != 0;
2640: break;
2641: }
2642: case 2: {
2643: button1 = (chord & 0x1) != 0;
2644: button2 = type == SWT.MouseDown;
2645: button3 = (chord & 0x2) != 0;
2646: break;
2647: }
2648: case 3: {
2649: button1 = (chord & 0x1) != 0;
2650: button2 = (chord & 0x4) != 0;
2651: button3 = type == SWT.MouseDown;
2652: break;
2653: }
2654: }
2655: org.eclipse.swt.internal.carbon.Point pt = new org.eclipse.swt.internal.carbon.Point();
2656: OS.GetGlobalMouse(pt);
2657: mouseCursorPosition.x = pt.h;
2658: mouseCursorPosition.y = pt.v;
2659: return OS.CGPostMouseEvent(mouseCursorPosition, true,
2660: 3, button1, button3, button2) == 0;
2661: }
2662: }
2663: }
2664: return false;
2665: }
2666:
2667: void postEvent(Event event) {
2668: /*
2669: * Place the event at the end of the event queue.
2670: * This code is always called in the Display's
2671: * thread so it must be re-enterant but does not
2672: * need to be synchronized.
2673: */
2674: if (eventQueue == null)
2675: eventQueue = new Event[4];
2676: int index = 0;
2677: int length = eventQueue.length;
2678: while (index < length) {
2679: if (eventQueue[index] == null)
2680: break;
2681: index++;
2682: }
2683: if (index == length) {
2684: Event[] newQueue = new Event[length + 4];
2685: System.arraycopy(eventQueue, 0, newQueue, 0, length);
2686: eventQueue = newQueue;
2687: }
2688: eventQueue[index] = event;
2689: }
2690:
2691: /**
2692: * Maps a point from one coordinate system to another.
2693: * When the control is null, coordinates are mapped to
2694: * the display.
2695: * <p>
2696: * NOTE: On right-to-left platforms where the coordinate
2697: * systems are mirrored, special care needs to be taken
2698: * when mapping coordinates from one control to another
2699: * to ensure the result is correctly mirrored.
2700: *
2701: * Mapping a point that is the origin of a rectangle and
2702: * then adding the width and height is not equivalent to
2703: * mapping the rectangle. When one control is mirrored
2704: * and the other is not, adding the width and height to a
2705: * point that was mapped causes the rectangle to extend
2706: * in the wrong direction. Mapping the entire rectangle
2707: * instead of just one point causes both the origin and
2708: * the corner of the rectangle to be mapped.
2709: * </p>
2710: *
2711: * @param from the source <code>Control</code> or <code>null</code>
2712: * @param to the destination <code>Control</code> or <code>null</code>
2713: * @param point to be mapped
2714: * @return point with mapped coordinates
2715: *
2716: * @exception IllegalArgumentException <ul>
2717: * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
2718: * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2719: * </ul>
2720: * @exception SWTException <ul>
2721: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2722: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2723: * </ul>
2724: *
2725: * @since 2.1.2
2726: */
2727: public Point map(Control from, Control to, Point point) {
2728: checkDevice();
2729: if (point == null)
2730: error(SWT.ERROR_NULL_ARGUMENT);
2731: return map(from, to, point.x, point.y);
2732: }
2733:
2734: /**
2735: * Maps a point from one coordinate system to another.
2736: * When the control is null, coordinates are mapped to
2737: * the display.
2738: * <p>
2739: * NOTE: On right-to-left platforms where the coordinate
2740: * systems are mirrored, special care needs to be taken
2741: * when mapping coordinates from one control to another
2742: * to ensure the result is correctly mirrored.
2743: *
2744: * Mapping a point that is the origin of a rectangle and
2745: * then adding the width and height is not equivalent to
2746: * mapping the rectangle. When one control is mirrored
2747: * and the other is not, adding the width and height to a
2748: * point that was mapped causes the rectangle to extend
2749: * in the wrong direction. Mapping the entire rectangle
2750: * instead of just one point causes both the origin and
2751: * the corner of the rectangle to be mapped.
2752: * </p>
2753: *
2754: * @param from the source <code>Control</code> or <code>null</code>
2755: * @param to the destination <code>Control</code> or <code>null</code>
2756: * @param x coordinates to be mapped
2757: * @param y coordinates to be mapped
2758: * @return point with mapped coordinates
2759: *
2760: * @exception IllegalArgumentException <ul>
2761: * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2762: * </ul>
2763: * @exception SWTException <ul>
2764: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2765: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2766: * </ul>
2767: *
2768: * @since 2.1.2
2769: */
2770: public Point map(Control from, Control to, int x, int y) {
2771: checkDevice();
2772: if (from != null && from.isDisposed())
2773: error(SWT.ERROR_INVALID_ARGUMENT);
2774: if (to != null && to.isDisposed())
2775: error(SWT.ERROR_INVALID_ARGUMENT);
2776: Point point = new Point(x, y);
2777: Rect rect = new Rect();
2778: if (from != null) {
2779: int window = OS.GetControlOwner(from.handle);
2780: if (OS.HIVIEW) {
2781: CGPoint pt = new CGPoint();
2782: OS.HIViewConvertPoint(pt, from.handle, 0);
2783: point.x += (int) pt.x;
2784: point.y += (int) pt.y;
2785: OS.GetWindowBounds(window,
2786: (short) OS.kWindowStructureRgn, rect);
2787: } else {
2788: OS.GetControlBounds(from.handle, rect);
2789: point.x += rect.left;
2790: point.y += rect.top;
2791: OS.GetWindowBounds(window,
2792: (short) OS.kWindowContentRgn, rect);
2793: }
2794: point.x += rect.left;
2795: point.y += rect.top;
2796: Rect inset = from.getInset();
2797: point.x -= inset.left;
2798: point.y -= inset.top;
2799: }
2800: if (to != null) {
2801: int window = OS.GetControlOwner(to.handle);
2802: if (OS.HIVIEW) {
2803: CGPoint pt = new CGPoint();
2804: OS.HIViewConvertPoint(pt, to.handle, 0);
2805: point.x -= (int) pt.x;
2806: point.y -= (int) pt.y;
2807: OS.GetWindowBounds(window,
2808: (short) OS.kWindowStructureRgn, rect);
2809: } else {
2810: OS.GetControlBounds(to.handle, rect);
2811: point.x -= rect.left;
2812: point.y -= rect.top;
2813: OS.GetWindowBounds(window,
2814: (short) OS.kWindowContentRgn, rect);
2815: }
2816: point.x -= rect.left;
2817: point.y -= rect.top;
2818: Rect inset = to.getInset();
2819: point.x += inset.left;
2820: point.y += inset.top;
2821: }
2822: return point;
2823: }
2824:
2825: /**
2826: * Maps a point from one coordinate system to another.
2827: * When the control is null, coordinates are mapped to
2828: * the display.
2829: * <p>
2830: * NOTE: On right-to-left platforms where the coordinate
2831: * systems are mirrored, special care needs to be taken
2832: * when mapping coordinates from one control to another
2833: * to ensure the result is correctly mirrored.
2834: *
2835: * Mapping a point that is the origin of a rectangle and
2836: * then adding the width and height is not equivalent to
2837: * mapping the rectangle. When one control is mirrored
2838: * and the other is not, adding the width and height to a
2839: * point that was mapped causes the rectangle to extend
2840: * in the wrong direction. Mapping the entire rectangle
2841: * instead of just one point causes both the origin and
2842: * the corner of the rectangle to be mapped.
2843: * </p>
2844: *
2845: * @param from the source <code>Control</code> or <code>null</code>
2846: * @param to the destination <code>Control</code> or <code>null</code>
2847: * @param rectangle to be mapped
2848: * @return rectangle with mapped coordinates
2849: *
2850: * @exception IllegalArgumentException <ul>
2851: * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
2852: * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2853: * </ul>
2854: * @exception SWTException <ul>
2855: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2856: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2857: * </ul>
2858: *
2859: * @since 2.1.2
2860: */
2861: public Rectangle map(Control from, Control to, Rectangle rectangle) {
2862: checkDevice();
2863: if (rectangle == null)
2864: error(SWT.ERROR_NULL_ARGUMENT);
2865: return map(from, to, rectangle.x, rectangle.y, rectangle.width,
2866: rectangle.height);
2867: }
2868:
2869: /**
2870: * Maps a point from one coordinate system to another.
2871: * When the control is null, coordinates are mapped to
2872: * the display.
2873: * <p>
2874: * NOTE: On right-to-left platforms where the coordinate
2875: * systems are mirrored, special care needs to be taken
2876: * when mapping coordinates from one control to another
2877: * to ensure the result is correctly mirrored.
2878: *
2879: * Mapping a point that is the origin of a rectangle and
2880: * then adding the width and height is not equivalent to
2881: * mapping the rectangle. When one control is mirrored
2882: * and the other is not, adding the width and height to a
2883: * point that was mapped causes the rectangle to extend
2884: * in the wrong direction. Mapping the entire rectangle
2885: * instead of just one point causes both the origin and
2886: * the corner of the rectangle to be mapped.
2887: * </p>
2888: *
2889: * @param from the source <code>Control</code> or <code>null</code>
2890: * @param to the destination <code>Control</code> or <code>null</code>
2891: * @param x coordinates to be mapped
2892: * @param y coordinates to be mapped
2893: * @param width coordinates to be mapped
2894: * @param height coordinates to be mapped
2895: * @return rectangle with mapped coordinates
2896: *
2897: * @exception IllegalArgumentException <ul>
2898: * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2899: * </ul>
2900: * @exception SWTException <ul>
2901: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2902: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2903: * </ul>
2904: *
2905: * @since 2.1.2
2906: */
2907: public Rectangle map(Control from, Control to, int x, int y,
2908: int width, int height) {
2909: checkDevice();
2910: if (from != null && from.isDisposed())
2911: error(SWT.ERROR_INVALID_ARGUMENT);
2912: if (to != null && to.isDisposed())
2913: error(SWT.ERROR_INVALID_ARGUMENT);
2914: Rectangle rectangle = new Rectangle(x, y, width, height);
2915: Rect rect = new Rect();
2916: if (from != null) {
2917: int window = OS.GetControlOwner(from.handle);
2918: if (OS.HIVIEW) {
2919: CGPoint pt = new CGPoint();
2920: OS.HIViewConvertPoint(pt, from.handle, 0);
2921: rectangle.x += (int) pt.x;
2922: rectangle.y += (int) pt.y;
2923: OS.GetWindowBounds(window,
2924: (short) OS.kWindowStructureRgn, rect);
2925: } else {
2926: OS.GetControlBounds(from.handle, rect);
2927: rectangle.x += rect.left;
2928: rectangle.y += rect.top;
2929: OS.GetWindowBounds(window,
2930: (short) OS.kWindowContentRgn, rect);
2931: }
2932: rectangle.x += rect.left;
2933: rectangle.y += rect.top;
2934: Rect inset = from.getInset();
2935: rectangle.x -= inset.left;
2936: rectangle.y -= inset.top;
2937: }
2938: if (to != null) {
2939: int window = OS.GetControlOwner(to.handle);
2940: if (OS.HIVIEW) {
2941: CGPoint pt = new CGPoint();
2942: OS.HIViewConvertPoint(pt, to.handle, 0);
2943: rectangle.x -= (int) pt.x;
2944: rectangle.y -= (int) pt.y;
2945: OS.GetWindowBounds(window,
2946: (short) OS.kWindowStructureRgn, rect);
2947: } else {
2948: OS.GetControlBounds(to.handle, rect);
2949: rectangle.x -= rect.left;
2950: rectangle.y -= rect.top;
2951: OS.GetWindowBounds(window,
2952: (short) OS.kWindowContentRgn, rect);
2953: }
2954: rectangle.x -= rect.left;
2955: rectangle.y -= rect.top;
2956: Rect inset = to.getInset();
2957: rectangle.x += inset.left;
2958: rectangle.y += inset.top;
2959: }
2960: return rectangle;
2961: }
2962:
2963: int menuProc(int nextHandler, int theEvent, int userData) {
2964: short menuID = 0;
2965: if (userData != 0) {
2966: menuID = OS.GetMenuID(userData);
2967: } else {
2968: int[] theMenu = new int[1];
2969: OS.GetEventParameter(theEvent, OS.kEventParamDirectObject,
2970: OS.typeMenuRef, null, 4, null, theMenu);
2971: menuID = OS.GetMenuID(theMenu[0]);
2972: }
2973: Menu menu = getMenu(menuID);
2974: if (menu != null)
2975: return menu.menuProc(nextHandler, theEvent, userData);
2976: return OS.eventNotHandledErr;
2977: }
2978:
2979: int mouseProc(int nextHandler, int theEvent, int userData) {
2980: int eventKind = OS.GetEventKind(theEvent);
2981: switch (eventKind) {
2982: case OS.kEventMouseDown:
2983: short[] buttonData = new short[1];
2984: OS.GetEventParameter(theEvent, OS.kEventParamMouseButton,
2985: OS.typeMouseButton, null, 2, null, buttonData);
2986: int[] clickCountData = new int[1];
2987: OS.GetEventParameter(theEvent, OS.kEventParamClickCount,
2988: OS.typeUInt32, null, 4, null, clickCountData);
2989: clickCount = clickCountButton == buttonData[0] ? clickCountData[0]
2990: : 1;
2991: clickCountButton = buttonData[0];
2992: break;
2993: case OS.kEventMouseDragged:
2994: case OS.kEventMouseMoved:
2995: mouseMoved = true;
2996: }
2997: if (mouseUpControl != null && eventKind == OS.kEventMouseUp) {
2998: if (!mouseUpControl.isDisposed()) {
2999: mouseUpControl.mouseProc(nextHandler, theEvent,
3000: userData);
3001: mouseUpControl = null;
3002: return OS.noErr;
3003: }
3004: mouseUpControl = null;
3005: }
3006: int sizeof = org.eclipse.swt.internal.carbon.Point.sizeof;
3007: org.eclipse.swt.internal.carbon.Point where = new org.eclipse.swt.internal.carbon.Point();
3008: OS.GetEventParameter(theEvent, OS.kEventParamMouseLocation,
3009: OS.typeQDPoint, null, sizeof, null, where);
3010: int[] theWindow = new int[1];
3011: int part = OS.FindWindow(where, theWindow);
3012: switch (part) {
3013: case OS.inMenuBar: {
3014: if (eventKind == OS.kEventMouseDown) {
3015: clearMenuFlags();
3016: if (menuBar == null || menuBar.isEnabled()) {
3017: OS.MenuSelect(where);
3018: }
3019: clearMenuFlags();
3020: return OS.noErr;
3021: }
3022: break;
3023: }
3024: case OS.inContent: {
3025: Rect windowRect = new Rect();
3026: OS.GetWindowBounds(theWindow[0],
3027: (short) OS.kWindowContentRgn, windowRect);
3028: CGPoint inPoint = new CGPoint();
3029: inPoint.x = where.h - windowRect.left;
3030: inPoint.y = where.v - windowRect.top;
3031: if (OS.HIVIEW) {
3032: int root = OS.HIViewGetRoot(theWindow[0]);
3033: int[] buffer = new int[1];
3034: OS.HIViewGetViewForMouseEvent(root, theEvent, buffer);
3035: int view = buffer[0];
3036: OS.HIViewFindByID(root, OS.kHIViewWindowContentID(),
3037: buffer);
3038: int contentView = buffer[0];
3039: while (view != 0 && view != contentView
3040: && !OS.IsControlEnabled(view)) {
3041: view = OS.HIViewGetSuperview(view);
3042: }
3043: Widget widget = null;
3044: boolean consume = false;
3045: do {
3046: widget = getWidget(view);
3047: if (widget != null) {
3048: if (widget.isEnabled())
3049: break;
3050: consume = true;
3051: }
3052: view = OS.HIViewGetSuperview(view);
3053: } while (view != 0 && view != contentView);
3054: if (widget != null) {
3055: if (widget.contains((int) inPoint.x,
3056: (int) inPoint.y)) {
3057: int result = userData != 0 ? widget.mouseProc(
3058: nextHandler, theEvent, userData)
3059: : OS.eventNotHandledErr;
3060: return consume ? OS.noErr : result;
3061: }
3062: }
3063: } else {
3064: int[] theRoot = new int[1];
3065: OS.GetRootControl(theWindow[0], theRoot);
3066: int[] theControl = new int[1];
3067: OS.HIViewGetSubviewHit(theRoot[0], inPoint, true,
3068: theControl);
3069: while (theControl[0] != 0
3070: && !OS.IsControlEnabled(theControl[0])) {
3071: OS.GetSuperControl(theControl[0], theControl);
3072: }
3073: Widget widget = null;
3074: boolean consume = false;
3075: if (theControl[0] == 0)
3076: theControl[0] = theRoot[0];
3077: do {
3078: widget = getWidget(theControl[0]);
3079: if (widget != null) {
3080: if (widget.isEnabled())
3081: break;
3082: consume = true;
3083: }
3084: OS.GetSuperControl(theControl[0], theControl);
3085: } while (theControl[0] != 0);
3086: if (theControl[0] == 0)
3087: widget = getWidget(theRoot[0]);
3088: if (widget != null) {
3089: if (widget.contains((int) inPoint.x,
3090: (int) inPoint.y)) {
3091: int result = userData != 0 ? widget.mouseProc(
3092: nextHandler, theEvent, userData)
3093: : OS.eventNotHandledErr;
3094: return consume ? OS.noErr : result;
3095: }
3096: }
3097: }
3098: break;
3099: }
3100: }
3101: switch (eventKind) {
3102: case OS.kEventMouseDragged:
3103: case OS.kEventMouseMoved:
3104: OS.InitCursor();
3105: }
3106: return OS.eventNotHandledErr;
3107: }
3108:
3109: int mouseHoverProc(int id, int handle) {
3110: OS.RemoveEventLoopTimer(id);
3111: mouseHoverID = 0;
3112: mouseMoved = false;
3113: if (currentControl != null && !currentControl.isDisposed()) {
3114: //OPTIMIZE - use OS calls
3115: int chord = OS.GetCurrentEventButtonState();
3116: int modifiers = OS.GetCurrentEventKeyModifiers();
3117: Point pt = currentControl.toControl(getCursorLocation());
3118: currentControl.sendMouseEvent(SWT.MouseHover, (short) 0,
3119: true, chord, (short) pt.x, (short) pt.y, modifiers);
3120: }
3121: return 0;
3122: }
3123:
3124: int[] readImageRef(int path) {
3125: int[] image = null;
3126: int url = OS.CFURLCreateFromFileSystemRepresentation(
3127: OS.kCFAllocatorDefault, path, OS.strlen(path), false);
3128: if (url != 0) {
3129: int extention = OS.CFURLCopyPathExtension(url);
3130: if (extention != 0) {
3131: int length = OS.CFStringGetLength(extention);
3132: char[] buffer = new char[length];
3133: CFRange range = new CFRange();
3134: range.length = length;
3135: OS.CFStringGetCharacters(extention, range, buffer);
3136: String ext = new String(buffer);
3137: if (ext.equalsIgnoreCase("png")) {
3138: int provider = OS.CGDataProviderCreateWithURL(url);
3139: if (provider != 0) {
3140: image = new int[] {
3141: OS.CGImageCreateWithPNGDataProvider(
3142: provider, null, true,
3143: OS.kCGRenderingIntentDefault),
3144: 0 };
3145: OS.CGDataProviderRelease(provider);
3146: }
3147: } else if (ext.equalsIgnoreCase("jpeg")
3148: || ext.equals("jpg")) {
3149: int provider = OS.CGDataProviderCreateWithURL(url);
3150: if (provider != 0) {
3151: image = new int[] {
3152: OS.CGImageCreateWithJPEGDataProvider(
3153: provider, null, true,
3154: OS.kCGRenderingIntentDefault),
3155: 0 };
3156: OS.CGDataProviderRelease(provider);
3157: }
3158: } else if (ext.equalsIgnoreCase("icns")) {
3159: byte[] fsRef = new byte[80];
3160: if (OS.CFURLGetFSRef(url, fsRef)) {
3161: byte[] fsSpec = new byte[70];
3162: if (OS.FSGetCatalogInfo(fsRef, 0, null, null,
3163: fsSpec, null) == OS.noErr) {
3164: int[] iconFamily = new int[1];
3165: OS.ReadIconFile(fsSpec, iconFamily);
3166: if (iconFamily[0] != 0) {
3167: image = createImageFromFamily(
3168: iconFamily[0],
3169: OS.kThumbnail32BitData,
3170: OS.kThumbnail8BitMask, 128, 128);
3171: OS.DisposeHandle(iconFamily[0]);
3172: }
3173: }
3174: }
3175: }
3176: OS.CFRelease(extention);
3177: }
3178: OS.CFRelease(url);
3179: }
3180: return image;
3181: }
3182:
3183: /**
3184: * Reads an event from the operating system's event queue,
3185: * dispatches it appropriately, and returns <code>true</code>
3186: * if there is potentially more work to do, or <code>false</code>
3187: * if the caller can sleep until another event is placed on
3188: * the event queue.
3189: * <p>
3190: * In addition to checking the system event queue, this method also
3191: * checks if any inter-thread messages (created by <code>syncExec()</code>
3192: * or <code>asyncExec()</code>) are waiting to be processed, and if
3193: * so handles them before returning.
3194: * </p>
3195: *
3196: * @return <code>false</code> if the caller can sleep upon return from this method
3197: *
3198: * @exception SWTException <ul>
3199: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3200: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3201: * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
3202: * </ul>
3203: *
3204: * @see #sleep
3205: * @see #wake
3206: */
3207: public boolean readAndDispatch() {
3208: checkDevice();
3209: boolean events = false;
3210: events |= runSettings();
3211: events |= runTimers();
3212: events |= runEnterExit();
3213: events |= runPopups();
3214: events |= runGrabs();
3215: int[] outEvent = new int[1];
3216: int status = OS.ReceiveNextEvent(0, null,
3217: OS.kEventDurationNoWait, true, outEvent);
3218: if (status == OS.noErr) {
3219: events = true;
3220: int eventClass = OS.GetEventClass(outEvent[0]);
3221: int eventKind = OS.GetEventKind(outEvent[0]);
3222: OS.SendEventToEventTarget(outEvent[0], OS
3223: .GetEventDispatcherTarget());
3224: OS.ReleaseEvent(outEvent[0]);
3225:
3226: /*
3227: * Feature in the Macintosh. HIComboBox does not send any
3228: * notification when the selection changes. The fix is to
3229: * detect if the combo text has changed after every event
3230: * has been dispatched. This is only necessary when the
3231: * combo has focus.
3232: */
3233: if (focusCombo != null && !focusCombo.isDisposed()) {
3234: focusCombo.checkSelection();
3235: }
3236:
3237: /*
3238: * Feature in the Macintosh. When an indeterminate progress
3239: * bar is running, it floods the event queue with messages in
3240: * order to show the animation. This means that async messages
3241: * will never run because there are always messages from the
3242: * operating system. The fix is to run async messages when ever
3243: * there is a wake message.
3244: *
3245: * NOTE: This is not the correct behavior. Operating system
3246: * messages are supposed to have priority over async messages.
3247: */
3248: if (eventClass == WAKE_CLASS && eventKind == WAKE_KIND) {
3249: runAsyncMessages(false);
3250: }
3251: }
3252: events |= runPaint();
3253: if (events) {
3254: runDeferredEvents();
3255: return true;
3256: }
3257: return runAsyncMessages(false);
3258: }
3259:
3260: static synchronized void register(Display display) {
3261: for (int i = 0; i < Displays.length; i++) {
3262: if (Displays[i] == null) {
3263: Displays[i] = display;
3264: return;
3265: }
3266: }
3267: Display[] newDisplays = new Display[Displays.length + 4];
3268: System.arraycopy(Displays, 0, newDisplays, 0, Displays.length);
3269: newDisplays[Displays.length] = display;
3270: Displays = newDisplays;
3271: }
3272:
3273: /**
3274: * Releases any internal resources back to the operating
3275: * system and clears all fields except the device handle.
3276: * <p>
3277: * Disposes all shells which are currently open on the display.
3278: * After this method has been invoked, all related related shells
3279: * will answer <code>true</code> when sent the message
3280: * <code>isDisposed()</code>.
3281: * </p><p>
3282: * When a device is destroyed, resources that were acquired
3283: * on behalf of the programmer need to be returned to the
3284: * operating system. For example, if the device allocated a
3285: * font to be used as the system font, this font would be
3286: * freed in <code>release</code>. Also,to assist the garbage
3287: * collector and minimize the amount of memory that is not
3288: * reclaimed when the programmer keeps a reference to a
3289: * disposed device, all fields except the handle are zero'd.
3290: * The handle is needed by <code>destroy</code>.
3291: * </p>
3292: * This method is called before <code>destroy</code>.
3293: *
3294: * @see Device#dispose
3295: * @see #destroy
3296: */
3297: protected void release() {
3298: sendEvent(SWT.Dispose, new Event());
3299: Shell[] shells = getShells();
3300: for (int i = 0; i < shells.length; i++) {
3301: Shell shell = shells[i];
3302: if (!shell.isDisposed())
3303: shell.dispose();
3304: }
3305: if (tray != null)
3306: tray.dispose();
3307: tray = null;
3308: while (readAndDispatch()) {
3309: }
3310: if (disposeList != null) {
3311: for (int i = 0; i < disposeList.length; i++) {
3312: if (disposeList[i] != null)
3313: disposeList[i].run();
3314: }
3315: }
3316: disposeList = null;
3317: synchronizer.releaseSynchronizer();
3318: synchronizer = null;
3319: releaseDisplay();
3320: super .release();
3321: }
3322:
3323: void releaseDisplay() {
3324: disposeWindows();
3325:
3326: if (gcWindow != 0)
3327: OS.DisposeWindow(gcWindow);
3328: gcWindow = 0;
3329:
3330: /* Release Timers */
3331: if (caretID != 0)
3332: OS.RemoveEventLoopTimer(caretID);
3333: if (mouseHoverID != 0)
3334: OS.RemoveEventLoopTimer(mouseHoverID);
3335: caretID = mouseHoverID = 0;
3336: if (timerIds != null) {
3337: for (int i = 0; i < timerIds.length; i++) {
3338: if (timerIds[i] != 0 && timerIds[i] != -1) {
3339: OS.RemoveEventLoopTimer(timerIds[i]);
3340: }
3341: }
3342: }
3343: timerIds = null;
3344:
3345: actionCallback.dispose();
3346: appleEventCallback.dispose();
3347: caretCallback.dispose();
3348: commandCallback.dispose();
3349: controlCallback.dispose();
3350: accessibilityCallback.dispose();
3351: drawItemCallback.dispose();
3352: itemCompareCallback.dispose();
3353: itemDataCallback.dispose();
3354: itemNotificationCallback.dispose();
3355: helpCallback.dispose();
3356: hitTestCallback.dispose();
3357: keyboardCallback.dispose();
3358: menuCallback.dispose();
3359: mouseHoverCallback.dispose();
3360: mouseCallback.dispose();
3361: trackingCallback.dispose();
3362: windowCallback.dispose();
3363: colorCallback.dispose();
3364: textInputCallback.dispose();
3365: appearanceCallback.dispose();
3366: actionCallback = appleEventCallback = caretCallback = commandCallback = appearanceCallback = null;
3367: accessibilityCallback = controlCallback = drawItemCallback = itemDataCallback = itemNotificationCallback = null;
3368: helpCallback = hitTestCallback = keyboardCallback = menuCallback = itemCompareCallback = null;
3369: mouseHoverCallback = mouseCallback = trackingCallback = windowCallback = colorCallback = null;
3370: textInputCallback = null;
3371: actionProc = appleEventProc = caretProc = commandProc = appearanceProc = 0;
3372: accessibilityProc = controlProc = drawItemProc = itemDataProc = itemNotificationProc = itemCompareProc = 0;
3373: helpProc = hitTestProc = keyboardProc = menuProc = 0;
3374: mouseHoverProc = mouseProc = trackingProc = windowProc = colorProc = 0;
3375: textInputProc = 0;
3376: timerCallback.dispose();
3377: timerCallback = null;
3378: timerProc = 0;
3379: grabControl = currentControl = mouseUpControl = focusControl = focusCombo = null;
3380: helpWidget = null;
3381: if (helpString != 0)
3382: OS.CFRelease(helpString);
3383: helpString = 0;
3384: menus = popups = null;
3385: menuBar = null;
3386:
3387: /* Release the System Images */
3388: if (errorImage != null)
3389: errorImage.dispose();
3390: if (infoImage != null)
3391: infoImage.dispose();
3392: if (warningImage != null)
3393: warningImage.dispose();
3394: errorImage = infoImage = warningImage = null;
3395:
3396: /* Release the System Cursors */
3397: for (int i = 0; i < cursors.length; i++) {
3398: if (cursors[i] != null)
3399: cursors[i].dispose();
3400: }
3401: cursors = null;
3402:
3403: /* Release Dock image */
3404: if (dockImage != 0)
3405: OS.CGImageRelease(dockImage);
3406: if (dockImageData != 0)
3407: OS.DisposePtr(dockImageData);
3408: dockImage = dockImageData = 0;
3409:
3410: //NOT DONE - call terminate TXN if this is the last display
3411: //NOTE: - display create and dispose needs to be synchronized on all platforms
3412: // TXNTerminateTextension ();
3413: }
3414:
3415: /**
3416: * Removes the listener from the collection of listeners who will
3417: * be notified when an event of the given type occurs anywhere in
3418: * a widget. The event type is one of the event constants defined
3419: * in class <code>SWT</code>.
3420: *
3421: * @param eventType the type of event to listen for
3422: * @param listener the listener which should no longer be notified when the event occurs
3423: *
3424: * @exception IllegalArgumentException <ul>
3425: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3426: * </ul>
3427: * @exception SWTException <ul>
3428: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3429: * </ul>
3430: *
3431: * @see Listener
3432: * @see SWT
3433: * @see #addFilter
3434: * @see #addListener
3435: *
3436: * @since 3.0
3437: */
3438: public void removeFilter(int eventType, Listener listener) {
3439: checkDevice();
3440: if (listener == null)
3441: error(SWT.ERROR_NULL_ARGUMENT);
3442: if (filterTable == null)
3443: return;
3444: filterTable.unhook(eventType, listener);
3445: if (filterTable.size() == 0)
3446: filterTable = null;
3447: }
3448:
3449: /**
3450: * Removes the listener from the collection of listeners who will
3451: * be notified when an event of the given type occurs. The event type
3452: * is one of the event constants defined in class <code>SWT</code>.
3453: *
3454: * @param eventType the type of event to listen for
3455: * @param listener the listener which should no longer be notified when the event occurs
3456: *
3457: * @exception IllegalArgumentException <ul>
3458: * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
3459: * </ul>
3460: * @exception SWTException <ul>
3461: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3462: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3463: * </ul>
3464: *
3465: * @see Listener
3466: * @see SWT
3467: * @see #addListener
3468: *
3469: * @since 2.0
3470: */
3471: public void removeListener(int eventType, Listener listener) {
3472: checkDevice();
3473: if (listener == null)
3474: error(SWT.ERROR_NULL_ARGUMENT);
3475: if (eventTable == null)
3476: return;
3477: eventTable.unhook(eventType, listener);
3478: }
3479:
3480: void removeMenu(Menu menu) {
3481: if (menus == null)
3482: return;
3483: menus[menu.id - ID_START] = null;
3484: }
3485:
3486: void removePopup(Menu menu) {
3487: if (popups == null)
3488: return;
3489: for (int i = 0; i < popups.length; i++) {
3490: if (popups[i] == menu) {
3491: popups[i] = null;
3492: return;
3493: }
3494: }
3495: }
3496:
3497: Widget removeWidget(int handle) {
3498: if (handle == 0)
3499: return null;
3500: Widget widget = null;
3501: property[0] = 0;
3502: OS.GetControlProperty(handle, SWT0, SWT0, 4, null, property);
3503: int index = property[0] - 1;
3504: if (0 <= index && index < widgetTable.length) {
3505: widget = widgetTable[index];
3506: widgetTable[index] = null;
3507: indexTable[index] = freeSlot;
3508: freeSlot = index;
3509: OS.RemoveControlProperty(handle, SWT0, SWT0);
3510:
3511: }
3512: return widget;
3513: }
3514:
3515: boolean runAsyncMessages(boolean all) {
3516: return synchronizer.runAsyncMessages(all);
3517: }
3518:
3519: boolean runEnterExit() {
3520: //OPTIMIZE - no garbage, widget hit tested again in mouse move
3521: boolean eventSent = false;
3522: Control control = null;
3523: int[] theControl = new int[1];
3524: org.eclipse.swt.internal.carbon.Point where = new org.eclipse.swt.internal.carbon.Point();
3525: OS.GetGlobalMouse(where);
3526: int[] theWindow = new int[1];
3527: if (OS.FindWindow(where, theWindow) == OS.inContent) {
3528: if (theWindow[0] != 0) {
3529: Rect rect = new Rect();
3530: OS.GetWindowBounds(theWindow[0],
3531: (short) OS.kWindowContentRgn, rect);
3532: CGPoint inPoint = new CGPoint();
3533: inPoint.x = where.h - rect.left;
3534: inPoint.y = where.v - rect.top;
3535: int[] theRoot = new int[1];
3536: OS.GetRootControl(theWindow[0], theRoot);
3537: OS.HIViewGetSubviewHit(theRoot[0], inPoint, true,
3538: theControl);
3539: while (theControl[0] != 0
3540: && !OS.IsControlEnabled(theControl[0])) {
3541: OS.GetSuperControl(theControl[0], theControl);
3542: }
3543: boolean propagate = true;
3544: if (theControl[0] != 0) {
3545: do {
3546: Widget widget = getWidget(theControl[0]);
3547: if (widget != null) {
3548: if (widget instanceof Control) {
3549: Control cursorControl = (Control) widget;
3550: if (cursorControl.isEnabled()) {
3551: if (cursorControl.isEnabledModal()) {
3552: if (widget
3553: .isTrimHandle(theControl[0])) {
3554: propagate = false;
3555: break;
3556: }
3557: control = cursorControl;
3558: }
3559: break;
3560: }
3561: }
3562: }
3563: OS.GetSuperControl(theControl[0], theControl);
3564: } while (theControl[0] != 0);
3565: }
3566: if (control == null && propagate) {
3567: theControl[0] = theRoot[0];
3568: Widget widget = getWidget(theControl[0]);
3569: if (widget != null && widget instanceof Control) {
3570: Control cursorControl = (Control) widget;
3571: if (cursorControl.isEnabled()) {
3572: if (cursorControl.isEnabledModal()) {
3573: control = cursorControl;
3574: theControl[0] = control.handle;
3575: }
3576: }
3577: }
3578: }
3579: if (control != null
3580: && !control.contains((int) inPoint.x,
3581: (int) inPoint.y)) {
3582: control = null;
3583: }
3584: }
3585: }
3586: if (control != currentControl) {
3587: if (currentControl != null && !currentControl.isDisposed()) {
3588: eventSent = true;
3589: int chord = OS.GetCurrentEventButtonState();
3590: int modifiers = OS.GetCurrentEventKeyModifiers();
3591: Point pt = currentControl.toControl(where.h, where.v);
3592: currentControl.sendMouseEvent(SWT.MouseExit, (short) 0,
3593: true, chord, (short) pt.x, (short) pt.y,
3594: modifiers);
3595: if (mouseHoverID != 0)
3596: OS.RemoveEventLoopTimer(mouseHoverID);
3597: mouseHoverID = 0;
3598: mouseMoved = false;
3599: }
3600: // widget could be disposed at this point
3601: if (control != null && control.isDisposed())
3602: control = null;
3603: if ((currentControl = control) != null) {
3604: eventSent = true;
3605: int chord = OS.GetCurrentEventButtonState();
3606: int modifiers = OS.GetCurrentEventKeyModifiers();
3607: Point pt = currentControl.toControl(where.h, where.v);
3608: currentControl.sendMouseEvent(SWT.MouseEnter,
3609: (short) 0, true, chord, (short) pt.x,
3610: (short) pt.y, modifiers);
3611: }
3612: }
3613: if (control != null && mouseMoved) {
3614: int[] outDelay = new int[1];
3615: OS.HMGetTagDelay(outDelay);
3616: if (mouseHoverID != 0) {
3617: OS.SetEventLoopTimerNextFireTime(mouseHoverID,
3618: outDelay[0] / 1000.0);
3619: } else {
3620: int eventLoop = OS.GetCurrentEventLoop();
3621: int[] id = new int[1];
3622: OS.InstallEventLoopTimer(eventLoop,
3623: outDelay[0] / 1000.0, 0.0, mouseHoverProc, 0,
3624: id);
3625: mouseHoverID = id[0];
3626: }
3627: mouseMoved = false;
3628: }
3629: if (!OS.StillDown() && theWindow[0] != 0 && theControl[0] != 0) {
3630: Rect rect = new Rect();
3631: OS.GetWindowBounds(theWindow[0],
3632: (short) OS.kWindowContentRgn, rect);
3633: where.h -= rect.left;
3634: where.v -= rect.top;
3635: int modifiers = OS.GetCurrentEventKeyModifiers();
3636: boolean[] cursorWasSet = new boolean[1];
3637: OS.HandleControlSetCursor(theControl[0], where,
3638: (short) modifiers, cursorWasSet);
3639: //GOOGLE: Allow WebKit to maintain it's own cursor state.
3640: if (!cursorWasSet[0] && !(control instanceof Browser))
3641: OS.SetThemeCursor(OS.kThemeArrowCursor);
3642: }
3643: return eventSent;
3644: }
3645:
3646: boolean runDeferredEvents() {
3647: /*
3648: * Run deferred events. This code is always
3649: * called in the Display's thread so it must
3650: * be re-enterant need not be synchronized.
3651: */
3652: while (eventQueue != null) {
3653:
3654: /* Take an event off the queue */
3655: Event event = eventQueue[0];
3656: if (event == null)
3657: break;
3658: int length = eventQueue.length;
3659: System.arraycopy(eventQueue, 1, eventQueue, 0, --length);
3660: eventQueue[length] = null;
3661:
3662: /* Run the event */
3663: Widget widget = event.widget;
3664: if (widget != null && !widget.isDisposed()) {
3665: Widget item = event.item;
3666: if (item == null || !item.isDisposed()) {
3667: widget.notifyListeners(event.type, event);
3668: }
3669: }
3670:
3671: /*
3672: * At this point, the event queue could
3673: * be null due to a recursive invokation
3674: * when running the event.
3675: */
3676: }
3677:
3678: /* Clear the queue */
3679: eventQueue = null;
3680: return true;
3681: }
3682:
3683: boolean runEventLoopTimers() {
3684: allowTimers = false;
3685: boolean result = OS.ReceiveNextEvent(0, null,
3686: OS.kEventDurationNoWait, false, null) == OS.noErr;
3687: allowTimers = true;
3688: return result;
3689: }
3690:
3691: boolean runGrabs() {
3692: if (grabControl == null || grabbing)
3693: return false;
3694: if (!OS.StillDown()) {
3695: grabControl = null;
3696: return false;
3697: }
3698: Rect rect = new Rect();
3699: int[] outModifiers = new int[1];
3700: short[] outResult = new short[1];
3701: CGPoint pt = new CGPoint();
3702: org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point();
3703: grabbing = true;
3704: mouseUpControl = null;
3705: try {
3706: while (grabControl != null && !grabControl.isDisposed()
3707: && outResult[0] != OS.kMouseTrackingMouseUp) {
3708: if (!OS.HIVIEW)
3709: grabControl.getShell().update(true);
3710: lastModifiers = OS.GetCurrentEventKeyModifiers();
3711: int oldState = OS.GetCurrentEventButtonState();
3712: int handle = grabControl.handle;
3713: int window = OS.GetControlOwner(handle);
3714: int port = OS.HIVIEW ? -1 : OS.GetWindowPort(window);
3715: OS.TrackMouseLocationWithOptions(port,
3716: OS.kTrackMouseLocationOptionDontConsumeMouseUp,
3717: 10 / 1000.0, outPt, outModifiers, outResult);
3718: int type = 0, button = 0;
3719: switch ((int) outResult[0]) {
3720: case OS.kMouseTrackingTimedOut: {
3721: runAsyncMessages(false);
3722: break;
3723: }
3724: case OS.kMouseTrackingMouseDown: {
3725: type = SWT.MouseDown;
3726: int newState = OS.GetCurrentEventButtonState();
3727: if ((oldState & 0x1) == 0 && (newState & 0x1) != 0)
3728: button = 1;
3729: if ((oldState & 0x2) == 0 && (newState & 0x2) != 0)
3730: button = 2;
3731: if ((oldState & 0x4) == 0 && (newState & 0x4) != 0)
3732: button = 3;
3733: break;
3734: }
3735: case OS.kMouseTrackingMouseUp: {
3736: type = SWT.MouseUp;
3737: int newState = OS.GetCurrentEventButtonState();
3738: if ((oldState & 0x1) != 0 && (newState & 0x1) == 0)
3739: button = 1;
3740: if ((oldState & 0x2) != 0 && (newState & 0x2) == 0)
3741: button = 2;
3742: if ((oldState & 0x4) != 0 && (newState & 0x4) == 0)
3743: button = 3;
3744: break;
3745: }
3746: // case OS.kMouseTrackingMouseExited: type = SWT.MouseExit; break;
3747: // case OS.kMouseTrackingMouseEntered: type = SWT.MouseEnter; break;
3748: case OS.kMouseTrackingMouseDragged: {
3749: mouseMoved = true;
3750: type = SWT.MouseMove;
3751: dragDetect(grabControl);
3752: break;
3753: }
3754: case OS.kMouseTrackingMouseKeyModifiersChanged:
3755: break;
3756: case OS.kMouseTrackingUserCancelled:
3757: break;
3758: case OS.kMouseTrackingMouseMoved: {
3759: mouseMoved = true;
3760: type = SWT.MouseMove;
3761: break;
3762: }
3763: }
3764: boolean events = type != 0;
3765: if (type != 0) {
3766: int x = outPt.h;
3767: int y = outPt.v;
3768: if (OS.HIVIEW) {
3769: OS.GetWindowBounds(window,
3770: (short) OS.kWindowStructureRgn, rect);
3771: pt.x = x - rect.left;
3772: pt.y = y - rect.top;
3773: OS.HIViewConvertPoint(pt, 0, handle);
3774: x = (int) pt.x;
3775: y = (int) pt.y;
3776: } else {
3777: OS.GetControlBounds(handle, rect);
3778: x -= rect.left;
3779: y -= rect.top;
3780: }
3781: int chord = OS.GetCurrentEventButtonState();
3782: if (grabControl != null
3783: && !grabControl.isDisposed()) {
3784: if (type == SWT.MouseUp) {
3785: mouseUpControl = grabControl;
3786: } else {
3787: grabControl.sendMouseEvent(type,
3788: (short) button, true, chord,
3789: (short) x, (short) y,
3790: outModifiers[0]);
3791: }
3792: }
3793: }
3794: if (events)
3795: runDeferredEvents();
3796: }
3797: } finally {
3798: grabbing = false;
3799: grabControl = null;
3800: }
3801: return true;
3802: }
3803:
3804: boolean runPaint() {
3805: if (!needsPaint)
3806: return false;
3807: needsPaint = false;
3808: for (int i = 0; i < widgetTable.length; i++) {
3809: Widget widget = widgetTable[i];
3810: if (widget != null && widget instanceof Shell) {
3811: Shell shell = (Shell) widget;
3812: if (shell.invalRgn != 0) {
3813: int invalRgn = shell.invalRgn;
3814: shell.invalRgn = 0;
3815: shell
3816: .redrawChildren(OS
3817: .HIViewGetRoot(shell.shellHandle),
3818: invalRgn);
3819: OS.DisposeRgn(invalRgn);
3820: }
3821: }
3822: }
3823: return true;
3824: }
3825:
3826: boolean runPopups() {
3827: if (popups == null)
3828: return false;
3829: grabControl = null;
3830: boolean result = false;
3831: while (popups != null) {
3832: Menu menu = popups[0];
3833: if (menu == null)
3834: break;
3835: int length = popups.length;
3836: System.arraycopy(popups, 1, popups, 0, --length);
3837: popups[length] = null;
3838: clearMenuFlags();
3839: runDeferredEvents();
3840: menu._setVisible(true);
3841: clearMenuFlags();
3842: result = true;
3843: }
3844: popups = null;
3845: return result;
3846: }
3847:
3848: boolean runSettings() {
3849: if (!runSettings)
3850: return false;
3851: runSettings = false;
3852: initializeInsets();
3853: sendEvent(SWT.Settings, null);
3854: Shell[] shells = getShells();
3855: for (int i = 0; i < shells.length; i++) {
3856: Shell shell = shells[i];
3857: if (!shell.isDisposed()) {
3858: shell.redraw(true);
3859: shell.layout(true, true);
3860: }
3861: }
3862: return true;
3863: }
3864:
3865: boolean runTimers() {
3866: if (timerList == null)
3867: return false;
3868: boolean result = false;
3869: for (int i = 0; i < timerList.length; i++) {
3870: if (timerIds[i] == -1) {
3871: Runnable runnable = timerList[i];
3872: timerList[i] = null;
3873: timerIds[i] = 0;
3874: if (runnable != null) {
3875: result = true;
3876: runnable.run();
3877: }
3878: }
3879: }
3880: return result;
3881: }
3882:
3883: void sendEvent(int eventType, Event event) {
3884: if (eventTable == null && filterTable == null) {
3885: return;
3886: }
3887: if (event == null)
3888: event = new Event();
3889: event.display = this ;
3890: event.type = eventType;
3891: if (event.time == 0)
3892: event.time = getLastEventTime();
3893: if (!filterEvent(event)) {
3894: if (eventTable != null)
3895: eventTable.sendEvent(event);
3896: }
3897: }
3898:
3899: /**
3900: * On platforms which support it, sets the application name
3901: * to be the argument. On Motif, for example, this can be used
3902: * to set the name used for resource lookup. Specifying
3903: * <code>null</code> for the name clears it.
3904: *
3905: * @param name the new app name or <code>null</code>
3906: */
3907: public static void setAppName(String name) {
3908: APP_NAME = name;
3909: }
3910:
3911: void setCurrentCaret(Caret caret) {
3912: if (caretID != 0)
3913: OS.RemoveEventLoopTimer(caretID);
3914: caretID = 0;
3915: currentCaret = caret;
3916: if (currentCaret != null) {
3917: int blinkRate = currentCaret.blinkRate;
3918: int[] timerId = new int[1];
3919: double time = blinkRate / 1000.0;
3920: int eventLoop = OS.GetCurrentEventLoop();
3921: OS.InstallEventLoopTimer(eventLoop, time, time, caretProc,
3922: 0, timerId);
3923: caretID = timerId[0];
3924: }
3925: }
3926:
3927: void setCursor(int cursor) {
3928: switch (cursor) {
3929: case OS.kThemePointingHandCursor:
3930: case OS.kThemeArrowCursor:
3931: case OS.kThemeSpinningCursor:
3932: case OS.kThemeCrossCursor:
3933: case OS.kThemeWatchCursor:
3934: case OS.kThemeIBeamCursor:
3935: case OS.kThemeNotAllowedCursor:
3936: case OS.kThemeResizeLeftRightCursor:
3937: case OS.kThemeResizeLeftCursor:
3938: case OS.kThemeResizeRightCursor:
3939: OS.SetThemeCursor(cursor);
3940: break;
3941: default:
3942: OS.SetCursor(cursor);
3943: }
3944: }
3945:
3946: /**
3947: * Sets the location of the on-screen pointer relative to the top left corner
3948: * of the screen. <b>Note: It is typically considered bad practice for a
3949: * program to move the on-screen pointer location.</b>
3950: *
3951: * @param x the new x coordinate for the cursor
3952: * @param y the new y coordinate for the cursor
3953: *
3954: * @exception SWTException <ul>
3955: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3956: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3957: * </ul>
3958: *
3959: * @since 2.1
3960: */
3961: public void setCursorLocation(int x, int y) {
3962: checkDevice();
3963: CGPoint pt = new CGPoint();
3964: pt.x = x;
3965: pt.y = y;
3966: OS.CGWarpMouseCursorPosition(pt);
3967: }
3968:
3969: /**
3970: * Sets the location of the on-screen pointer relative to the top left corner
3971: * of the screen. <b>Note: It is typically considered bad practice for a
3972: * program to move the on-screen pointer location.</b>
3973: *
3974: * @param point new position
3975: *
3976: * @exception SWTException <ul>
3977: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3978: * <li>ERROR_NULL_ARGUMENT - if the point is null
3979: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3980: * </ul>
3981: *
3982: * @since 2.0
3983: */
3984: public void setCursorLocation(Point point) {
3985: checkDevice();
3986: if (point == null)
3987: error(SWT.ERROR_NULL_ARGUMENT);
3988: setCursorLocation(point.x, point.y);
3989: }
3990:
3991: /**
3992: * Sets the application defined property of the receiver
3993: * with the specified name to the given argument.
3994: * <p>
3995: * Applications may have associated arbitrary objects with the
3996: * receiver in this fashion. If the objects stored in the
3997: * properties need to be notified when the display is disposed
3998: * of, it is the application's responsibility provide a
3999: * <code>disposeExec()</code> handler which does so.
4000: * </p>
4001: *
4002: * @param key the name of the property
4003: * @param value the new value for the property
4004: *
4005: * @exception IllegalArgumentException <ul>
4006: * <li>ERROR_NULL_ARGUMENT - if the key is null</li>
4007: * </ul>
4008: * @exception SWTException <ul>
4009: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4010: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4011: * </ul>
4012: *
4013: * @see #getData(String)
4014: * @see #disposeExec(Runnable)
4015: */
4016: public void setData(String key, Object value) {
4017: checkDevice();
4018: if (key == null)
4019: error(SWT.ERROR_NULL_ARGUMENT);
4020:
4021: if (key.equals(ADD_WIDGET_KEY)) {
4022: Object[] data = (Object[]) value;
4023: int handle = ((Integer) data[0]).intValue();
4024: Widget widget = (Widget) data[1];
4025: if (widget == null)
4026: removeWidget(handle);
4027: else
4028: addWidget(handle, widget);
4029: }
4030:
4031: /* Remove the key/value pair */
4032: if (value == null) {
4033: if (keys == null)
4034: return;
4035: int index = 0;
4036: while (index < keys.length && !keys[index].equals(key))
4037: index++;
4038: if (index == keys.length)
4039: return;
4040: if (keys.length == 1) {
4041: keys = null;
4042: values = null;
4043: } else {
4044: String[] newKeys = new String[keys.length - 1];
4045: Object[] newValues = new Object[values.length - 1];
4046: System.arraycopy(keys, 0, newKeys, 0, index);
4047: System.arraycopy(keys, index + 1, newKeys, index,
4048: newKeys.length - index);
4049: System.arraycopy(values, 0, newValues, 0, index);
4050: System.arraycopy(values, index + 1, newValues, index,
4051: newValues.length - index);
4052: keys = newKeys;
4053: values = newValues;
4054: }
4055: return;
4056: }
4057:
4058: /* Add the key/value pair */
4059: if (keys == null) {
4060: keys = new String[] { key };
4061: values = new Object[] { value };
4062: return;
4063: }
4064: for (int i = 0; i < keys.length; i++) {
4065: if (keys[i].equals(key)) {
4066: values[i] = value;
4067: return;
4068: }
4069: }
4070: String[] newKeys = new String[keys.length + 1];
4071: Object[] newValues = new Object[values.length + 1];
4072: System.arraycopy(keys, 0, newKeys, 0, keys.length);
4073: System.arraycopy(values, 0, newValues, 0, values.length);
4074: newKeys[keys.length] = key;
4075: newValues[values.length] = value;
4076: keys = newKeys;
4077: values = newValues;
4078: }
4079:
4080: /**
4081: * Sets the application defined, display specific data
4082: * associated with the receiver, to the argument.
4083: * The <em>display specific data</em> is a single,
4084: * unnamed field that is stored with every display.
4085: * <p>
4086: * Applications may put arbitrary objects in this field. If
4087: * the object stored in the display specific data needs to
4088: * be notified when the display is disposed of, it is the
4089: * application's responsibility provide a
4090: * <code>disposeExec()</code> handler which does so.
4091: * </p>
4092: *
4093: * @param data the new display specific data
4094: *
4095: * @exception SWTException <ul>
4096: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4097: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4098: * </ul>
4099: *
4100: * @see #getData()
4101: * @see #disposeExec(Runnable)
4102: */
4103: public void setData(Object data) {
4104: checkDevice();
4105: this .data = data;
4106: }
4107:
4108: /**
4109: * Sets the synchronizer used by the display to be
4110: * the argument, which can not be null.
4111: *
4112: * @param synchronizer the new synchronizer for the display (must not be null)
4113: *
4114: * @exception IllegalArgumentException <ul>
4115: * <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
4116: * </ul>
4117: * @exception SWTException <ul>
4118: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4119: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4120: * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
4121: * </ul>
4122: */
4123: public void setSynchronizer(Synchronizer synchronizer) {
4124: checkDevice();
4125: if (synchronizer == null)
4126: error(SWT.ERROR_NULL_ARGUMENT);
4127: if (this .synchronizer != null) {
4128: this .synchronizer.runAsyncMessages(true);
4129: }
4130: this .synchronizer = synchronizer;
4131: }
4132:
4133: void setMenuBar(Menu menu) {
4134: /*
4135: * Feature in the Macintosh. SetRootMenu() does not
4136: * accept NULL to indicate that their should be no
4137: * menu bar. The fix is to create a temporary empty
4138: * menu, set that to be the menu bar, clear the menu
4139: * bar and then delete the temporary menu.
4140: */
4141: if (menu == menuBar)
4142: return;
4143: int theMenu = 0;
4144: if (menu == null) {
4145: int outMenuRef[] = new int[1];
4146: OS.CreateNewMenu((short) ID_TEMPORARY, 0, outMenuRef);
4147: theMenu = outMenuRef[0];
4148: } else {
4149: theMenu = menu.handle;
4150: }
4151: OS.SetRootMenu(theMenu);
4152: if (menu == null) {
4153: OS.ClearMenuBar();
4154: OS.DisposeMenu(theMenu);
4155: }
4156: menuBar = menu;
4157: }
4158:
4159: /**
4160: * Causes the user-interface thread to <em>sleep</em> (that is,
4161: * to be put in a state where it does not consume CPU cycles)
4162: * until an event is received or it is otherwise awakened.
4163: *
4164: * @return <code>true</code> if an event requiring dispatching was placed on the queue.
4165: *
4166: * @exception SWTException <ul>
4167: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4168: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4169: * </ul>
4170: *
4171: * @see #wake
4172: */
4173: public boolean sleep() {
4174: checkDevice();
4175: if (getMessageCount() != 0)
4176: return true;
4177: disposeWindows();
4178: if (eventTable != null && eventTable.hooks(SWT.Settings)) {
4179: RGBColor color = new RGBColor();
4180: int status = OS.noErr, depth = getDepth();
4181: do {
4182: allowTimers = false;
4183: status = OS.ReceiveNextEvent(0, null, 0.5, false, null);
4184: allowTimers = true;
4185: if (status == OS.eventLoopTimedOutErr) {
4186: OS
4187: .GetThemeBrushAsColor(
4188: (short) OS.kThemeBrushPrimaryHighlightColor,
4189: (short) depth, true, color);
4190: if (highlightColor.red != color.red
4191: || highlightColor.green != color.green
4192: || highlightColor.blue != color.blue) {
4193: highlightColor = color;
4194: runSettings = true;
4195: return true;
4196: }
4197: }
4198: } while (status == OS.eventLoopTimedOutErr);
4199: return status == OS.noErr;
4200: }
4201: allowTimers = false;
4202: int status = OS.ReceiveNextEvent(0, null,
4203: OS.kEventDurationForever, false, null);
4204: allowTimers = true;
4205: return status == OS.noErr;
4206: }
4207:
4208: /**
4209: * Causes the <code>run()</code> method of the runnable to
4210: * be invoked by the user-interface thread at the next
4211: * reasonable opportunity. The thread which calls this method
4212: * is suspended until the runnable completes. Specifying <code>null</code>
4213: * as the runnable simply wakes the user-interface thread.
4214: * <p>
4215: * Note that at the time the runnable is invoked, widgets
4216: * that have the receiver as their display may have been
4217: * disposed. Therefore, it is necessary to check for this
4218: * case inside the runnable before accessing the widget.
4219: * </p>
4220: *
4221: * @param runnable code to run on the user-interface thread or <code>null</code>
4222: *
4223: * @exception SWTException <ul>
4224: * <li>ERROR_FAILED_EXEC - if an exception occured when executing the runnable</li>
4225: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4226: * </ul>
4227: *
4228: * @see #asyncExec
4229: */
4230: public void syncExec(Runnable runnable) {
4231: if (isDisposed())
4232: error(SWT.ERROR_DEVICE_DISPOSED);
4233: synchronizer.syncExec(runnable);
4234: }
4235:
4236: int textInputProc(int nextHandler, int theEvent, int userData) {
4237: int theWindow = OS.GetUserFocusWindow();
4238: if (theWindow != 0) {
4239: int[] theControl = new int[1];
4240: OS.GetKeyboardFocus(theWindow, theControl);
4241: Widget widget = getWidget(theControl[0]);
4242: if (widget != null) {
4243: /* Stop the default event handler from activating the default button */
4244: OS.GetWindowDefaultButton(theWindow, theControl);
4245: OS.SetWindowDefaultButton(theWindow, 0);
4246: int result = widget.textInputProc(nextHandler,
4247: theEvent, userData);
4248: if (result == OS.eventNotHandledErr) {
4249: result = OS.CallNextEventHandler(nextHandler,
4250: theEvent);
4251: }
4252: OS.SetWindowDefaultButton(theWindow, theControl[0]);
4253: return result;
4254: }
4255: }
4256: return OS.eventNotHandledErr;
4257: }
4258:
4259: /**
4260: * Causes the <code>run()</code> method of the runnable to
4261: * be invoked by the user-interface thread after the specified
4262: * number of milliseconds have elapsed. If milliseconds is less
4263: * than zero, the runnable is not executed.
4264: * <p>
4265: * Note that at the time the runnable is invoked, widgets
4266: * that have the receiver as their display may have been
4267: * disposed. Therefore, it is necessary to check for this
4268: * case inside the runnable before accessing the widget.
4269: * </p>
4270: *
4271: * @param milliseconds the delay before running the runnable
4272: * @param runnable code to run on the user-interface thread
4273: *
4274: * @exception IllegalArgumentException <ul>
4275: * <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
4276: * </ul>
4277: * @exception SWTException <ul>
4278: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4279: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4280: * </ul>
4281: *
4282: * @see #asyncExec
4283: */
4284: public void timerExec(int milliseconds, Runnable runnable) {
4285: checkDevice();
4286: if (runnable == null)
4287: error(SWT.ERROR_NULL_ARGUMENT);
4288: if (timerList == null)
4289: timerList = new Runnable[4];
4290: if (timerIds == null)
4291: timerIds = new int[4];
4292: int index = 0;
4293: while (index < timerList.length) {
4294: if (timerList[index] == runnable)
4295: break;
4296: index++;
4297: }
4298: if (index != timerList.length) {
4299: int timerId = timerIds[index];
4300: if (milliseconds < 0) {
4301: OS.RemoveEventLoopTimer(timerId);
4302: timerList[index] = null;
4303: timerIds[index] = 0;
4304: } else {
4305: OS.SetEventLoopTimerNextFireTime(timerId,
4306: milliseconds / 1000.0);
4307: }
4308: return;
4309: }
4310: if (milliseconds < 0)
4311: return;
4312: index = 0;
4313: while (index < timerList.length) {
4314: if (timerList[index] == null)
4315: break;
4316: index++;
4317: }
4318: if (index == timerList.length) {
4319: Runnable[] newTimerList = new Runnable[timerList.length + 4];
4320: System.arraycopy(timerList, 0, newTimerList, 0,
4321: timerList.length);
4322: timerList = newTimerList;
4323: int[] newTimerIds = new int[timerIds.length + 4];
4324: System.arraycopy(timerIds, 0, newTimerIds, 0,
4325: timerIds.length);
4326: timerIds = newTimerIds;
4327: }
4328: int[] timerId = new int[1];
4329: int eventLoop = OS.GetCurrentEventLoop();
4330: OS.InstallEventLoopTimer(eventLoop, milliseconds / 1000.0, 0.0,
4331: timerProc, index, timerId);
4332: if (timerId[0] != 0) {
4333: timerIds[index] = timerId[0];
4334: timerList[index] = runnable;
4335: }
4336: }
4337:
4338: int timerProc(int id, int index) {
4339: OS.RemoveEventLoopTimer(id);
4340: if (timerList == null)
4341: return 0;
4342: if (0 <= index && index < timerList.length) {
4343: if (allowTimers) {
4344: Runnable runnable = timerList[index];
4345: timerList[index] = null;
4346: timerIds[index] = 0;
4347: if (runnable != null)
4348: runnable.run();
4349: } else {
4350: timerIds[index] = -1;
4351: wakeThread();
4352: }
4353: }
4354: return 0;
4355: }
4356:
4357: int trackingProc(int browser, int itemID, int property,
4358: int theRect, int startPt, int modifiers) {
4359: Widget widget = getWidget(browser);
4360: if (widget != null)
4361: return widget.trackingProc(browser, itemID, property,
4362: theRect, startPt, modifiers);
4363: return OS.noErr;
4364: }
4365:
4366: /**
4367: * Forces all outstanding paint requests for the display
4368: * to be processed before this method returns.
4369: *
4370: * @exception SWTException <ul>
4371: * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
4372: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4373: * </ul>
4374: *
4375: * @see Control#update()
4376: */
4377: public void update() {
4378: checkDevice();
4379: Shell[] shells = getShells();
4380: for (int i = 0; i < shells.length; i++) {
4381: Shell shell = shells[i];
4382: if (!shell.isDisposed())
4383: shell.update(true);
4384: }
4385: /*
4386: * This code is intentionally commented.
4387: */
4388: // int [] outEvent = new int [1];
4389: // int [] mask = new int [] {OS.kEventClassWindow, OS.kEventWindowUpdate};
4390: // while (OS.ReceiveNextEvent (mask.length / 2, mask, OS.kEventDurationNoWait, true, outEvent) == OS.noErr) {
4391: // /*
4392: // * Bug in the Macintosh. For some reason, when a hierarchy of
4393: // * windows is disposed from kEventWindowClose, despite the fact
4394: // * that DisposeWindow() has been called, the window is not
4395: // * disposed and there are outstandings kEventWindowUpdate events
4396: // * in the event queue. Dispatching these events will cause a
4397: // * segment fault. The fix is to dispatch events to visible
4398: // * windows only.
4399: // */
4400: // int [] theWindow = new int [1];
4401: // OS.GetEventParameter (outEvent [0], OS.kEventParamDirectObject, OS.typeWindowRef, null, 4, null, theWindow);
4402: // if (OS.IsWindowVisible (theWindow [0])) OS.SendEventToEventTarget (outEvent [0], OS.GetEventDispatcherTarget ());
4403: // OS.ReleaseEvent (outEvent [0]);
4404: // }
4405: }
4406:
4407: void updateQuitMenu() {
4408: boolean enabled = true;
4409: Shell[] shells = getShells();
4410: int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL
4411: | SWT.SYSTEM_MODAL;
4412: for (int i = 0; i < shells.length; i++) {
4413: Shell shell = shells[i];
4414: if ((shell.style & mask) != 0 && shell.isVisible()) {
4415: enabled = false;
4416: break;
4417: }
4418: }
4419: if (enabled) {
4420: OS.EnableMenuCommand(0, OS.kHICommandQuit);
4421: } else {
4422: OS.DisableMenuCommand(0, OS.kHICommandQuit);
4423: }
4424: }
4425:
4426: /**
4427: * If the receiver's user-interface thread was <code>sleep</code>ing,
4428: * causes it to be awakened and start running again. Note that this
4429: * method may be called from any thread.
4430: *
4431: * @exception SWTException <ul>
4432: * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
4433: * </ul>
4434: *
4435: * @see #sleep
4436: */
4437: public void wake() {
4438: if (isDisposed())
4439: error(SWT.ERROR_DEVICE_DISPOSED);
4440: if (thread == Thread.currentThread())
4441: return;
4442: wakeThread();
4443: }
4444:
4445: void wakeThread() {
4446: int[] wakeEvent = new int[1];
4447: OS.CreateEvent(0, WAKE_CLASS, WAKE_KIND, 0.0,
4448: OS.kEventAttributeUserEvent, wakeEvent);
4449: OS.PostEventToQueue(queue, wakeEvent[0],
4450: (short) OS.kEventPriorityStandard);
4451: if (wakeEvent[0] != 0)
4452: OS.ReleaseEvent(wakeEvent[0]);
4453: }
4454:
4455: int windowProc(int nextHandler, int theEvent, int userData) {
4456: Widget widget = getWidget(userData);
4457: if (widget == null) {
4458: int[] theWindow = new int[1];
4459: OS.GetEventParameter(theEvent, OS.kEventParamDirectObject,
4460: OS.typeWindowRef, null, 4, null, theWindow);
4461: int[] theRoot = new int[1];
4462: OS.GetRootControl(theWindow[0], theRoot);
4463: widget = getWidget(theRoot[0]);
4464: }
4465: if (widget != null)
4466: return widget.windowProc(nextHandler, theEvent, userData);
4467: return OS.eventNotHandledErr;
4468: }
4469:
4470: }
|