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