diff --git a/src/java/davmail/ui/tray/SwtAwtEventQueue.java b/src/java/davmail/ui/tray/SwtAwtEventQueue.java new file mode 100644 index 00000000..a9f7a907 --- /dev/null +++ b/src/java/davmail/ui/tray/SwtAwtEventQueue.java @@ -0,0 +1,116 @@ +/* + * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway + * Copyright (C) 2010 Mickael Guessant + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package davmail.ui.tray; + +import org.apache.log4j.Logger; +import org.eclipse.swt.internal.gtk.OS; + +import java.awt.*; +import java.util.EmptyStackException; + +/** + * Custom AWT event queue to trap X errors and avoid application crash. + */ +public class SwtAwtEventQueue extends EventQueue { + protected static final Logger LOGGER = Logger.getLogger(SwtAwtEventQueue.class); + + /** + * Register SWT GDK error handler + */ + public static void registerErrorHandler() { + OS.gdk_error_trap_push(); + } + + /** + * Handle errors caught by SWT GDK error handler + */ + public static void handleGdkError() { + OS.gdk_flush(); + int errorCode = OS.gdk_error_trap_pop(); + if (errorCode != 0) { + LOGGER.debug("Uncaught GDK X error: " + errorCode); + } + } + + /** + * @inheritDoc + */ + public void postEvent(AWTEvent event) { + registerErrorHandler(); + super.postEvent(event); + handleGdkError(); + } + + /** + * @inheritDoc + */ + protected void dispatchEvent(AWTEvent event) { + registerErrorHandler(); + super.dispatchEvent(event); + handleGdkError(); + } + + /** + * @inheritDoc + */ + public AWTEvent getNextEvent() throws InterruptedException { + registerErrorHandler(); + AWTEvent event = super.getNextEvent(); + handleGdkError(); + return event; + } + + /** + * @inheritDoc + */ + public synchronized AWTEvent peekEvent() { + registerErrorHandler(); + AWTEvent event = super.peekEvent(); + handleGdkError(); + return event; + } + + /** + * @inheritDoc + */ + public synchronized AWTEvent peekEvent(int id) { + registerErrorHandler(); + AWTEvent event = super.peekEvent(id); + handleGdkError(); + return event; + } + + /** + * @inheritDoc + */ + protected void pop() throws EmptyStackException { + registerErrorHandler(); + super.pop(); + handleGdkError(); + } + + /** + * @inheritDoc + */ + public synchronized void push(EventQueue newEventQueue) { + registerErrorHandler(); + super.push(newEventQueue); + handleGdkError(); + } +} diff --git a/src/java/davmail/ui/tray/SwtGatewayTray.java b/src/java/davmail/ui/tray/SwtGatewayTray.java index 87e8abb5..8d039641 100644 --- a/src/java/davmail/ui/tray/SwtGatewayTray.java +++ b/src/java/davmail/ui/tray/SwtGatewayTray.java @@ -29,11 +29,14 @@ import org.apache.log4j.lf5.LF5Appender; import org.apache.log4j.lf5.LogLevel; import org.apache.log4j.lf5.viewer.LogBrokerMonitor; import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.DeviceData; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.*; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; import javax.swing.*; +import java.awt.*; import java.io.IOException; import java.net.URL; @@ -174,20 +177,24 @@ public class SwtGatewayTray implements DavGatewayTrayInterface { // workaround for bug when SWT and AWT both try to access Gtk if (lafClassName.indexOf("gtk") > 0) { lafClassName = UIManager.getCrossPlatformLookAndFeelClassName(); + // replace AWT event queue Gdk error handler to avoid application crash + Toolkit.getDefaultToolkit().getSystemEventQueue().push(new SwtAwtEventQueue()); + SwtAwtEventQueue.registerErrorHandler(); + UIManager.setLookAndFeel(lafClassName); + SwtAwtEventQueue.handleGdkError(); + } else { + UIManager.setLookAndFeel(lafClassName); } - UIManager.setLookAndFeel(lafClassName); } catch (Exception e) { DavGatewayTray.warn(new BundleMessage("LOG_UNABLE_TO_SET_LOOK_AND_FEEL")); } + new Thread("SWT") { @Override public void run() { try { - DeviceData data = new DeviceData(); - data.debug = true; - display = new Display(data); - + display = new Display(); shell = new Shell(display); final Tray tray = display.getSystemTray();