javauis/eswt_qt/org.eclipse.swt/Eclipse_SWT_PI/common_j2me/org/eclipse/swt/internal/qt/UIThreadHandOverManager.java
author hgs
Mon, 04 Oct 2010 11:29:25 +0300
changeset 78 71ad690e91f5
permissions -rw-r--r--
v2.2.17_1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
78
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     1
/*******************************************************************************
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     2
 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     3
 * All rights reserved. This program and the accompanying materials
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     4
 * are made available under the terms of the Eclipse Public License v1.0
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     5
 * which accompanies this distribution, and is available at
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     6
 * http://www.eclipse.org/legal/epl-v10.html
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     7
 *
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     8
 * Contributors:
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
     9
 *     Nokia Corporation - initial implementation
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    10
 *******************************************************************************/
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    11
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    12
package org.eclipse.swt.internal.qt;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    13
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    14
import org.eclipse.swt.internal.qt.ApplicationUIListener;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    15
import org.eclipse.swt.internal.qt.midp.UIThreadLauncher;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    16
import org.eclipse.swt.widgets.Display;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    17
import org.eclipse.swt.widgets.Internal_PackageSupport;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    18
import org.eclipse.swt.widgets.Shell;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    19
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    20
/**
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    21
 * A class that manages the UI thread hand-over from the internal UI event 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    22
 * loop to the application. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    23
 */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    24
public final class UIThreadHandOverManager {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    25
    private static Object lock = new Object();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    26
    private static boolean threadWaitingForApplication;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    27
    private static Runnable applicationRunnable;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    28
    private static ApplicationUIListener applicationUIListener;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    29
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    30
    /**
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    31
     * Pass the control of the thread to the application by calling a Runnable
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    32
     * provided by the application. If the Runnable has not yet been provided
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    33
     * then the thread waits until it becomes available, or the wait is aborted
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    34
     * by calling <code>abortWait()</code>. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    35
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    36
    public static void runApplicationUI() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    37
        synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    38
            if(!applicationWaiting()) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    39
                waitForApplication();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    40
            } else {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    41
                // Release the waiting application thread
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    42
                lock.notify();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    43
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    44
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    45
        callback();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    46
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    47
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    48
    /**
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    49
     * If the UI thread is waiting for the application to request the callback
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    50
     * in the UI thread then calling this will abort the wait and make the UI
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    51
     * thread to return back from the <code>runApplicationUI()</code>.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    52
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    53
    public static void abortWait() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    54
        synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    55
            if(threadWaitingForApplication) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    56
                lock.notify();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    57
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    58
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    59
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    60
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    61
    /**
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    62
     * Called indirectly by the application when it's requesting the UI thread. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    63
     * Application will pass a Runnable as a parameter and expects it to get called
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    64
     * in the UI thread. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    65
     * 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    66
     * @param runnable
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    67
     *            The Runnable to call in the UI thread.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    68
     * @return True if obtaining the UI thread was successful and the runnable
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    69
     *         will be called.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    70
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    71
    public static boolean startInUIThread(Runnable runnable) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    72
        // Make sure that the internal event loop is started. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    73
        EventLoop.getInternalDisplay();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    74
        
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    75
        synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    76
            applicationRunnable = runnable;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    77
            if(threadWaitingForApplication) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    78
                lock.notify();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    79
            } else {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    80
                if(!waitForUIThread()) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    81
                    // If the internal UI has not been created then it can't be
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    82
                    // signaled and we can't wait for it. This must mean there's
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    83
                    // no UI thread yet in the process and we can create it here.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    84
                    if(!UIThreadLauncher.startInUIThread(runnable)) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    85
                        return false;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    86
                    }   
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    87
                }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    88
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    89
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    90
        return true;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    91
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    92
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    93
    /**
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    94
     * Sets the listener that will be notified of the state of the UI during its
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    95
     * life-time.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    96
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    97
    public static void setApplicationUIListener(ApplicationUIListener listener) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    98
        synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
    99
            applicationUIListener = listener;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   100
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   101
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   102
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   103
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   104
     * Signal the internal UI loop and wait until it passes the control of the
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   105
     * UI thread into runApplicationUI(). Return false if the internal UI can't
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   106
     * be signaled. 
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   107
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   108
    private static boolean waitForUIThread() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   109
        if(signalUIThreadRequest()) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   110
            try {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   111
                lock.wait();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   112
            } catch(InterruptedException e) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   113
                // Nothing to do
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   114
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   115
            return true;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   116
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   117
        return false;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   118
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   119
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   120
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   121
     * Wait until signaled by the application requesting the callback to its
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   122
     * Runnable, or by abortWait().
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   123
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   124
    private static void waitForApplication() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   125
        threadWaitingForApplication = true;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   126
        try {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   127
            lock.wait();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   128
        } catch(InterruptedException e) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   129
            // Nothing to do
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   130
        } finally {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   131
            threadWaitingForApplication = false;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   132
        }       
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   133
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   134
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   135
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   136
     * Returns true if application has provided the Runnable and is thus waiting
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   137
     * for the callback.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   138
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   139
    private static boolean applicationWaiting() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   140
        return (applicationRunnable != null);
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   141
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   142
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   143
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   144
     * Post an event to the internal Display to request the control of the UI
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   145
     * thread. After this runApplication() should get called in the UI thread.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   146
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   147
    private static boolean signalUIThreadRequest() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   148
        Display internalDisplay = Internal_PackageSupport.getInternalDisplayInstance();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   149
        if(internalDisplay != null) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   150
            if(applicationUIListener != null) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   151
                applicationUIListener.applicationUIThreadRequest();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   152
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   153
            return true;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   154
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   155
        return false;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   156
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   157
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   158
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   159
     * Call back the application's runnable
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   160
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   161
    private static void callback() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   162
        try {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   163
            boolean runnableOk;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   164
            synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   165
                runnableOk = (applicationRunnable != null);
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   166
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   167
            if(runnableOk) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   168
                flushInternals();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   169
                applicationRunnable.run();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   170
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   171
        } finally {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   172
            synchronized(lock) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   173
                applicationRunnable = null;
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   174
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   175
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   176
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   177
    
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   178
    /*
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   179
     * Clear any events or other items possibly left over by any previous usage
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   180
     * of the UI resources. There must not be anything that can interfere with
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   181
     * the application. It must appear as the application starts with an
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   182
     * uninitialized UI.
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   183
     */
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   184
    private static void flushInternals() {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   185
        Display internalDisplay = Internal_PackageSupport.getInternalDisplayInstance();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   186
        
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   187
        // Dispose all widgets
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   188
        Shell[] shells = internalDisplay.getShells();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   189
        for(int i = 0; i < shells.length; ++i) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   190
            if(shells[i] != null && !shells[i].isDisposed()) {
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   191
                shells[i].dispose();
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   192
            }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   193
        }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   194
        
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   195
        // Flush the event queue
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   196
        while(internalDisplay.readAndDispatch()) {}
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   197
    }
71ad690e91f5 v2.2.17_1
hgs
parents:
diff changeset
   198
}