/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.runtime.swt.internal.selector;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
import com.windowtester.runtime.internal.OS;
import com.windowtester.runtime.swt.internal.debug.LogHandler;
public abstract class SystemEventMonitor implements Listener, Runnable {
private boolean posted = false;
private int eventType;
private Widget widget;
/**
* The number of milliseconds to sleep after posting to the OS event queue before
* attempting to post again
*/
public static final int OS_POST_FAILED_SLEEP_INTERVAL = 100;
/**
* The maximum number of attempts to post an event to the OS event queue
*/
public static final int OS_POST_MAX_RETRIES = 30;
public SystemEventMonitor(Widget widget, int eventType){
this.widget = widget;
this.eventType = eventType;
}
public void handleEvent(Event event) {
if(event.type==eventType)
posted = true;
}
public void run() {
int tries = 0;
//cache the Display --- NOTE: fetching it later might not be safe if the Widget is disposed
final Display display = widget.getDisplay();
// add listener to the widget
display.syncExec(new Runnable() {
public void run() {
widget.addListener(eventType, SystemEventMonitor.this);
}
});
try {
posted = false;
// run an execution method
syncExecEvents();
// sleep until posted == true or timeout
while (!posted && ++tries <= SystemEventMonitor.OS_POST_MAX_RETRIES) {
DisplayEventDispatcher.pause(SystemEventMonitor.OS_POST_FAILED_SLEEP_INTERVAL);
}
}finally{
//need to guard against disposed widgets
if (!widget.isDisposed()) {
Runnable runnable = new Runnable() {
public void run() {
if (!widget.isDisposed())
widget.removeListener(eventType,
SystemEventMonitor.this);
}
};
//Linux fix case 38523
if (OS.isLinux())
display.asyncExec(runnable);
else
display.syncExec(runnable);
}
}
// keep heavy method out of the cycle
if (tries > SystemEventMonitor.OS_POST_MAX_RETRIES)
LogHandler.log("Dispatched Event Monitor: max retries (" + SystemEventMonitor.OS_POST_MAX_RETRIES + ") exceeded, giving up on waiting for notification.");
}
public abstract void syncExecEvents();
}