Merging releases/1.6@4025:4130 into trunk; supercedes trunk:c4118.

svn merge -c-4118 https://google-web-toolkit.googlecode.com/svn/trunk .
svn merge --accept postpone -r4025:4130 https://google-web-toolkit.googlecode.com/svn/releases/1.6 .



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@4142 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/CompileArgProcessor.java b/dev/core/src/com/google/gwt/dev/CompileArgProcessor.java
index 14047e5..fdc5e99 100644
--- a/dev/core/src/com/google/gwt/dev/CompileArgProcessor.java
+++ b/dev/core/src/com/google/gwt/dev/CompileArgProcessor.java
@@ -18,14 +18,14 @@
 import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
 import com.google.gwt.dev.util.arg.ArgHandlerModuleName;
 import com.google.gwt.dev.util.arg.ArgHandlerTreeLoggerFlag;
-import com.google.gwt.dev.util.arg.ArgHandlerWorkDir;
+import com.google.gwt.dev.util.arg.ArgHandlerWorkDirRequired;
 import com.google.gwt.util.tools.ToolBase;
 
 abstract class CompileArgProcessor extends ToolBase {
   public CompileArgProcessor(CompileTaskOptions options) {
     registerHandler(new ArgHandlerLogLevel(options));
     registerHandler(new ArgHandlerTreeLoggerFlag(options));
-    registerHandler(new ArgHandlerWorkDir(options));
+    registerHandler(new ArgHandlerWorkDirRequired(options));
     registerHandler(new ArgHandlerModuleName(options));
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/CompilePerms.java b/dev/core/src/com/google/gwt/dev/CompilePerms.java
index 53180f9..55c5999 100644
--- a/dev/core/src/com/google/gwt/dev/CompilePerms.java
+++ b/dev/core/src/com/google/gwt/dev/CompilePerms.java
@@ -180,10 +180,6 @@
      */
     final CompilePermsOptions options = new CompilePermsOptionsImpl();
     if (new ArgProcessor(options).processArgs(args)) {
-      if (options.getWorkDir() == null) {
-        System.err.println("The -workDir is required for the CompilePerms phase.");
-        System.exit(1);
-      }
       CompileTask task = new CompileTask() {
         public boolean run(TreeLogger logger) throws UnableToCompleteException {
           return new CompilePerms(options).run(logger);
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 71c96a0..3d7b06d 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -21,11 +21,12 @@
 import com.google.gwt.dev.CompileTaskRunner.CompileTask;
 import com.google.gwt.dev.Link.LinkOptionsImpl;
 import com.google.gwt.dev.Precompile.PrecompileOptionsImpl;
-import com.google.gwt.dev.cfg.ModuleDef;
 import com.google.gwt.dev.util.PerfLogger;
 import com.google.gwt.dev.util.Util;
 import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
 import com.google.gwt.dev.util.arg.ArgHandlerOutDir;
+import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
+import com.google.gwt.util.tools.Utility;
 
 import java.io.File;
 import java.io.IOException;
@@ -38,6 +39,10 @@
   static final class ArgProcessor extends Precompile.ArgProcessor {
     public ArgProcessor(CompilerOptions options) {
       super(options);
+
+      // Override the ArgHandlerWorkDirRequired in the super class.
+      registerHandler(new ArgHandlerWorkDirOptional(options));
+
       registerHandler(new ArgHandlerExtraDir(options));
       registerHandler(new ArgHandlerOutDir(options));
     }
@@ -69,10 +74,6 @@
       return linkOptions.getExtraDir();
     }
 
-    public File getLegacyExtraDir(TreeLogger logger, ModuleDef module) {
-      return linkOptions.getLegacyExtraDir(logger, module);
-    }
-
     public File getOutDir() {
       return linkOptions.getOutDir();
     }
@@ -93,34 +94,19 @@
      * shutdown AWT related threads, since the contract for their termination is
      * still implementation-dependent.
      */
-    boolean deleteWorkDir = false;
     final CompilerOptions options = new GWTCompilerOptionsImpl();
     if (new ArgProcessor(options).processArgs(args)) {
-      try {
-        deleteWorkDir = options.ensureWorkDir();
-        System.err.println("deleteWorkDir: " + deleteWorkDir);
-      } catch (IOException ex) {
-        System.err.println("Couldn't create new workDir: " + ex.getMessage());
-        System.err.println("Either fix the error, or supply an explicit -workDir flag.");
-        System.exit(1);
-      }
       CompileTask task = new CompileTask() {
         public boolean run(TreeLogger logger) throws UnableToCompleteException {
           return new GWTCompiler(options).run(logger);
         }
       };
       if (CompileTaskRunner.runWithAppropriateLogger(options, task)) {
-        if (deleteWorkDir) {
-          Util.recursiveDelete(options.getWorkDir(), false);
-        }
         // Exit w/ success code.
         System.exit(0);
       }
     }
     // Exit w/ non-success code.
-    if (deleteWorkDir) {
-      Util.recursiveDelete(options.getWorkDir(), false);
-    }
     System.exit(1);
   }
 
@@ -137,23 +123,39 @@
       PerfLogger.start("compile");
       logger = logger.branch(TreeLogger.INFO, "Compiling module "
           + options.getModuleName());
-      if (new Precompile(options).run(logger)) {
-        /*
-         * TODO: use the in-memory result of Precompile to run CompilePerms
-         * instead of serializing through the file system.
-         */
-        CompilePermsOptionsImpl permsOptions = new CompilePermsOptionsImpl();
-        permsOptions.copyFrom(options);
-        if (new CompilePerms(permsOptions).run(logger)) {
-          if (new Link(options).run(logger)) {
-            logger.log(TreeLogger.INFO, "Compilation succeeded");
-            PerfLogger.end();
-            return true;
+
+      boolean tempWorkDir = false;
+      try {
+        if (options.getWorkDir() == null) {
+          options.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc"));
+          tempWorkDir = true;
+        }
+
+        if (new Precompile(options).run(logger)) {
+          /*
+           * TODO: use the in-memory result of Precompile to run CompilePerms
+           * instead of serializing through the file system.
+           */
+          CompilePermsOptionsImpl permsOptions = new CompilePermsOptionsImpl();
+          permsOptions.copyFrom(options);
+          if (new CompilePerms(permsOptions).run(logger)) {
+            if (new Link(options).run(logger)) {
+              logger.log(TreeLogger.INFO, "Compilation succeeded");
+              return true;
+            }
           }
         }
+
+        logger.log(TreeLogger.ERROR, "Compilation failed");
+      } catch (IOException e) {
+        logger.log(TreeLogger.ERROR,
+            "Unable to create compiler work directory", e);
+      } finally {
+        PerfLogger.end();
+        if (tempWorkDir) {
+          Util.recursiveDelete(options.getWorkDir(), false);
+        }
       }
-      logger.log(TreeLogger.ERROR, "Compilation failed");
-      PerfLogger.end();
       return false;
     }
   }
diff --git a/dev/core/src/com/google/gwt/dev/GWTShell.java b/dev/core/src/com/google/gwt/dev/GWTShell.java
index 460ec3f..48a5d17 100644
--- a/dev/core/src/com/google/gwt/dev/GWTShell.java
+++ b/dev/core/src/com/google/gwt/dev/GWTShell.java
@@ -43,7 +43,7 @@
 import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
 import com.google.gwt.dev.util.arg.ArgHandlerOutDir;
 import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
-import com.google.gwt.dev.util.arg.ArgHandlerWorkDir;
+import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
 import com.google.gwt.dev.util.log.AbstractTreeLogger;
 import com.google.gwt.util.tools.ArgHandlerExtra;
 import com.google.gwt.util.tools.ArgHandlerFlag;
@@ -439,7 +439,7 @@
     registerHandler(new ArgHandlerLogLevel(options));
 
     registerHandler(new ArgHandlerGenDir(options));
-    registerHandler(new ArgHandlerWorkDir(options));
+    registerHandler(new ArgHandlerWorkDirOptional(options));
 
     if (!noURLs) {
       registerHandler(new ArgHandlerStartupURLsExtra());
diff --git a/dev/core/src/com/google/gwt/dev/Link.java b/dev/core/src/com/google/gwt/dev/Link.java
index 182d44b..d476bbc 100644
--- a/dev/core/src/com/google/gwt/dev/Link.java
+++ b/dev/core/src/com/google/gwt/dev/Link.java
@@ -34,9 +34,7 @@
 
 import java.io.File;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * Performs the last phase of compilation, merging the compilation outputs.
@@ -47,20 +45,6 @@
    */
   public interface LinkOptions extends CompileTaskOptions, OptionExtraDir,
       OptionOutDir {
-    
-    /**
-     * A born-deprecated method to enact "legacy" -aux support if -extra is not
-     * specified.  This method will <i>either</i> return the same as 
-     * {@link OptionExtraDir#getExtraDir()}, if -extra is specified, <i>or</i>
-     * return the legacy equivalent <i>outputDir</i>/<i>ModuleName</i>-aux.  In
-     * this second case, it will also emit a warning to direct people to -extra,
-     * and flag the fact that non-deployable bits are in what should be the 
-     * deployable output directory. 
-     *
-     * @return pathname for extra files
-     */
-    @Deprecated
-    File getLegacyExtraDir(TreeLogger logger, ModuleDef module);
   }
 
   static class ArgProcessor extends CompileArgProcessor {
@@ -84,7 +68,6 @@
 
     private File extraDir;
     private File outDir;
-    private Set<File> alreadyWarned = new HashSet<File>();
 
     public LinkOptionsImpl() {
     }
@@ -103,26 +86,6 @@
       return extraDir;
     }
 
-    public File getLegacyExtraDir(TreeLogger logger, ModuleDef module) {
-      // safety that we need this at all...
-      if (extraDir != null) {
-        return extraDir;
-      }
-      // okay, figure the old location, by module...
-      String deployDir = module.getDeployTo();
-      File moduleExtraDir = new File(outDir, 
-          deployDir.substring(0, deployDir.length() - 1) + "-aux");
-      // and warn the user about it, but only if it'd be new news.
-      if (!alreadyWarned.contains(moduleExtraDir)) {
-        logger.log(TreeLogger.WARN, "Non-deployed artificats will be in " 
-            + moduleExtraDir.getPath()
-            + ", inside deployable output directory " + outDir.getPath()
-            + ".  Use -extra to relocate the auxilliary files.");
-        alreadyWarned.add(moduleExtraDir);
-      }
-      return moduleExtraDir;
-    }
-
     public File getOutDir() {
       return outDir;
     }
@@ -144,6 +107,16 @@
     return doLink(logger, linkerContext, precompilation, jsFiles);
   }
 
+  public static void link(TreeLogger logger, ModuleDef module,
+      Precompilation precompilation, File[] jsFiles, File outDir, File extrasDir)
+      throws UnableToCompleteException {
+    StandardLinkerContext linkerContext = new StandardLinkerContext(logger,
+        module, precompilation.getUnifiedAst().getOptions());
+    ArtifactSet artifacts = doLink(logger, linkerContext, precompilation,
+        jsFiles);
+    doProduceOutput(logger, artifacts, linkerContext, module, outDir, extrasDir);
+  }
+
   public static void main(String[] args) {
     /*
      * NOTE: main always exits with a call to System.exit to terminate any
@@ -153,10 +126,6 @@
      */
     final LinkOptions options = new LinkOptionsImpl();
     if (new ArgProcessor(options).processArgs(args)) {
-      if (options.getWorkDir() == null) {
-        System.err.println("The -workDir is required for the Link phase.");
-        System.exit(1);
-      }
       CompileTask task = new CompileTask() {
         public boolean run(TreeLogger logger) throws UnableToCompleteException {
           return new Link(options).run(logger);
@@ -188,6 +157,48 @@
     return linkerContext.invokeLink(logger);
   }
 
+  private static void doProduceOutput(TreeLogger logger, ArtifactSet artifacts,
+      StandardLinkerContext linkerContext, ModuleDef module, File outDir,
+      File extraDir) throws UnableToCompleteException {
+    boolean warnOnExtra = false;
+    File moduleExtraDir;
+    if (extraDir == null) {
+      /*
+       * Legacy behavior for backwards compatibility; if the extra directory is
+       * not specified, make it a sibling to the deploy directory, with -aux.
+       */
+      String deployDir = module.getDeployTo();
+      deployDir = deployDir.substring(0, deployDir.length() - 1) + "-aux";
+      moduleExtraDir = new File(outDir, deployDir);
+
+      /*
+       * Only warn when we create a new legacy extra dir.
+       */
+      warnOnExtra = !moduleExtraDir.exists();
+    } else {
+      moduleExtraDir = new File(extraDir, module.getDeployTo());
+    }
+
+    File moduleOutDir = new File(outDir, module.getDeployTo());
+    Util.recursiveDelete(moduleOutDir, true);
+    Util.recursiveDelete(moduleExtraDir, true);
+    linkerContext.produceOutputDirectory(logger, artifacts, moduleOutDir,
+        moduleExtraDir);
+
+    /*
+     * Warn on legacy extra directory, but only if: 1) It didn't exist before.
+     * 2) We just created it.
+     */
+    if (warnOnExtra && moduleExtraDir.exists()) {
+      logger.log(
+          TreeLogger.WARN,
+          "Non-public artificats were produced in '"
+              + moduleExtraDir.getAbsolutePath()
+              + "' within the public output folder; use -extra to specify an alternate location");
+    }
+    logger.log(TreeLogger.INFO, "Link succeeded");
+  }
+
   private static void finishPermuation(TreeLogger logger, Permutation perm,
       File jsFile, StandardLinkerContext linkerContext)
       throws UnableToCompleteException {
@@ -215,16 +226,6 @@
 
   private ModuleDef module;
 
-  /**
-   * This is the output directory for private files.
-   */
-  private File moduleExtraDir;
-
-  /**
-   * This is the output directory for public files.
-   */
-  private File moduleOutDir;
-
   private final LinkOptionsImpl options;
 
   public Link(LinkOptions options) {
@@ -232,7 +233,8 @@
   }
 
   public boolean run(TreeLogger logger) throws UnableToCompleteException {
-    init(logger);
+    module = ModuleDefLoader.loadFromClassPath(logger, options.getModuleName());
+
     File precompilationFile = new File(options.getCompilerWorkDir(),
         Precompile.PRECOMPILATION_FILENAME);
     if (!precompilationFile.exists()) {
@@ -270,26 +272,9 @@
         module, precompilation.getUnifiedAst().getOptions());
     ArtifactSet artifacts = doLink(branch, linkerContext, precompilation,
         jsFiles);
-    if (artifacts != null) {
-      linkerContext.produceOutputDirectory(branch, artifacts, moduleOutDir,
-          moduleExtraDir);
-      branch.log(TreeLogger.INFO, "Link succeeded");
-      return true;
-    }
-    branch.log(TreeLogger.ERROR, "Link failed");
-    return false;
-  }
 
-  private void init(TreeLogger logger) throws UnableToCompleteException {
-    module = ModuleDefLoader.loadFromClassPath(logger, options.getModuleName());
-    moduleOutDir = new File(options.getOutDir(), module.getDeployTo());
-    Util.recursiveDelete(moduleOutDir, true);
-    if (options.getExtraDir() == null) {
-      // legacy location
-      moduleExtraDir = options.getLegacyExtraDir(logger, module);
-    } else {
-      moduleExtraDir = new File(options.getExtraDir(), module.getDeployTo());
-    }
-    Util.recursiveDelete(moduleExtraDir, false);
+    doProduceOutput(branch, artifacts, linkerContext, module,
+        options.getOutDir(), options.getExtraDir());
+    return true;
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/PermutationCompiler.java b/dev/core/src/com/google/gwt/dev/PermutationCompiler.java
index 4922b76..5ae54b4 100644
--- a/dev/core/src/com/google/gwt/dev/PermutationCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/PermutationCompiler.java
@@ -19,9 +19,8 @@
 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.dev.cfg.BindingProperty;
 import com.google.gwt.dev.cfg.StaticPropertyOracle;
-import com.google.gwt.dev.jjs.UnifiedAst;
 import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
-import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.UnifiedAst;
 import com.google.gwt.dev.util.PerfLogger;
 
 import java.util.concurrent.BlockingQueue;
@@ -191,14 +190,6 @@
         });
       }
 
-      if (!hasEnoughMemory()) {
-        /*
-         * Not enough memory to run, but if there are multiple threads, we can
-         * try again with fewer threads.
-         */
-        tryToExitNonFinalThread(outOfMemoryRetryAction);
-      }
-
       boolean definitelyFinalThread = (threadCount.get() == 1);
       try {
         String[] result = currentTask.call();
@@ -247,26 +238,6 @@
     }
 
     /**
-     * Returns <code>true</code> if there is enough estimated memory to run
-     * another permutation, or if this is the last live worker thread and we
-     * have no choice.
-     */
-    private boolean hasEnoughMemory() {
-      if (threadCount.get() == 1) {
-        // I'm the last thread, so I have to at least try.
-        return true;
-      }
-
-      if (astMemoryUsage >= getPotentialFreeMemory()) {
-        return true;
-      }
-
-      // Best effort memory reclaim.
-      System.gc();
-      return astMemoryUsage < getPotentialFreeMemory();
-    }
-
-    /**
      * Exits this thread if and only if it's not the last running thread,
      * performing the specified action before terminating.
      * 
@@ -294,21 +265,6 @@
   private static final Result FINISHED_RESULT = new Result(null, -1) {
   };
 
-  private static long getPotentialFreeMemory() {
-    long used = Runtime.getRuntime().totalMemory()
-        - Runtime.getRuntime().freeMemory();
-    assert (used > 0);
-    long potentialFree = Runtime.getRuntime().maxMemory() - used;
-    assert (potentialFree >= 0);
-    return potentialFree;
-  }
-
-  /**
-   * Holds an estimate of how many bytes of memory a new concurrent compilation
-   * will consume.
-   */
-  protected final long astMemoryUsage;
-
   /**
    * A queue of results being sent from worker threads to the main thread.
    */
@@ -329,7 +285,6 @@
   public PermutationCompiler(TreeLogger logger, UnifiedAst unifiedAst,
       Permutation[] perms, int[] permsToRun) {
     this.logger = logger;
-    this.astMemoryUsage = unifiedAst.getAstMemoryUsage();
     for (int permToRun : permsToRun) {
       tasks.add(new PermutationTask(logger, unifiedAst, perms[permToRun],
           permToRun));
@@ -387,52 +342,10 @@
     result = Math.min(Runtime.getRuntime().availableProcessors(), result);
 
     /*
-     * Allow user-defined override as an escape valve.
+     * User-defined value caps.
      */
-    result = Math.min(result, Integer.getInteger("gwt.jjs.maxThreads", result));
+    result = Math.min(result, Integer.getInteger("gwt.jjs.maxThreads", 1));
 
-    if (result == 1) {
-      return 1;
-    }
-
-    // More than one thread would definitely be faster at this point.
-
-    if (JProgram.isTracingEnabled()) {
-      logger.log(TreeLogger.INFO,
-          "Parallel compilation disabled due to gwt.jjs.traceMethods being enabled");
-      return 1;
-    }
-
-    int desiredThreads = result;
-
-    /*
-     * Need to do some memory estimation to figure out how many concurrent
-     * threads we can safely run.
-     */
-    long potentialFreeMemory = getPotentialFreeMemory();
-    int extraMemUsageThreads = (int) (potentialFreeMemory / astMemoryUsage);
-    logger.log(TreeLogger.TRACE,
-        "Extra threads constrained by estimated memory usage: "
-            + extraMemUsageThreads + " = " + potentialFreeMemory + " / "
-            + astMemoryUsage);
-    int memUsageThreads = extraMemUsageThreads + 1;
-
-    if (memUsageThreads < desiredThreads) {
-      long currentMaxMemory = Runtime.getRuntime().maxMemory();
-      // Convert to megabytes.
-      currentMaxMemory /= 1024 * 1024;
-
-      long suggestedMaxMemory = currentMaxMemory * 2;
-
-      logger.log(TreeLogger.WARN, desiredThreads
-          + " threads could be run concurrently, but only " + memUsageThreads
-          + " threads will be run due to limited memory; "
-          + "increasing the amount of memory by using the -Xmx flag "
-          + "at startup (java -Xmx" + suggestedMaxMemory
-          + "M ...) may result in faster compiles");
-    }
-
-    result = Math.min(memUsageThreads, desiredThreads);
     return result;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java
index 6be2c2f..a7e8bf0 100644
--- a/dev/core/src/com/google/gwt/dev/Precompile.java
+++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -47,10 +47,8 @@
 import com.google.gwt.dev.util.arg.ArgHandlerValidateOnlyFlag;
 import com.google.gwt.dev.util.arg.OptionGenDir;
 import com.google.gwt.dev.util.arg.OptionValidateOnly;
-import com.google.gwt.util.tools.Utility;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.SortedMap;
@@ -68,7 +66,6 @@
    */
   public interface PrecompileOptions extends JJSOptions, CompileTaskOptions,
       OptionGenDir, OptionValidateOnly {
-    boolean ensureWorkDir() throws IOException;
   }
 
   static class ArgProcessor extends CompileArgProcessor {
@@ -109,24 +106,6 @@
       setValidateOnly(other.isValidateOnly());
     }
 
-    /**
-     * Checks that the workDir is set, or creates one if not using a temporary
-     * name.
-     * @returns true if intervention was required, i.e. we created a new directory
-     */
-    public boolean ensureWorkDir() throws IOException {
-      File workDir = super.getWorkDir();
-      if (workDir == null) {
-        // user didn't give us one, make one in a random location
-        workDir = Utility.makeTemporaryDirectory(null, "work-");
-        System.err.println("Created new work directory at " + workDir.getAbsolutePath()
-            + ", which will be removed on exit.  (Use -workDir DIRNAME to retain.)");
-        super.setWorkDir(workDir);
-        return true;
-      }
-      return false;
-    }
-
     public File getGenDir() {
       return genDir;
     }
@@ -247,10 +226,6 @@
      */
     final PrecompileOptions options = new PrecompileOptionsImpl();
     if (new ArgProcessor(options).processArgs(args)) {
-      if (options.getWorkDir() == null) {
-        System.err.println("The -workDir is required for the Precompile phase.");
-        System.exit(1);
-      }
       CompileTask task = new CompileTask() {
         public boolean run(TreeLogger logger) throws UnableToCompleteException {
           return new Precompile(options).run(logger);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index 0ab97c9..2d8d57a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -287,8 +287,6 @@
     JsProgram jsProgram = new JsProgram();
 
     try {
-      long usedMemoryBefore = singlePermutation ? 0 : getUsedMemory();
-
       /*
        * (1) Build a flattened map of TypeDeclarations => JType. The resulting
        * map contains entries for all reference types. BuildTypeMap also parses
@@ -308,10 +306,6 @@
       GenerateJavaAST.exec(allTypeDeclarations, typeMap, jprogram, jsProgram,
           options.isEnableAssertions());
 
-      long usedMemoryAfter = singlePermutation ? 0 : getUsedMemory();
-      long memoryDelta = usedMemoryAfter - usedMemoryBefore;
-      long astMemoryUsage = (long) (memoryDelta * 1.5);
-
       // GenerateJavaAST can uncover semantic JSNI errors; report & abort
       checkForErrors(logger, goldenCuds, true);
 
@@ -366,7 +360,7 @@
       RecordRebinds.exec(jprogram, rebindRequests);
 
       return new UnifiedAst(options, new AST(jprogram, jsProgram),
-          singlePermutation, astMemoryUsage, rebindRequests);
+          singlePermutation, rebindRequests);
     } catch (Throwable e) {
       throw logAndTranslateException(logger, e);
     } finally {
@@ -641,14 +635,6 @@
     return null;
   }
 
-  private static long getUsedMemory() {
-    System.gc();
-    long used = Runtime.getRuntime().totalMemory()
-        - Runtime.getRuntime().freeMemory();
-    assert (used > 0);
-    return used;
-  }
-
   private static UnableToCompleteException logAndTranslateException(
       TreeLogger logger, Throwable e) {
     if (e instanceof UnableToCompleteException) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java b/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
index a5e85b0..6dfc5fe 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
@@ -57,10 +57,42 @@
     }
   }
 
-  /**
-   * Estimated AST memory usage.
-   */
-  private long astMemoryUsage;
+  private static AST deserializeAst(byte[] serializedAst) {
+    try {
+      PerfLogger.start("deserialize");
+      ByteArrayInputStream bais = new ByteArrayInputStream(serializedAst);
+      ObjectInputStream is;
+      is = new ObjectInputStream(bais);
+      JProgram jprogram = (JProgram) is.readObject();
+      JsProgram jsProgram = (JsProgram) is.readObject();
+      return new AST(jprogram, jsProgram);
+    } catch (IOException e) {
+      throw new RuntimeException(
+          "Should be impossible for memory based streams", e);
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(
+          "Should be impossible when deserializing in process", e);
+    } finally {
+      PerfLogger.end();
+    }
+  }
+
+  private static byte[] serializeAst(AST ast) {
+    try {
+      PerfLogger.start("serialize");
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ObjectOutputStream os = new ObjectOutputStream(baos);
+      os.writeObject(ast.getJProgram());
+      os.writeObject(ast.getJsProgram());
+      os.close();
+      return baos.toByteArray();
+    } catch (IOException e) {
+      throw new RuntimeException(
+          "Should be impossible for memory based streams", e);
+    } finally {
+      PerfLogger.end();
+    }
+  }
 
   /**
    * The original AST; nulled out once consumed (by the first call to
@@ -84,31 +116,17 @@
   private final SortedSet<String> rebindRequests;
 
   /**
-   * The serialized form of savedAst.
+   * The serialized AST.
    */
   private byte[] serializedAst;
 
-  /**
-   * If <code>true</code>, only one permutation will be run, so we don't need
-   * to serialize our AST (unless this whole object is about to be serialized).
-   */
-  private transient boolean singlePermutation;
-
   public UnifiedAst(JJSOptions options, AST initialAst,
-      boolean singlePermutation, long astMemoryUsage, Set<String> rebindRequests) {
+      boolean singlePermutation, Set<String> rebindRequests) {
     this.options = new JJSOptionsImpl(options);
     this.initialAst = initialAst;
-    this.singlePermutation = singlePermutation;
-    this.astMemoryUsage = astMemoryUsage;
     this.rebindRequests = Collections.unmodifiableSortedSet(new TreeSet<String>(
         rebindRequests));
-  }
-
-  /**
-   * Returns a rough estimate of how much memory an AST will take up.
-   */
-  public long getAstMemoryUsage() {
-    return astMemoryUsage;
+    this.serializedAst = singlePermutation ? null : serializeAst(initialAst);
   }
 
   /**
@@ -128,42 +146,19 @@
   AST getFreshAst() {
     synchronized (myLockObject) {
       if (initialAst != null) {
-        if (!singlePermutation && serializedAst == null) {
-          // Must preserve a serialized copy for future calls.
-          serializeAst();
-        }
         AST result = initialAst;
         initialAst = null;
         return result;
       } else {
         if (serializedAst == null) {
-          throw new IllegalStateException("No serialized AST was cached.");
+          throw new IllegalStateException(
+              "No serialized AST was cached and AST was already consumed.");
         }
-        return deserializeAst();
+        return deserializeAst(serializedAst);
       }
     }
   }
 
-  private AST deserializeAst() {
-    try {
-      PerfLogger.start("deserialize");
-      ByteArrayInputStream bais = new ByteArrayInputStream(serializedAst);
-      ObjectInputStream is;
-      is = new ObjectInputStream(bais);
-      JProgram jprogram = (JProgram) is.readObject();
-      JsProgram jsProgram = (JsProgram) is.readObject();
-      return new AST(jprogram, jsProgram);
-    } catch (IOException e) {
-      throw new RuntimeException(
-          "Should be impossible for memory based streams", e);
-    } catch (ClassNotFoundException e) {
-      throw new RuntimeException(
-          "Should be impossible when deserializing in process", e);
-    } finally {
-      PerfLogger.end();
-    }
-  }
-
   /**
    * Re-initialize lock object.
    */
@@ -172,35 +167,17 @@
     return this;
   }
 
-  private void serializeAst() {
-    try {
-      assert (initialAst != null);
-      assert (serializedAst == null);
-      PerfLogger.start("serialize");
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      ObjectOutputStream os = new ObjectOutputStream(baos);
-      os.writeObject(initialAst.getJProgram());
-      os.writeObject(initialAst.getJsProgram());
-      os.close();
-      serializedAst = baos.toByteArray();
-
-      // Very rough heuristic.
-      astMemoryUsage = Math.max(astMemoryUsage, serializedAst.length * 4);
-    } catch (IOException e) {
-      throw new RuntimeException(
-          "Should be impossible for memory based streams", e);
-    } finally {
-      PerfLogger.end();
-    }
-  }
-
   /**
    * Force byte serialization of AST before writing.
    */
   private Object writeReplace() {
-    synchronized (myLockObject) {
-      if (serializedAst == null) {
-        serializeAst();
+    if (serializedAst == null) {
+      synchronized (myLockObject) {
+        if (initialAst == null) {
+          throw new IllegalStateException(
+              "No serialized AST was cached and AST was already consumed.");
+        }
+        serializedAst = serializeAst(initialAst);
       }
     }
     return this;
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
index 166ac03..1fc2d9b 100644
--- a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
+++ b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
@@ -174,11 +174,8 @@
     // Tell Tomcat its base directory so that it won't complain.
     //
     String catBase = System.getProperty("catalina.base");
-    if (catBase == null || !(new File(catBase)).exists()) {
-      if (catBase == null) {
-        catBase = topWorkDir.getAbsolutePath() + "tomcat"; 
-      }
-      generateDefaultCatalinaBase(logger, new File(catBase));
+    if (catBase == null) {
+      catBase = generateDefaultCatalinaBase(logger, topWorkDir);
       System.setProperty("catalina.base", catBase);
     }
 
@@ -331,10 +328,10 @@
    * Extracts a valid catalina base instance from the classpath. Does not
    * overwrite any existing files.
    */
-  private void generateDefaultCatalinaBase(TreeLogger logger, File catBase) {
+  private String generateDefaultCatalinaBase(TreeLogger logger, File workDir) {
     logger = logger.branch(
         TreeLogger.TRACE,
-        "Property 'catalina.base' not specified or not present; checking for a standard catalina base image instead",
+        "Property 'catalina.base' not specified; checking for a standard catalina base image instead",
         null);
 
     // Recursively copies out files and directories
@@ -349,6 +346,7 @@
       caught = e;
     }
 
+    File catBase = new File(workDir, "tomcat");
     if (resourceMap == null || resourceMap.isEmpty()) {
       logger.log(TreeLogger.WARN, "Could not find " + tomcatEtcDir, caught);
     } else {
@@ -356,6 +354,8 @@
         copyFileNoOverwrite(logger, entry.getKey(), entry.getValue(), catBase);
       }
     }
+
+    return catBase.getAbsolutePath();
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java
index b45b807..394c376 100644
--- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerExtraDir.java
@@ -20,8 +20,9 @@
 import java.io.File;
 
 /**
- * Argument handler for processing the extra directory option.  If not specified,
- * legacy behavior is to write private artifacts to ${outdir}/Module-aux.
+ * Argument handler for processing the extra directory option. If not specified,
+ * legacy behavior is to write private artifacts to
+ * <code>${outdir}/fully.qualified.Module-aux</code>.
  */
 public final class ArgHandlerExtraDir extends ArgHandlerDir {
 
@@ -43,4 +44,4 @@
   public void setDir(File dir) {
     option.setExtraDir(dir);
   }
-}
\ No newline at end of file
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirOptional.java
similarity index 69%
rename from dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java
rename to dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirOptional.java
index 7c3ef77..fc923fd 100644
--- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirOptional.java
@@ -20,23 +20,18 @@
 import java.io.File;
 
 /**
- * Argument handler for processing the output directory flag.  If not specified,
- * the GWTCompiler and Precompile classes will create one (under 
- * ${java.io.tmpdir}/GWT_TMP_DIR) with a guaranteed-unique name; the other tasks
- * will fail.
+ * Argument handler for processing an optional working directory.
  */
-public final class ArgHandlerWorkDir extends ArgHandlerDir {
-
-  public static final String GWT_TMP_DIR = "gwt-tmp";
+public final class ArgHandlerWorkDirOptional extends ArgHandlerDir {
 
   private final OptionWorkDir option;
 
-  public ArgHandlerWorkDir(OptionWorkDir option) {
+  public ArgHandlerWorkDirOptional(OptionWorkDir option) {
     this.option = option;
   }
 
   public String getPurpose() {
-    return "The compiler work directory (must be writeable; defaults to random name under system temp dir)";
+    return "The compiler work directory (must be writeable; defaults to a system temp dir)";
   }
 
   public String getTag() {
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirRequired.java
similarity index 64%
copy from dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java
copy to dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirRequired.java
index 7c3ef77..6413f35 100644
--- a/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDir.java
+++ b/dev/core/src/com/google/gwt/dev/util/arg/ArgHandlerWorkDirRequired.java
@@ -20,23 +20,18 @@
 import java.io.File;
 
 /**
- * Argument handler for processing the output directory flag.  If not specified,
- * the GWTCompiler and Precompile classes will create one (under 
- * ${java.io.tmpdir}/GWT_TMP_DIR) with a guaranteed-unique name; the other tasks
- * will fail.
+ * Argument handler for processing a required work directory.
  */
-public final class ArgHandlerWorkDir extends ArgHandlerDir {
-
-  public static final String GWT_TMP_DIR = "gwt-tmp";
+public final class ArgHandlerWorkDirRequired extends ArgHandlerDir {
 
   private final OptionWorkDir option;
 
-  public ArgHandlerWorkDir(OptionWorkDir option) {
+  public ArgHandlerWorkDirRequired(OptionWorkDir option) {
     this.option = option;
   }
 
   public String getPurpose() {
-    return "The compiler work directory (must be writeable; defaults to random name under system temp dir)";
+    return "The compiler work directory (must be writeable)";
   }
 
   public String getTag() {
@@ -44,6 +39,11 @@
   }
 
   @Override
+  public boolean isRequired() {
+    return true;
+  }
+
+  @Override
   public void setDir(File dir) {
     option.setWorkDir(dir);
   }
diff --git a/dev/core/src/com/google/gwt/util/tools/ToolBase.java b/dev/core/src/com/google/gwt/util/tools/ToolBase.java
index 5666aa5..b965bd3 100644
--- a/dev/core/src/com/google/gwt/util/tools/ToolBase.java
+++ b/dev/core/src/com/google/gwt/util/tools/ToolBase.java
@@ -19,12 +19,10 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 
 /**
  * A base class for a GWT related command-line application. To use this:
@@ -61,13 +59,10 @@
     System.setProperty("swt.library.path", installPath + '/');
   }
 
-  // Use a tree map to sort the order.
-  //
-  private final Map<String, ArgHandler> argHandlers = new TreeMap<String, ArgHandler>();
-
-  // Use a list to preserve the declared order for help printing.
-  //
-  private final List<ArgHandler> orderedArgHandlers = new ArrayList<ArgHandler>();
+  /**
+   * Use a linked hash map to preserve the declaration order.
+   */
+  private final Map<String, ArgHandler> argHandlers = new LinkedHashMap<String, ArgHandler>();
 
   protected String getDescription() {
     return null;
@@ -82,7 +77,7 @@
 
     ArgHandler nullHandler = null;
     int widest = 0;
-    for (ArgHandler handler : orderedArgHandlers) {
+    for (ArgHandler handler : argHandlers.values()) {
       if (handler.isUndocumented()) {
         continue;
       }
@@ -111,7 +106,7 @@
 
     // Print the command-line template.
     //
-    for (ArgHandler handler : orderedArgHandlers) {
+    for (ArgHandler handler : argHandlers.values()) {
       if (handler.isUndocumented()) {
         continue;
       }
@@ -154,7 +149,7 @@
 
     // Print the details.
     //
-    for (ArgHandler handler : orderedArgHandlers) {
+    for (ArgHandler handler : argHandlers.values()) {
       if (handler.isUndocumented()) {
         continue;
       }
@@ -294,7 +289,6 @@
 
   protected void registerHandler(ArgHandler handler) {
     String tag = handler.getTag();
-    orderedArgHandlers.add(handler);
     argHandlers.put(tag != null ? tag : "", handler);
   }
 }
diff --git a/dev/core/src/com/google/gwt/util/tools/Utility.java b/dev/core/src/com/google/gwt/util/tools/Utility.java
index 3e99fcf..03697bf 100644
--- a/dev/core/src/com/google/gwt/util/tools/Utility.java
+++ b/dev/core/src/com/google/gwt/util/tools/Utility.java
@@ -15,8 +15,6 @@
  */
 package com.google.gwt.util.tools;
 
-import com.google.gwt.dev.util.arg.ArgHandlerWorkDir;
-
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -40,6 +38,8 @@
  */
 public final class Utility {
 
+  private static final String GWT_TMP_DIR = "gwt-tmp";
+
   private static String sDevJarName = null;
   private static String sInstallPath = null;
 
@@ -231,43 +231,38 @@
   /**
    * Creates a randomly-named temporary directory.
    * 
-   * @param baseDir base directory to contain the new directory.  May be 
-   *    {@code null}, in which case a subdirectory under the
-   *    {@code java.io.tmpdir} system property, named by 
-   *    {@link ArgHandlerWorkDir#GWT_TMP_DIR}, will be used.
-   * @param prefix the initial characters of the new directory name.  Since all the
-   *    platforms we care about allow long names, this will not be pruned as for
-   *    {@link File#createTempFile(String, String, File), but short names are still
-   *    preferable.  The directory created will have five random characters appended
-   *    to the prefix.
-   * @returns a newly-created temporary directory
+   * @param baseDir base directory to contain the new directory. May be
+   *          {@code null}, in which case a subdirectory under the
+   *          {@code java.io.tmpdir} system property, named by
+   *          {@link #GWT_TMP_DIR}, will be used.
+   * @param prefix the initial characters of the new directory name
+   * @return a newly-created temporary directory; the caller must delete this
+   *          directory (either when done or on VM exit)
    */
-  public static File makeTemporaryDirectory(File baseDir, String prefix) 
+  public static File makeTemporaryDirectory(File baseDir, String prefix)
       throws IOException {
     if (baseDir == null) {
-      baseDir = new File(System.getProperty("java.io.tmpdir"), ArgHandlerWorkDir.GWT_TMP_DIR);
+      baseDir = new File(System.getProperty("java.io.tmpdir"), GWT_TMP_DIR);
     }
-    int tries = 0;
-    while (tries < 20) {
-      tries++;
-      int rand = (int) (Math.random() * Integer.MAX_VALUE);
-      StringBuffer tag = new StringBuffer();
-      for (int i = 0; i < 5; i++) {
-        int bits = rand & 0x1f; // low 5 bits: [a-z][0-4] for 32 values
-        rand >>= 5;
-        tag.append(Character.forDigit(bits, 36)); 
+    baseDir.mkdirs();
+
+    // Try this a few times due to non-atomic delete+mkdir operations.
+    for (int tries = 0; tries < 3; ++tries) {
+      File result = File.createTempFile(prefix, null, baseDir);
+      if (!result.delete()) {
+        throw new IOException("Couldn't delete temporary file "
+            + result.getAbsolutePath() + " to replace with a directory.");
       }
-      File result = new File(baseDir, prefix + tag.toString());
-      if (!result.exists()) {
-        if (result.mkdirs()) {
-          return result;
-        }
+      if (result.mkdirs()) {
+        // Success.
+        return result;
       }
     }
-    throw new IOException("couldn't create temporary directory in 20 tries in " 
-        + baseDir.getAbsolutePath());
+    throw new IOException(
+        "Couldn't create temporary directory after 3 tries in "
+            + baseDir.getAbsolutePath());
   }
-  
+
   public static void streamOut(File file, OutputStream out, int bufferSize)
       throws IOException {
     FileInputStream fis = null;
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java b/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java
new file mode 100644
index 0000000..c7e674a
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/common/EventReporter.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.common;
+
+import com.google.gwt.event.dom.client.HandlesAllKeyEvents;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.FocusListener;
+import com.google.gwt.user.client.ui.HasHTML;
+import com.google.gwt.user.client.ui.HasText;
+import com.google.gwt.user.client.ui.KeyboardListener;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.MouseListener;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.SuggestionEvent;
+import com.google.gwt.user.client.ui.SuggestionHandler;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
+
+/**
+ * Helper class to create visual tests.
+ * 
+ * @param <V> value type
+ * @param <T> target type
+ */
+@SuppressWarnings("deprecation")
+public class EventReporter<V, T> extends HandlesAllKeyEvents implements
+    ChangeListener, FocusListener, ValueChangeHandler<V>,
+    SelectionHandler<Suggestion>, SuggestionHandler, KeyboardListener,
+    ChangeHandler, BlurHandler, FocusHandler, ClickHandler, ClickListener,
+    CloseHandler<T>, MouseListener {
+
+  /**
+   * Add/remove handlers via check box.
+   * 
+   */
+  public abstract class CheckBoxEvent extends CheckBox implements
+      ValueChangeHandler<Boolean> {
+    String name;
+
+    public CheckBoxEvent(String name, Panel p) {
+      this.name = name;
+      this.setText(name);
+      p.add(this);
+      this.addValueChangeHandler(this);
+      this.setValue(true, true);
+    }
+
+    public abstract void addHandler();
+
+    public void onValueChange(ValueChangeEvent<Boolean> event) {
+      if (event.getValue().booleanValue()) {
+        report("add " + name);
+        addHandler();
+      } else {
+        report("remove " + name);
+        removeHandler();
+      }
+    }
+
+    public abstract void removeHandler();
+  }
+
+  private VerticalPanel panel = new VerticalPanel();
+
+  public EventReporter(Panel parent) {
+    parent.add(this.panel);
+  }
+
+  public String getInfo(Object sender) {
+    if (sender instanceof HasText) {
+      return ((HasText) sender).getText();
+    } else if (sender instanceof UIObject
+        && ((UIObject) sender).getTitle() != null) {
+      return ((UIObject) sender).getTitle();
+    } else if (sender instanceof HasHTML) {
+      return ((HasHTML) sender).getHTML();
+    } else {
+      return sender.toString();
+    }
+  }
+
+  public void onBlur(BlurEvent event) {
+    report(event);
+  }
+
+  public void onChange(ChangeEvent event) {
+    report(event);
+  }
+
+  @SuppressWarnings("deprecation")
+  public void onChange(Widget sender) {
+    report("change on " + getInfo(sender));
+  }
+
+  public void onClick(ClickEvent event) {
+    report(event);
+  }
+
+  @SuppressWarnings("deprecation")
+  public void onClick(Widget sender) {
+    report("click: " + getInfo(sender));
+  }
+
+  public void onClose(CloseEvent<T> event) {
+    report("close " + getInfo(event.getTarget()));
+  }
+
+  public void onFocus(FocusEvent event) {
+    report(event);
+  }
+
+  public void onFocus(Widget sender) {
+    report("focus: " + getInfo(sender));
+  }
+
+  public void onKeyDown(KeyDownEvent event) {
+    report(event);
+  }
+
+  public void onKeyDown(Widget sender, char keyCode, int modifiers) {
+    report(getInfo(sender) + "key down code: " + keyCode + " modifiers: "
+        + modifiers);
+  }
+
+  public void onKeyPress(KeyPressEvent event) {
+    report(event);
+  }
+
+  public void onKeyPress(Widget sender, char keyCode, int modifiers) {
+    report(getInfo(sender) + "key press code: " + keyCode + " modifiers: "
+        + modifiers);
+  }
+
+  public void onKeyUp(KeyUpEvent event) {
+    report(event);
+  }
+
+  public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    report(getInfo(sender) + "key  up code: " + keyCode + " modifiers: "
+        + modifiers);
+  }
+
+  public void onLostFocus(Widget sender) {
+    report("blur: " + sender.getClass());
+  }
+
+  public void onMouseDown(Widget sender, int x, int y) {
+    report(getInfo(sender) + "mouse down");
+  }
+
+  public void onMouseEnter(Widget sender) {
+    report(getInfo(sender) + "mouse enter");
+  }
+
+  public void onMouseLeave(Widget sender) {
+    report(getInfo(sender) + "mouse leave");
+  }
+
+  public void onMouseMove(Widget sender, int x, int y) {
+    report(getInfo(sender) + "mouse move");
+  }
+
+  public void onMouseUp(Widget sender, int x, int y) {
+    report(getInfo(sender) + "mouse up");
+  }
+
+  public void onSelection(SelectionEvent<Suggestion> event) {
+    report(event);
+  }
+
+  public void onSuggestionSelected(SuggestionEvent event) {
+    report("suggestion: " + event.getSelectedSuggestion());
+  }
+
+  public void onValueChange(ValueChangeEvent<V> event) {
+    report(event);
+  }
+
+  // will be replaced by logging
+  public void report(String s) {
+    panel.insert(new Label(s), 0);
+    if (panel.getWidgetCount() == 10) {
+      panel.remove(9);
+    }
+  }
+
+  private void report(GwtEvent<?> event) {
+    report(getInfo(event.getSource()) + " fired " + event.toDebugString());
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/common/Utility.java b/reference/code-museum/src/com/google/gwt/museum/client/common/Utility.java
index c4d4093..66a2860 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/common/Utility.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/common/Utility.java
@@ -1,33 +1,33 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.common;

-

-import com.google.gwt.dom.client.HeadElement;

-

-/**

- * Utility helper methods.

- */

-public class Utility {

-  /**

-   * Convenience method for getting the document's head element.

-   * 

-   * @return the document's head element

-   */

-  public static native HeadElement getHeadElement() /*-{

-    return $doc.getElementsByTagName("head")[0];

-  }-*/;

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.common;
+
+import com.google.gwt.dom.client.HeadElement;
+
+/**
+ * Utility helper methods.
+ */
+public class Utility {
+  /**
+   * Convenience method for getting the document's head element.
+   * 
+   * @return the document's head element
+   */
+  public static native HeadElement getHeadElement() /*-{
+    return $doc.getElementsByTagName("head")[0];
+  }-*/;
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
index 688e47e..58745c5 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/DefaultMuseum.java
@@ -1,48 +1,64 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.core.client.EntryPoint;

-import com.google.gwt.museum.client.viewer.Museum;

-

-/**

- * Default bug museum. Contains a list of all GWT issues reported in the system

- * to date.

- */

-public class DefaultMuseum extends Museum implements EntryPoint {

-  public DefaultMuseum() {

-    addIssue(new Issue1245());

-    addIssue(new Issue1772());

-    addIssue(new Issue1897());

-    addIssue(new Issue1932());

-    addIssue(new Issue2261());

-    addIssue(new Issue2290());

-    addIssue(new Issue2307());

-    addIssue(new Issue2321());

-    addIssue(new Issue2331());

-    addIssue(new Issue2338());

-    addIssue(new Issue2339());

-    addIssue(new Issue2390());

-    addIssue(new Issue1169());

-    addIssue(new Issue2392());

-    addIssue(new Issue2443());

-    addIssue(new Issue2553());

-    addIssue(new Issue2855());

-    addIssue(new TreeVisuals());

-    addIssue(new TestFireEvents());

-  }

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.museum.client.viewer.Museum;
+
+/**
+ * Default bug museum. By default, shows all visual tests defined in GWT ui to
+ * date. Modify the code to add all bugs in as well.
+ */
+public class DefaultMuseum extends Museum implements EntryPoint {
+
+  public DefaultMuseum() {
+    addVisuals();
+    addBugs();
+  }
+
+  public void addBugs() {
+    addIssue(new Issue1245());
+    addIssue(new Issue1772());
+    addIssue(new Issue1897());
+    addIssue(new Issue1932());
+    addIssue(new Issue2261());
+    addIssue(new Issue2290());
+    addIssue(new Issue2307());
+    addIssue(new Issue2321());
+    addIssue(new Issue2331());
+    addIssue(new Issue2338());
+    addIssue(new Issue2339());
+    addIssue(new Issue2390());
+    addIssue(new Issue1169());
+    addIssue(new Issue2392());
+    addIssue(new Issue2443());
+    addIssue(new Issue2553());
+    addIssue(new Issue2855());
+  }
+
+  public void addVisuals() {
+    addIssue(new VisualsForDisclosurePanelEvents());
+    addIssue(new VisualsForEventsFiring());
+    addIssue(new VisualsForPopupEvents());
+    addIssue(new VisualsForTextEvents());
+    addIssue(new VisualsForSuggestBoxEvents());
+    addIssue(new VisualsForTableEvents());
+    addIssue(new VisualsForTree());
+    addIssue(new VisualsForTreeEvents());
+    addIssue(new VisualsForWindowEvents());
+    addIssue(new VisualsForDialogBox());
+  }
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1245.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1245.java
index 7550547..86837a9 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1245.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1245.java
@@ -1,57 +1,57 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

- 

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.Tree;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * Ugly focus ring on Tree.

- */

-public class Issue1245 extends AbstractIssue {

-  Tree t = null;

-

-  @Override

-  public Widget createIssue() {

-    t = new Tree();

-    t.addItem("a").addItem("a.a");

-    t.addItem("b");

-    t.addItem("c").addItem("c.a");

-    return t;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "No focus triangle should be visible";

-  }

-

-  @Override

-  public String getSummary() {

-    return "Ugly focus ring on Tree";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-  public void onAttatched() {

-    t.setFocus(true);

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Ugly focus ring on Tree.
+ */
+public class Issue1245 extends AbstractIssue {
+  Tree t = null;
+
+  @Override
+  public Widget createIssue() {
+    t = new Tree();
+    t.addItem("a").addItem("a.a");
+    t.addItem("b");
+    t.addItem("c").addItem("c.a");
+    return t;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "No focus triangle should be visible";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Ugly focus ring on Tree";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  public void onAttatched() {
+    t.setFocus(true);
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1488.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1488.java
index ce989a0..e8150f4 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1488.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1488.java
@@ -1,51 +1,51 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.RichTextArea;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * RichTextArea - setEnabled does not work.

- * 

- */

-public class Issue1488 extends AbstractIssue {

-  RichTextArea t = new RichTextArea();

-

-  @Override

-  public Widget createIssue() {

-    t.setFocus(true);

-    return t;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Should not be able to type in the text area";

-  }

-

-  @Override

-  public String getSummary() {

-    return "RichTextArea - setEnabled does not work";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.RichTextArea;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * RichTextArea - setEnabled does not work.
+ * 
+ */
+public class Issue1488 extends AbstractIssue {
+  RichTextArea t = new RichTextArea();
+
+  @Override
+  public Widget createIssue() {
+    t.setFocus(true);
+    return t;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Should not be able to type in the text area";
+  }
+
+  @Override
+  public String getSummary() {
+    return "RichTextArea - setEnabled does not work";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1897.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1897.java
index e6a0832..8f21036 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1897.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1897.java
@@ -15,12 +15,13 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.RichTextArea;
@@ -28,7 +29,7 @@
 import com.google.gwt.user.client.ui.Widget;
 
 /**
- * <h1> Attaching and detaching a RichTextArea too fast crashes GWT </h1>
+ * <h1>Attaching and detaching a RichTextArea too fast crashes GWT</h1>
  * 
  * <p>
  * The RichTextArea uses a Timer or iframe.onload event (depending on the
@@ -65,8 +66,8 @@
       hPanel.setSpacing(10);
 
       // Add option to attach RichTextArea
-      Button attachButton = new Button("Attach RichText", new ClickListener() {
-        public void onClick(Widget sender) {
+      Button attachButton = new Button("Attach RichText", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           if (rta.isAttached()) {
             Window.alert("RichTextArea is already attached.");
           }
@@ -76,8 +77,8 @@
       hPanel.add(attachButton);
 
       // Add option to detach RichTextArea
-      Button detachButton = new Button("Detach RichText", new ClickListener() {
-        public void onClick(Widget sender) {
+      Button detachButton = new Button("Detach RichText", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           if (!rta.isAttached()) {
             Window.alert("RichTextArea is already detached.");
             return;
@@ -89,8 +90,8 @@
 
       // Add option to attach and detach RichTextArea
       Button quickDetachButton = new Button("Attach/Detach RichText",
-          new ClickListener() {
-            public void onClick(Widget sender) {
+          new ClickHandler() {
+            public void onClick(ClickEvent event) {
               if (rta.isAttached()) {
                 Window.alert("RichTextArea is already attached.");
                 return;
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
index 60df7ab..67b5d33 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue1932.java
@@ -16,13 +16,14 @@
 package com.google.gwt.museum.client.defaultmuseum;
 
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventPreview;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
@@ -38,7 +39,7 @@
  */
 public class Issue1932 extends AbstractIssue {
   /**
-   * A set of options used to set the page margins and borders
+   * A set of options used to set the page margins and borders.
    */
   private class ControlPanel extends Composite {
     private final Grid grid = new Grid(2, 3);
@@ -54,8 +55,8 @@
       marginBox.setText("10px");
       grid.setHTML(0, 0, "<b>Margin:</b>");
       grid.setWidget(0, 1, marginBox);
-      grid.setWidget(0, 2, new Button("Set", new ClickListener() {
-        public void onClick(Widget sender) {
+      grid.setWidget(0, 2, new Button("Set", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           updateMargin();
         }
       }));
@@ -64,8 +65,8 @@
       borderBox.setText("5px solid #DDDDDD");
       grid.setHTML(1, 0, "<b>Border:</b>");
       grid.setWidget(1, 1, borderBox);
-      grid.setWidget(1, 2, new Button("Set", new ClickListener() {
-        public void onClick(Widget sender) {
+      grid.setWidget(1, 2, new Button("Set", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           updateBorder();
         }
       }));
@@ -131,12 +132,10 @@
             int absY = event.getClientY() + Window.getScrollTop();
             RootPanel.get().add(positioner, absX, absY);
 
-            echo.setHTML(
-              "event.clientX: " + event.getClientX() + "<br>" +
-              "event.clientY: " + event.getClientY() + "<br>" +
-              "absolute left: " + positioner.getAbsoluteLeft() + "<br>" +
-              "absolute top: " + positioner.getAbsoluteTop()
-            );
+            echo.setHTML("event.clientX: " + event.getClientX() + "<br>"
+                + "event.clientY: " + event.getClientY() + "<br>"
+                + "absolute left: " + positioner.getAbsoluteLeft() + "<br>"
+                + "absolute top: " + positioner.getAbsoluteTop());
             break;
         }
         return true;
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2261.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2261.java
index 876e698..7c1904e 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2261.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2261.java
@@ -1,55 +1,55 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.DisclosurePanel;

-import com.google.gwt.user.client.ui.Label;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * Open disclosure panel causes flicker.

- */

-public class Issue2261 extends AbstractIssue {

-

-  @Override

-  public Widget createIssue() {

-    DisclosurePanel disclosurePanel = new DisclosurePanel("Disclosure Panel 1");

-    disclosurePanel.setAnimationEnabled(true);

-    Label content = new Label("Some content<br/><br/><br/>");

-    content.setHeight("200px");

-    content.getElement().getStyle().setProperty("background", "blue");

-    disclosurePanel.setContent(content);

-    return disclosurePanel;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Open disclosure panel and you should not see a flicker";

-  }

-

-  @Override

-  public String getSummary() {

-    return "DisclosurePanel flicker";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Open disclosure panel causes flicker.
+ */
+public class Issue2261 extends AbstractIssue {
+
+  @Override
+  public Widget createIssue() {
+    DisclosurePanel disclosurePanel = new DisclosurePanel("Disclosure Panel 1");
+    disclosurePanel.setAnimationEnabled(true);
+    Label content = new Label("Some content<br/><br/><br/>");
+    content.setHeight("200px");
+    content.getElement().getStyle().setProperty("background", "blue");
+    disclosurePanel.setContent(content);
+    return disclosurePanel;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open disclosure panel and you should not see a flicker";
+  }
+
+  @Override
+  public String getSummary() {
+    return "DisclosurePanel flicker";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2290.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2290.java
index 8a0e016..8543e9e 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2290.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2290.java
@@ -21,7 +21,7 @@
 import com.google.gwt.user.client.ui.Widget;
 
 /**
- * <h1> gwt-TreeItem refers to the wrong element in TreeItem </h1>
+ * <h1>gwt-TreeItem refers to the wrong element in TreeItem</h1>
  * 
  * <p>
  * gwt-TreeItem used to refer to the span that directly wrapped the text in a
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2307.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2307.java
index 10cb529..ca9ed69 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2307.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2307.java
@@ -15,10 +15,11 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.CaptionPanel;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.TextBox;
@@ -50,8 +51,8 @@
       final TextBox textBox = new TextBox();
       textBox.setText("<b>CaptionPanel</b>");
       grid.setWidget(0, 1, textBox);
-      grid.setWidget(0, 0, new Button("setCaptionText", new ClickListener() {
-        public void onClick(Widget sender) {
+      grid.setWidget(0, 0, new Button("setCaptionText", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           captionPanel.setCaptionText(textBox.getText());
         }
       }));
@@ -60,8 +61,8 @@
       final TextBox htmlBox = new TextBox();
       htmlBox.setText("<b>CaptionPanel</b>");
       grid.setWidget(1, 1, htmlBox);
-      grid.setWidget(1, 0, new Button("setCaptionHTML", new ClickListener() {
-        public void onClick(Widget sender) {
+      grid.setWidget(1, 0, new Button("setCaptionHTML", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           captionPanel.setCaptionHTML(htmlBox.getText());
         }
       }));
@@ -70,8 +71,8 @@
       final TextBox contentBox = new TextBox();
       contentBox.setText("<b><i>I am a Button</i></b>");
       grid.setWidget(2, 1, contentBox);
-      grid.setWidget(2, 0, new Button("setContentWidget", new ClickListener() {
-        public void onClick(Widget sender) {
+      grid.setWidget(2, 0, new Button("setContentWidget", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           captionPanel.setContentWidget(new Button(contentBox.getText()));
         }
       }));
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2321.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2321.java
index 944452c..44ba2d8 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2321.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2321.java
@@ -15,9 +15,10 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DeckPanel;
 import com.google.gwt.user.client.ui.Grid;
@@ -45,8 +46,8 @@
       initWidget(grid);
 
       // Add option to detach the deck panel
-      Button addWidgetButton = new Button("Add widget", new ClickListener() {
-        public void onClick(Widget sender) {
+      Button addWidgetButton = new Button("Add widget", new ClickHandler() {
+        public void onClick(ClickEvent event) {
           addWidgetToDeckPanel();
         }
       });
@@ -54,8 +55,8 @@
 
       // Add option to retrieve the dimensions of the content
       Button updateDimButton = new Button("Get Current Dimensions",
-          new ClickListener() {
-            public void onClick(Widget sender) {
+          new ClickHandler() {
+            public void onClick(ClickEvent event) {
               updateContentDimensions();
             }
           });
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2331.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2331.java
index d575d37..26ae0d0 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2331.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2331.java
@@ -1,53 +1,53 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.Label;

-import com.google.gwt.user.client.ui.StackPanel;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * Clicking on StackPanel fails to open stack.

- */

-public class Issue2331 extends AbstractIssue {

-

-  @Override

-  public Widget createIssue() {

-    StackPanel p = new StackPanel();

-    p.add(new Label("Content A"), "Header A");

-    p.add(new Label("Content B"), "Header B");

-    p.add(new Label("Content C"), "Header C");

-    return p;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Click on B";

-  }

-

-  @Override

-  public String getSummary() {

-    return "Stack Panel does not response to switching stacks";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.StackPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Clicking on StackPanel fails to open stack.
+ */
+public class Issue2331 extends AbstractIssue {
+
+  @Override
+  public Widget createIssue() {
+    StackPanel p = new StackPanel();
+    p.add(new Label("Content A"), "Header A");
+    p.add(new Label("Content B"), "Header B");
+    p.add(new Label("Content C"), "Header C");
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Click on B";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Stack Panel does not response to switching stacks";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2338.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2338.java
index 3afd182..1f619c0 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2338.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2338.java
@@ -1,55 +1,55 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.Tree;

-import com.google.gwt.user.client.ui.TreeItem;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * Opening a tree item flickers in IE7 because all of the children are shown for

- * an instant, and then the animation continues normally.

- */

-public class Issue2338 extends AbstractIssue {

-

-  @Override

-  public Widget createIssue() {

-    Tree tree = new Tree();

-    tree.setAnimationEnabled(true);

-    TreeItem root = tree.addItem("Root");

-    for (int i = 0; i < 5; i++) {

-      root.addItem("Item " + i);

-    }

-    return tree;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Open the root node and you should not see a flicker";

-  }

-

-  @Override

-  public String getSummary() {

-    return "Tree animation flickers when expanding a TreeItem";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeItem;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Opening a tree item flickers in IE7 because all of the children are shown for
+ * an instant, and then the animation continues normally.
+ */
+public class Issue2338 extends AbstractIssue {
+
+  @Override
+  public Widget createIssue() {
+    Tree tree = new Tree();
+    tree.setAnimationEnabled(true);
+    TreeItem root = tree.addItem("Root");
+    for (int i = 0; i < 5; i++) {
+      root.addItem("Item " + i);
+    }
+    return tree;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open the root node and you should not see a flicker";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Tree animation flickers when expanding a TreeItem";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2339.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2339.java
index ce70cce..3cdcd09 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2339.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2339.java
@@ -1,63 +1,64 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.HTML;

-import com.google.gwt.user.client.ui.TabPanel;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * When you change to a different widget in the DeckPanel, there is a flicker in

- * IE7 where the new widget is completely visible for an instant, and then the

- * animation continues normally.

- */

-public class Issue2339 extends AbstractIssue {

-  private static final String[] TAB_BACKGROUNDS = {"#f88", "#88f", "#8f8", "#8ff", "#f8f"};

-

-  @Override

-  public Widget createIssue() {

-    final TabPanel tabPanel = new TabPanel();

-    String contentText = "";

-    for (int i = 0; i < TAB_BACKGROUNDS.length; i++) {

-      contentText += "Each tab has more text.<br>";

-      HTML content = new HTML(contentText);

-      content.getElement().getStyle().setProperty("background",

-          TAB_BACKGROUNDS[i]);

-      tabPanel.add(content, "Tab " + i);

-    }

-

-    tabPanel.selectTab(0);

-    tabPanel.getDeckPanel().setAnimationEnabled(true);

-    return tabPanel;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Switch to a different tab and you should not see a flicker";

-  }

-

-  @Override

-  public String getSummary() {

-    return "DeckPanel flickers when switching between widgets";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.TabPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * When you change to a different widget in the DeckPanel, there is a flicker in
+ * IE7 where the new widget is completely visible for an instant, and then the
+ * animation continues normally.
+ */
+public class Issue2339 extends AbstractIssue {
+  private static final String[] TAB_BACKGROUNDS = {
+      "#f88", "#88f", "#8f8", "#8ff", "#f8f"};
+
+  @Override
+  public Widget createIssue() {
+    final TabPanel tabPanel = new TabPanel();
+    String contentText = "";
+    for (int i = 0; i < TAB_BACKGROUNDS.length; i++) {
+      contentText += "Each tab has more text.<br>";
+      HTML content = new HTML(contentText);
+      content.getElement().getStyle().setProperty("background",
+          TAB_BACKGROUNDS[i]);
+      tabPanel.add(content, "Tab " + i);
+    }
+
+    tabPanel.selectTab(0);
+    tabPanel.getDeckPanel().setAnimationEnabled(true);
+    return tabPanel;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Switch to a different tab and you should not see a flicker";
+  }
+
+  @Override
+  public String getSummary() {
+    return "DeckPanel flickers when switching between widgets";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java
index dd0bdf9..b478ec9 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2390.java
@@ -15,10 +15,11 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.PopupPanel;
@@ -42,15 +43,15 @@
 
     // Create a modal PopupPanel
     final PopupPanel popup = new PopupPanel(false, true);
-    popup.setWidget(new Button("Hide Popup", new ClickListener() {
-      public void onClick(Widget sender) {
+    popup.setWidget(new Button("Hide Popup", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         popup.hide();
       }
     }));
 
     // Create a button to show the PopupPanel
-    Button showPopupButton = new Button("Show Popup", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button showPopupButton = new Button("Show Popup", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         popup.center();
       }
     });
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2443.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2443.java
index f7fd88a..8a77a6a 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2443.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2443.java
@@ -15,9 +15,10 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.VerticalPanel;
@@ -44,16 +45,16 @@
         + "DialogBox is dragged to the right edge of the screen.  ";
     VerticalPanel vPanel = new VerticalPanel();
     vPanel.add(new Label(message));
-    vPanel.add(new Button("Close", new ClickListener() {
-      public void onClick(Widget sender) {
+    vPanel.add(new Button("Close", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         dialogBox.hide();
       }
     }));
     dialogBox.setWidget(vPanel);
 
     // Create a button to display the dialog box
-    Button showButton = new Button("Show DialogBox", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button showButton = new Button("Show DialogBox", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         dialogBox.center();
       }
     });
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2855.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2855.java
index 9f5f4f0..6d77f74 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2855.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/Issue2855.java
@@ -15,10 +15,11 @@
  */
 package com.google.gwt.museum.client.defaultmuseum;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
@@ -40,28 +41,28 @@
 
     // Add buttons to call getters and setters
     Button toggleAutoHide = new Button("4. Toggle AutoHide",
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             popup.setAutoHideEnabled(!popup.isAutoHideEnabled());
           }
         });
-    Button toggleModal = new Button("3. Toggle Modal", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button toggleModal = new Button("3. Toggle Modal", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         popup.setModal(!popup.isModal());
       }
     });
-    Button isAutoHide = new Button("isAutoHide?", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button isAutoHide = new Button("isAutoHide?", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("AutoHide: " + popup.isAutoHideEnabled());
       }
     });
-    Button isModal = new Button("isModal?", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button isModal = new Button("isModal?", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("Modal: " + popup.isModal());
       }
     });
-    Button closeButton = new Button("Close", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button closeButton = new Button("Close", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         popup.hide();
       }
     });
@@ -74,13 +75,13 @@
     popup.setWidget(vPanel);
 
     // Add control buttons
-    Button showPopup = new Button("1. Show Popup", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button showPopup = new Button("1. Show Popup", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         popup.center();
       }
     });
-    Button clickable = new Button("2/4. Click Me", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button clickable = new Button("2/4. Click Me", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("You got me!");
       }
     });
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TestFireEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TestFireEvents.java
deleted file mode 100644
index 9d343db..0000000
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TestFireEvents.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.museum.client.defaultmuseum;
-
-import com.google.gwt.museum.client.common.AbstractIssue;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.WindowCloseListener;
-import com.google.gwt.user.client.WindowResizeListener;
-import com.google.gwt.user.client.WindowScrollListener;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
-import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Verify that events fire in all browsers.
- */
-public class TestFireEvents extends AbstractIssue {
-  private static final int WINDOW_EVENT_SCROLL = -1;
-  private static final int WINDOW_EVENT_RESIZE = -2;
-  private static final int WINDOW_EVENT_CLOSING = -3;
-
-  /**
-   * The main grid used for layout.
-   */
-  private FlexTable layout = null;
-
-  private Map<Integer, Integer> eventMap = new HashMap<Integer, Integer>();
-
-  @Override
-  public Widget createIssue() {
-    // Create a grid to hold all of the tests
-    eventMap.clear();
-    layout = new FlexTable();
-    layout.setCellPadding(3);
-    layout.setBorderWidth(2);
-    layout.setHTML(0, 0, "<b>Action to Perform</b>");
-    layout.setHTML(0, 1, "<b>Event</b>");
-    layout.setHTML(0, 2, "<b>Status</b>");
-
-    // Mouse and click events
-    Button button = new Button("Double-click me") {
-      @Override
-      public void onBrowserEvent(Event event) {
-        // Verify that values associated with events are defined. For some
-        // values, we just want to make sure we can get them without any
-        // errrors.
-        assert event.getClientX() > 0;
-        assert event.getClientY() > 0;
-        assert event.getScreenX() > 0;
-        assert event.getScreenY() > 0;
-        event.getAltKey();
-        event.getCtrlKey();
-        event.getShiftKey();
-        event.getMetaKey();
-        int eventType = event.getTypeInt();
-        switch (eventType) {
-          case Event.ONMOUSEDOWN:
-          case Event.ONMOUSEUP:
-            event.getButton();
-            break;
-          case Event.ONMOUSEOVER:
-          case Event.ONMOUSEOUT:
-            assert event.getFromElement() != null;
-            assert event.getToElement() != null;
-            break;
-        }
-
-        passTest(event);
-      }
-    };
-    button.sinkEvents(Event.ONCLICK | Event.ONDBLCLICK | Event.MOUSEEVENTS);
-    addTest(Event.ONCLICK, "click", button);
-    addDependentTest(Event.ONDBLCLICK, "dblclick");
-    addDependentTest(Event.ONMOUSEDOWN, "mousedown");
-    addDependentTest(Event.ONMOUSEUP, "mouseup");
-    addDependentTest(Event.ONMOUSEOVER, "mouseover");
-    addDependentTest(Event.ONMOUSEOUT, "mouseout");
-    addDependentTest(Event.ONMOUSEMOVE, "mousemove");
-
-    // Keyboard events
-    TextBox textBox = new TextBox() {
-      @SuppressWarnings("fallthrough")
-      @Override
-      public void onBrowserEvent(Event event) {
-        // Verify that values associated with events are defined
-        int eventType = event.getTypeInt();
-        switch (eventType) {
-          case Event.ONFOCUS:
-          case Event.ONBLUR:
-            break;
-          case Event.ONKEYDOWN:
-            event.getRepeat();
-            // Intentional fall through
-          case Event.ONKEYUP:
-          case Event.ONKEYPRESS:
-            event.getAltKey();
-            event.getCtrlKey();
-            event.getShiftKey();
-            event.getMetaKey();
-            assert event.getKeyCode() > 0;
-            break;
-          case Event.ONCHANGE:
-            break;
-        }
-
-        passTest(event);
-      }
-    };
-    textBox.sinkEvents(Event.KEYEVENTS | Event.ONFOCUS | Event.ONBLUR
-        | Event.ONCHANGE);
-    textBox.setText("Type a letter");
-    addTest(Event.ONKEYDOWN, "keydown", textBox);
-    addDependentTest(Event.ONKEYPRESS, "keypress");
-    addDependentTest(Event.ONKEYUP, "keyup");
-    addDependentTest(Event.ONFOCUS, "focus");
-    addDependentTest(Event.ONBLUR, "blur");
-    addDependentTest(Event.ONCHANGE, "change");
-
-    // onscroll and onmousewheel
-    String scrollableMessage = "Scroll to the bottom<br>(using mouse wheel<br>"
-        + "if supported)";
-    HTML scrollableContents = new HTML(scrollableMessage);
-    scrollableContents.setPixelSize(400, 400);
-    scrollableContents.getElement().getStyle().setProperty("textAlign", "left");
-    ScrollPanel scrollable = new ScrollPanel(scrollableContents) {
-      @Override
-      public void onBrowserEvent(Event event) {
-        // Verify that values associated with events are defined
-        int eventType = event.getTypeInt();
-        switch (eventType) {
-          case Event.ONMOUSEWHEEL:
-            event.getClientX();
-            event.getClientY();
-            event.getScreenX();
-            event.getScreenY();
-            event.getMouseWheelVelocityY();
-            break;
-          case Event.ONSCROLL:
-            break;
-        }
-
-        passTest(event);
-      }
-    };
-    scrollable.sinkEvents(Event.ONSCROLL | Event.ONMOUSEWHEEL);
-    scrollable.setAlwaysShowScrollBars(true);
-    scrollable.setPixelSize(200, 100);
-    addTest(Event.ONSCROLL, "scroll", scrollable);
-    addDependentTest(Event.ONMOUSEWHEEL, "mousewheel");
-
-    // onload
-    Image loadable = new Image() {
-      @Override
-      public void onBrowserEvent(Event event) {
-        passTest(event);
-
-        int eventType = event.getTypeInt();
-        switch (eventType) {
-          case Event.ONERROR:
-            setUrl("issues/images/gwtLogo.png");
-            break;
-          case Event.ONCONTEXTMENU:
-            assert event.getClientX() > 0;
-            assert event.getClientY() > 0;
-            assert event.getScreenX() > 0;
-            assert event.getScreenY() > 0;
-            event.getAltKey();
-            event.getShiftKey();
-            event.getCtrlKey();
-            event.getMetaKey();
-            break;
-        }
-      }
-    };
-    loadable.sinkEvents(Event.ONCONTEXTMENU);
-    addTest(Event.ONERROR, "error", loadable);
-    addDependentTest(Event.ONLOAD, "load");
-    addDependentTest(Event.ONCONTEXTMENU, "contextMenu");
-    loadable.setUrl("imageDoesNotExist.abc");
-
-    // Window Scroll Event
-    Label windowLabel = new Label("Window level events");
-    addTest(WINDOW_EVENT_SCROLL, "window.onscroll", windowLabel);
-    Window.addWindowScrollListener(new WindowScrollListener() {
-      public void onWindowScrolled(int scrollLeft, int scrollTop) {
-        passTest(WINDOW_EVENT_SCROLL);
-      }
-    });
-
-    // Window Resize Event
-    addDependentTest(WINDOW_EVENT_RESIZE, "window.onresize");
-    Window.addWindowResizeListener(new WindowResizeListener() {
-      public void onWindowResized(int width, int height) {
-        passTest(WINDOW_EVENT_RESIZE);
-      }
-    });
-
-    // Window Closing Event
-    addDependentTest(WINDOW_EVENT_CLOSING, "window.onbeforeunload");
-    Window.addWindowCloseListener(new WindowCloseListener() {
-      public void onWindowClosed() {
-      }
-
-      public String onWindowClosing() {
-        passTest(WINDOW_EVENT_CLOSING);
-        return "";
-      }
-    });
-
-    // The following are not testable or not supported in all browsers
-    // onlosecapture
-
-    return layout;
-  }
-
-  @Override
-  public String getInstructions() {
-    return "Use the Widgets below to verify that all events fire in all "
-        + "browsers.  To test an event, perform the action require to trigger "
-        + "the event using the provided widget.";
-  }
-
-  @Override
-  public String getSummary() {
-    return "Events fire in current browsers";
-  }
-
-  @Override
-  public boolean hasCSS() {
-    return false;
-  }
-
-  /**
-   * Add a test that is dependent on a previous test.
-   * 
-   * @param eventType the type of event defined in {@link Event}
-   * @param eventName the name of the event
-   */
-  private void addDependentTest(int eventType, String eventName) {
-    // Find the last test
-    int numRows = layout.getRowCount();
-    eventMap.put(new Integer(eventType), new Integer(numRows));
-    for (int i = numRows - 1; i > 0; i--) {
-      if (layout.getCellCount(i) == 3) {
-        FlexCellFormatter formatter = layout.getFlexCellFormatter();
-        int rowSpan = formatter.getRowSpan(i, 0);
-        formatter.setRowSpan(i, 0, rowSpan + 1);
-        break;
-      }
-    }
-    layout.setText(numRows, 0, eventName);
-    layout.setText(numRows, 1, "?");
-  }
-
-  /**
-   * Add a new test that tests one or more events.
-   * 
-   * @param eventType the type of event defined in {@link Event}
-   * @param eventName the name of the event
-   * @param trigger the widget that triggers the events
-   */
-  private void addTest(int eventType, String eventName, Widget trigger) {
-    int numRows = layout.getRowCount();
-    eventMap.put(new Integer(eventType), new Integer(numRows));
-    layout.setWidget(numRows, 0, trigger);
-    layout.setText(numRows, 1, eventName);
-    layout.setText(numRows, 2, "?");
-
-    FlexCellFormatter formatter = layout.getFlexCellFormatter();
-    formatter.setVerticalAlignment(numRows, 0,
-        HasVerticalAlignment.ALIGN_MIDDLE);
-    formatter.setHorizontalAlignment(numRows, 0,
-        HasHorizontalAlignment.ALIGN_CENTER);
-  }
-
-  /**
-   * Mark the event as passed.
-   * 
-   * @param event the event that was triggered
-   */
-  private void passTest(Event event) {
-    passTest(event.getTypeInt());
-  }
-
-  /**
-   * Mark the event as passed.
-   * 
-   * @param eventType the event type that was triggered
-   */
-  private void passTest(int eventType) {
-    int rowIndex = eventMap.get(new Integer(eventType));
-    if (layout.getCellCount(rowIndex) == 3) {
-      layout.setHTML(rowIndex, 2, "pass");
-    } else {
-      layout.setHTML(rowIndex, 1, "pass");
-    }
-  }
-}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCheckBoxAndRadioButtonEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCheckBoxAndRadioButtonEvents.java
new file mode 100644
index 0000000..468b95a
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForCheckBoxAndRadioButtonEvents.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.EventReporter;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.RadioButton;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Visual testing of rich text box events.
+ */
+public class VisualsForCheckBoxAndRadioButtonEvents extends AbstractIssue {
+  private VerticalPanel p = new VerticalPanel();
+
+  @SuppressWarnings("deprecation")
+  @Override
+  public Widget createIssue() {
+    p.setWidth("500px");
+    p.setBorderWidth(1);
+    // TextBox
+    final CheckBox b = new CheckBox("My Checkbox");
+    b.setTitle("text box");
+    p.add(b);
+    EventReporter<Boolean, Object> handler = new EventReporter<Boolean, Object>(
+        p);
+    p.add(new Button("change value with event", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        b.setValue(false, true);
+      }
+    }));
+    b.addKeyboardListener(handler);
+    handler.addKeyHandlersTo(b);
+
+    b.addFocusHandler(handler);
+    b.addBlurHandler(handler);
+    b.addFocusListener(handler);
+    b.addValueChangeHandler(handler);
+
+    // Rich text box:
+    final RadioButton radio = new RadioButton("A", "With events");
+    p.add(radio);
+    final RadioButton radioPrime = new RadioButton("A", "No events");
+    p.add(radioPrime);
+    b.setTitle("Radio Button");
+    p.add(radio);
+    handler = new EventReporter<Boolean, Object>(p);
+    radio.addKeyboardListener(handler);
+    handler.addKeyHandlersTo(radio);
+    radio.addBlurHandler(handler);
+    radio.addFocusHandler(handler);
+    radio.addClickHandler(handler);
+    radio.addClickListener(handler);
+    radio.addValueChangeHandler(handler);
+    p.add(new Button("change value with event", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        radio.setValue(true, true);
+      }
+    }));
+
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Click on CheckBox and Radio Button, use change value events,see that correct events are firing";
+  }
+
+  @Override
+  public String getSummary() {
+    return "CheckBox and RadioButton test";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDialogBox.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDialogBox.java
new file mode 100644
index 0000000..403d7be
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDialogBox.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.DialogBox;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Verify that events fire in all browsers.
+ */
+public class VisualsForDialogBox extends AbstractIssue {
+
+  enum VisibleEvents {
+    mouseDown, mouseEnter, mouseLeave, mouseMove, mouseUp, captionMouseDown
+  }
+
+  private final class VisibleDialogBox extends DialogBox {
+    private FlexTable layout = null;
+
+    private final Map<VisibleEvents, Element> eventToElement = new HashMap<VisibleEvents, Element>();
+
+    private boolean maybeClose;
+
+    public VisibleDialogBox() {
+      this(false);
+    }
+
+    public VisibleDialogBox(boolean autoHide) {
+      this(autoHide, true);
+    }
+
+    public VisibleDialogBox(boolean autoHide, boolean modal) {
+      super(autoHide, modal);
+      layout = new FlexTable();
+      layout.setCellPadding(3);
+      layout.setBorderWidth(2);
+      layout.setHTML(0, 0, "<b>VisibleEvents</b>");
+      layout.setHTML(0, 1, "<b>Status</b>");
+
+      final String style = "float:right; border: 1px solid blue; color:blue;"
+          + "font-weight:bold; font-size:85%";
+      setHTML("I Gots a Close Box<div id='vis-closebox' style='" + style
+          + "'>&nbsp;X&nbsp;</div>");
+
+      for (VisibleEvents e : VisibleEvents.values()) {
+        eventToElement.put(e, addResultRow(e.name()));
+      }
+      add(layout);
+    }
+
+    @Override
+    public void onBrowserEvent(Event event) {
+      switch (event.getTypeInt()) {
+        case Event.ONMOUSEDOWN:
+          if (isCloseBoxEvent(event)) {
+            maybeClose = true;
+            return;
+          }
+        case Event.ONMOUSEUP:
+          if (maybeClose && isCloseBoxEvent(event)) {
+            maybeClose = false;
+            hide();
+            return;
+          }
+      }
+      maybeClose = false;
+      super.onBrowserEvent(event);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onMouseDown(Widget sender, int x, int y) {
+      pass(VisibleEvents.mouseDown);
+      super.onMouseDown(sender, x, y);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onMouseEnter(Widget sender) {
+      pass(VisibleEvents.mouseEnter);
+      sender.getElement().getStyle().setProperty("background", "yellow");
+      super.onMouseEnter(sender);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onMouseLeave(Widget sender) {
+      pass(VisibleEvents.mouseLeave);
+      sender.getElement().getStyle().setProperty("background", "");
+      super.onMouseLeave(sender);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onMouseMove(Widget sender, int x, int y) {
+      pass(VisibleEvents.mouseMove);
+      super.onMouseMove(sender, x, y);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Override
+    public void onMouseUp(Widget sender, int x, int y) {
+      pass(VisibleEvents.mouseUp);
+      super.onMouseUp(sender, x, y);
+    }
+
+    public void pass(VisibleEvents event) {
+      eventToElement.get(event).setInnerHTML(
+          "<span style='color:green'>pass</span>");
+    }
+
+    private Element addResultRow(String eventName) {
+      int row = layout.getRowCount();
+      layout.setHTML(row, 0, eventName);
+      layout.setHTML(row, 1, "<span style='color:red'>?</span>");
+      Element cell = layout.getCellFormatter().getElement(row, 1);
+      return cell;
+    }
+
+    private boolean isCloseBoxEvent(Event event) {
+      return Document.get().getElementById("vis-closebox").isOrHasChild(
+          event.getTarget());
+    }
+  }
+
+  @Override
+  public Widget createIssue() {
+    final VisibleDialogBox dialog = showVisibleDialog();
+
+    SimplePanel panel = new SimplePanel() {
+      @Override
+      protected void onUnload() {
+        dialog.hide();
+      }
+    };
+
+    return panel;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Confirm color change on mouse over caption, that the "
+        + "custom close box works, and that each mouse event fires.";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Legacy mouse event callbacks fire";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  private VisibleDialogBox showVisibleDialog() {
+    final VisibleDialogBox dialog = new VisibleDialogBox();
+    dialog.setModal(false);
+    dialog.center();
+    dialog.getCaption().addMouseDownHandler(new MouseDownHandler() {
+      public void onMouseDown(MouseDownEvent event) {
+        dialog.pass(VisibleEvents.captionMouseDown);
+      }
+    });
+
+    return dialog;
+  }
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDisclosurePanelEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDisclosurePanelEvents.java
new file mode 100644
index 0000000..772e923
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForDisclosurePanelEvents.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.DisclosureEvent;
+import com.google.gwt.user.client.ui.DisclosureHandler;
+import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Testing disclosure events.
+ */
+@SuppressWarnings("deprecation")
+public class VisualsForDisclosurePanelEvents extends AbstractIssue {
+
+  VerticalPanel report = new VerticalPanel();
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+
+    p.add(createDisclosurePanel("disclose 1"));
+    p.add(createDisclosurePanel("disclose 2"));
+    p.add(report);
+    report("reporting");
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Click on disclosure panel, see the expected Open and Close events firing";
+  }
+
+  @Override
+  public String getSummary() {
+    return "DisclosurePanel event tests";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  DisclosurePanel createDisclosurePanel(final String name) {
+    DisclosurePanel widget = new DisclosurePanel();
+    widget.setContent(new HTML("content for " + name));
+    widget.setTitle(name);
+    widget.setHeader(new CheckBox(name));
+    class MyHandler implements DisclosureHandler, OpenHandler<DisclosurePanel>,
+        CloseHandler<DisclosurePanel> {
+
+      public void onClose(CloseEvent<DisclosurePanel> event) {
+        report(event);
+      }
+
+      public void onClose(DisclosureEvent event) {
+        report(name + "close");
+      }
+
+      public void onOpen(DisclosureEvent event) {
+        report(name + "open");
+      }
+
+      public void onOpen(OpenEvent<DisclosurePanel> event) {
+        report(event);
+      }
+    }
+    MyHandler handler = new MyHandler();
+    widget.addCloseHandler(handler);
+    widget.addOpenHandler(handler);
+    widget.addEventHandler(handler);
+    return widget;
+  }
+
+  private void report(GwtEvent<?> event) {
+    String title = ((UIObject) event.getSource()).getTitle();
+    report(title + " fired " + event.toDebugString());
+  }
+
+  // will be replaced by logging
+  private void report(String s) {
+    report.insert(new Label(s), 0);
+    if (report.getWidgetCount() == 10) {
+      report.remove(9);
+    }
+  }
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForEventsFiring.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForEventsFiring.java
new file mode 100644
index 0000000..8450fd9
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForEventsFiring.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ContextMenuEvent;
+import com.google.gwt.event.dom.client.ContextMenuHandler;
+import com.google.gwt.event.dom.client.DoubleClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickHandler;
+import com.google.gwt.event.dom.client.ErrorEvent;
+import com.google.gwt.event.dom.client.ErrorHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasContextMenuHandlers;
+import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.ScrollEvent;
+import com.google.gwt.event.dom.client.ScrollHandler;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.HasVerticalAlignment;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Verify that events fire in all browsers.
+ */
+public class VisualsForEventsFiring extends AbstractIssue {
+  private static class CustomImage extends Image implements
+      HasDoubleClickHandlers, HasContextMenuHandlers {
+    public HandlerRegistration addContextMenuHandler(ContextMenuHandler handler) {
+      return addDomHandler(handler, ContextMenuEvent.getType());
+    }
+
+    public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) {
+      return addDomHandler(handler, DoubleClickEvent.getType());
+    }
+  }
+
+  private static final int WINDOW_EVENT_SCROLL = -1;
+  private static final int WINDOW_EVENT_RESIZE = -2;
+  private static final int WINDOW_EVENT_CLOSING = -3;
+
+  /**
+   * The main grid used for layout.
+   */
+  private FlexTable layout = null;
+
+  private Map<Integer, Integer> eventMap = new HashMap<Integer, Integer>();
+
+  @Override
+  public Widget createIssue() {
+    // Create a grid to hold all of the tests
+    eventMap.clear();
+    layout = new FlexTable();
+    layout.setCellPadding(3);
+    layout.setBorderWidth(2);
+    layout.setHTML(0, 0, "<b>Action to Perform</b>");
+    layout.setHTML(0, 1, "<b>Event</b>");
+    layout.setHTML(0, 2, "<b>Status</b>");
+
+    prepMouseEvents();
+    prepKeyboardEvents();
+    prepSrollAndMouseWheelEvents();
+    prepLoadEvents();
+    prepWindowEvents();
+
+    // The following are not testable or not supported in all browsers
+    // onlosecapture
+
+    return layout;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Use the Widgets below to verify that all events fire in all "
+        + "browsers.  To test an event, perform the action require to trigger "
+        + "the event using the provided widget.";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Events fire in current browsers";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  /**
+   * Add a test that is dependent on a previous test.
+   * 
+   * @param eventType the type of event defined in {@link Event}
+   * @param eventName the name of the event
+   */
+  private void addDependentTest(int eventType, String eventName) {
+    // Find the last test
+    int numRows = layout.getRowCount();
+    eventMap.put(new Integer(eventType), new Integer(numRows));
+    for (int i = numRows - 1; i > 0; i--) {
+      if (layout.getCellCount(i) == 3) {
+        FlexCellFormatter formatter = layout.getFlexCellFormatter();
+        int rowSpan = formatter.getRowSpan(i, 0);
+        formatter.setRowSpan(i, 0, rowSpan + 1);
+        break;
+      }
+    }
+    layout.setText(numRows, 0, eventName);
+    layout.setText(numRows, 1, "?");
+  }
+
+  /**
+   * Add a new test that tests one or more events.
+   * 
+   * @param eventType the type of event defined in {@link Event}
+   * @param eventName the name of the event
+   * @param trigger the widget that triggers the events
+   */
+  private void addTest(int eventType, String eventName, Widget trigger) {
+    int numRows = layout.getRowCount();
+    eventMap.put(new Integer(eventType), new Integer(numRows));
+    layout.setWidget(numRows, 0, trigger);
+    layout.setText(numRows, 1, eventName);
+    layout.setText(numRows, 2, "?");
+
+    FlexCellFormatter formatter = layout.getFlexCellFormatter();
+    formatter.setVerticalAlignment(numRows, 0,
+        HasVerticalAlignment.ALIGN_MIDDLE);
+    formatter.setHorizontalAlignment(numRows, 0,
+        HasHorizontalAlignment.ALIGN_CENTER);
+  }
+
+  /**
+   * Mark the event as passed.
+   * 
+   * @param event the event that was triggered
+   */
+  private void passTest(Event event) {
+    passTest(event.getTypeInt());
+  }
+
+  /**
+   * Mark the event as passed.
+   * 
+   * @param eventType the event type that was triggered
+   */
+  private void passTest(int eventType) {
+    int rowIndex = eventMap.get(new Integer(eventType));
+    if (layout.getCellCount(rowIndex) == 3) {
+      layout.setHTML(rowIndex, 2, "pass");
+    } else {
+      layout.setHTML(rowIndex, 1, "pass");
+    }
+  }
+
+  private void prepKeyboardEvents() {
+    // Setup a text box to trigger the events
+    TextBox textBox = new TextBox();
+
+    // Setup the tests
+    textBox.setText("Type a letter");
+    addTest(Event.ONKEYDOWN, "keydown", textBox);
+    addDependentTest(Event.ONKEYPRESS, "keypress");
+    addDependentTest(Event.ONKEYUP, "keyup");
+    addDependentTest(Event.ONFOCUS, "focus");
+    addDependentTest(Event.ONBLUR, "blur");
+    addDependentTest(Event.ONCHANGE, "change");
+
+    // Add event handlers
+    textBox.addKeyDownHandler(new KeyDownHandler() {
+      public void onKeyDown(KeyDownEvent event) {
+        event.isAutoRepeat();
+        event.isAltKeyDown();
+        event.isControlKeyDown();
+        event.isShiftKeyDown();
+        event.isMetaKeyDown();
+        assert event.getNativeKeyCode() > 0;
+        passTest(event.getNativeEvent());
+      }
+    });
+    textBox.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
+        event.isAltKeyDown();
+        event.isControlKeyDown();
+        event.isShiftKeyDown();
+        event.isMetaKeyDown();
+        assert event.getNativeKeyCode() > 0;
+        passTest(event.getNativeEvent());
+      }
+    });
+    textBox.addKeyPressHandler(new KeyPressHandler() {
+      public void onKeyPress(KeyPressEvent event) {
+        event.isAltKeyDown();
+        event.isControlKeyDown();
+        event.isShiftKeyDown();
+        event.isMetaKeyDown();
+        assert event.getCharCode() > 0;
+        passTest(event.getNativeEvent());
+      }
+    });
+    textBox.addFocusHandler(new FocusHandler() {
+      public void onFocus(FocusEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    textBox.addBlurHandler(new BlurHandler() {
+      public void onBlur(BlurEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    textBox.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+  }
+
+  private void prepLoadEvents() {
+    // Create an image to trigger events
+    final CustomImage loadable = new CustomImage();
+
+    // Setup the tests
+    addTest(Event.ONERROR, "error", loadable);
+    addDependentTest(Event.ONLOAD, "load");
+    addDependentTest(Event.ONCONTEXTMENU, "contextMenu");
+    addDependentTest(Event.ONDBLCLICK, "dblclick");
+
+    // Add the handlers
+    loadable.addErrorHandler(new ErrorHandler() {
+      public void onError(ErrorEvent event) {
+        loadable.setUrl("issues/images/gwtLogo.png");
+        passTest(event.getNativeEvent());
+      }
+    });
+    loadable.addLoadHandler(new LoadHandler() {
+      public void onLoad(LoadEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    loadable.addDoubleClickHandler(new DoubleClickHandler() {
+      public void onDoubleClick(DoubleClickEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    loadable.addContextMenuHandler(new ContextMenuHandler() {
+      public void onContextMenu(ContextMenuEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+
+    // Trigger the events
+    loadable.setUrl("imageDoesNotExist.abc");
+  }
+
+  private void prepMouseEvents() {
+    // Create a button to trigger events
+    Button button = new Button("Click me") {
+      @Override
+      public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+
+        // Verify that values associated with events are defined. For some
+        // values, we just want to make sure we can get them without any
+        // errors.
+        assert event.getClientX() > 0;
+        assert event.getClientY() > 0;
+        assert event.getScreenX() > 0;
+        assert event.getScreenY() > 0;
+        event.getAltKey();
+        event.getCtrlKey();
+        event.getShiftKey();
+        event.getMetaKey();
+      }
+    };
+
+    // Setup the tests
+    addTest(Event.ONCLICK, "click", button);
+    addDependentTest(Event.ONMOUSEDOWN, "mousedown");
+    addDependentTest(Event.ONMOUSEUP, "mouseup");
+    addDependentTest(Event.ONMOUSEOVER, "mouseover");
+    addDependentTest(Event.ONMOUSEOUT, "mouseout");
+    addDependentTest(Event.ONMOUSEMOVE, "mousemove");
+
+    // Add event handlers
+    button.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    button.addMouseDownHandler(new MouseDownHandler() {
+      public void onMouseDown(MouseDownEvent event) {
+        event.getNativeButton();
+        passTest(event.getNativeEvent());
+      }
+    });
+    button.addMouseUpHandler(new MouseUpHandler() {
+      public void onMouseUp(MouseUpEvent event) {
+        event.getNativeButton();
+        passTest(event.getNativeEvent());
+      }
+    });
+    button.addMouseMoveHandler(new MouseMoveHandler() {
+      public void onMouseMove(MouseMoveEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+    button.addMouseOutHandler(new MouseOutHandler() {
+      public void onMouseOut(MouseOutEvent event) {
+        assert event.getFromElement() != null;
+        assert event.getToElement() != null;
+        passTest(event.getNativeEvent());
+      }
+    });
+    button.addMouseOverHandler(new MouseOverHandler() {
+      public void onMouseOver(MouseOverEvent event) {
+        assert event.getFromElement() != null;
+        assert event.getToElement() != null;
+        passTest(event.getNativeEvent());
+      }
+    });
+  }
+
+  private void prepSrollAndMouseWheelEvents() {
+    // Create a widget to trigger events
+    String scrollableMessage = "Scroll to the bottom<br>(using mouse wheel<br>"
+        + "if supported)";
+    HTML scrollableContents = new HTML(scrollableMessage);
+    scrollableContents.setPixelSize(400, 400);
+    scrollableContents.getElement().getStyle().setProperty("textAlign",
+        "left");
+    ScrollPanel scrollable = new ScrollPanel(scrollableContents) {
+      @Override
+      public void onBrowserEvent(Event event) {
+        super.onBrowserEvent(event);
+
+        // Verify that values associated with events are defined
+        if (event.getTypeInt() == Event.ONMOUSEWHEEL) {
+          event.getClientX();
+          event.getClientY();
+          event.getScreenX();
+          event.getScreenY();
+          event.getMouseWheelVelocityY();
+          passTest(event);
+        }
+      }
+    };
+    scrollable.sinkEvents(Event.ONMOUSEWHEEL);
+
+    // Setup the tests
+    scrollable.setAlwaysShowScrollBars(true);
+    scrollable.setPixelSize(200, 100);
+    addTest(Event.ONSCROLL, "scroll", scrollable);
+    addDependentTest(Event.ONMOUSEWHEEL, "mousewheel");
+
+    // Add event handlers
+    scrollable.addScrollHandler(new ScrollHandler() {
+      public void onScroll(ScrollEvent event) {
+        passTest(event.getNativeEvent());
+      }
+    });
+  }
+
+  private void prepWindowEvents() {
+    Label windowLabel = new Label("Window level events");
+
+    // Setup the tests
+    addTest(WINDOW_EVENT_SCROLL, "window.onscroll", windowLabel);
+    addDependentTest(WINDOW_EVENT_RESIZE, "window.onresize");
+    addDependentTest(WINDOW_EVENT_CLOSING, "window.onbeforeunload");
+
+    // Add event handlers
+    Window.addWindowScrollHandler(new Window.ScrollHandler() {
+      public void onWindowScroll(Window.ScrollEvent event) {
+        passTest(WINDOW_EVENT_SCROLL);
+      }
+    });
+    Window.addResizeHandler(new ResizeHandler() {
+      public void onResize(ResizeEvent event) {
+        passTest(WINDOW_EVENT_RESIZE);
+      }
+    });
+    Window.addWindowClosingHandler(new Window.ClosingHandler() {
+      public void onWindowClosing(Window.ClosingEvent event) {
+        event.setMessage("Stay and verify that window.onbeforeunload() has passed");
+        passTest(WINDOW_EVENT_CLOSING);
+      }
+    });
+  }
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForMenuEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForMenuEvents.java
new file mode 100644
index 0000000..d11371a
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForMenuEvents.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.EventReporter;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.MenuBar;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A simple test for suggest box events.
+ */
+@SuppressWarnings("deprecation")
+public class VisualsForMenuEvents extends AbstractIssue {
+
+  HorizontalPanel report = new HorizontalPanel();
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+
+    createMenu(p);
+    report.setBorderWidth(3);
+
+    report.setCellWidth(report.getWidget(0), "300px");
+
+    p.add(report);
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open and close menu items and see that you get close events";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Menu event tests";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  void createMenu(Panel p) {
+    final EventReporter<Object, PopupPanel> reporter = new EventReporter<Object, PopupPanel>(
+        report);
+    Command command = new Command() {
+
+      public void execute() {
+        reporter.report("menu item selected");
+      }
+
+    };
+
+    MenuBar main = new MenuBar();
+    main.setTitle("Main");
+    p.add(main);
+    MenuBar barA = new MenuBar();
+    barA.setTitle("A");
+    CloseHandler<PopupPanel> handler = new CloseHandler<PopupPanel>() {
+
+      public void onClose(CloseEvent<PopupPanel> event) {
+        reporter.report("closed popup belonging to Main");
+      }
+
+    };
+    main.addCloseHandler(handler);
+    barA.addItem("a1", command);
+    barA.addItem("a2", command);
+
+    handler = new CloseHandler<PopupPanel>() {
+
+      public void onClose(CloseEvent<PopupPanel> event) {
+        reporter.report("closed popup belonging to A");
+      }
+
+    };
+    barA.addCloseHandler(handler);
+    MenuBar barB = new MenuBar();
+    barB.setTitle("B");
+    barB.addItem("b1", command);
+    barB.addItem("b2", command);
+
+    handler = new CloseHandler<PopupPanel>() {
+
+      public void onClose(CloseEvent<PopupPanel> event) {
+        reporter.report("closed popup belonging to B");
+      }
+
+    };
+    barB.addCloseHandler(handler);
+    MenuBar barC = new MenuBar();
+    barC.addItem("c1", command);
+    barC.addItem("c2", command);
+
+    handler = new CloseHandler<PopupPanel>() {
+
+      public void onClose(CloseEvent<PopupPanel> event) {
+        reporter.report("closed popup belonging to c");
+      }
+
+    };
+    barC.addCloseHandler(handler);
+    barC.setTitle("C");
+
+    handler = new CloseHandler<PopupPanel>() {
+
+      public void onClose(CloseEvent<PopupPanel> event) {
+        reporter.report("closed popup belonging to B");
+      }
+
+    };
+
+    main.addItem("A", barA);
+    barA.addItem("b", barB);
+    barB.addItem("c", barC);
+  }
+}
\ No newline at end of file
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForPopupEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForPopupEvents.java
new file mode 100644
index 0000000..ffa898a
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForPopupEvents.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A simple tree used to quickly exercise tree behavior.
+ */
+public class VisualsForPopupEvents extends AbstractIssue {
+  static int xPos = 0;
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel panel = new VerticalPanel();
+    createButton(true, true, panel);
+    createButton(true, false, panel);
+    createButton(false, true, panel);
+    createButton(false, false, panel);
+    return panel;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open and close each popup, check for the closing text in the window title";
+  }
+
+  @Override
+  public String getSummary() {
+    return "popup event visual test";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  private void createButton(boolean autoHide, boolean modal, VerticalPanel panel) {
+    final String text = " popup " + (modal ? " modal " : " non-modal ")
+        + (autoHide ? "auto hide" : " persistent");
+    panel.add(new HTML("<h2>" + text + "</h2>"));
+    final PopupPanel p = new PopupPanel(autoHide, modal);
+    p.setTitle(text);
+    Button b = new Button("show", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        p.setPopupPosition(200,
+            ((Button) event.getSource()).getAbsoluteTop() - 10);
+        p.show();
+      }
+    });
+    panel.add(b);
+    p.setWidget(new Button("hide me", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        p.hide();
+      }
+    }));
+
+    p.addCloseHandler(new CloseHandler<PopupPanel>() {
+      public void onClose(CloseEvent<PopupPanel> event) {
+        Window.setTitle("closing popup '" + p.getTitle() + "'. autohide:"
+            + event.isAutoClosed());
+      }
+    });
+  }
+}
\ No newline at end of file
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java
new file mode 100644
index 0000000..9d1dbb6
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForSuggestBoxEvents.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.EventReporter;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.SuggestBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A simple test for suggest box events.
+ */
+@SuppressWarnings("deprecation")
+public class VisualsForSuggestBoxEvents extends AbstractIssue {
+
+  HorizontalPanel report = new HorizontalPanel();
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+
+    p.add(createSuggestBox("suggest 1", p));
+    p.add(createSuggestBox("suggest 2", p));
+    report.setBorderWidth(3);
+
+    report.setCellWidth(report.getWidget(0), "300px");
+    report.setCellWidth(report.getWidget(1), "300px");
+
+    p.add(report);
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Select suggestions from suggest box, check report for events being fired";
+  }
+
+  @Override
+  public String getSummary() {
+    return "suggest box event visual test";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  SuggestBox createSuggestBox(final String suggestBoxName, Panel p) {
+
+    List<String> femaleNames = Arrays.asList(new String[] {
+        "Jamie", "Jill", "Jackie", "Susan", "Helen", "Emily", "Karen",
+        "Abigail", "Kaitlyn", "Laura", "Joanna", "Tasha"});
+    MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
+    oracle.addAll(femaleNames);
+
+    final SuggestBox b = new SuggestBox(oracle);
+    b.setTitle(suggestBoxName);
+    p.add(b);
+    final CheckBox selectsFirst = new CheckBox("Selects first suggestion");
+    selectsFirst.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
+      public void onValueChange(ValueChangeEvent<Boolean> event) {
+        b.setSelectsFirstItem(event.getValue());
+      }
+    });
+    selectsFirst.setChecked(b.getSelectsFirstItem());
+    p.add(selectsFirst);
+    final EventReporter<String, SuggestBox> handler = new EventReporter<String, SuggestBox>(
+        report);
+
+    handler.new CheckBoxEvent("KeyDown", p) {
+      HandlerRegistration reg;
+      @Override
+      public void addHandler() {
+        reg = b.addKeyDownHandler(handler);
+      }
+
+      @Override
+      public void removeHandler() {
+        reg.removeHandler();
+        reg = null;
+      }
+    };
+
+    handler.new CheckBoxEvent("ChangeListener", p) {
+
+      @Override
+      public void addHandler() {
+        b.addChangeListener(handler);
+      }
+
+      @Override
+      public void removeHandler() {
+        b.removeChangeListener(handler);
+      }
+    };
+    handler.new CheckBoxEvent("Suggestion listener", p) {
+
+      @Override
+      public void addHandler() {
+        b.addEventHandler(handler);
+      }
+
+      @Override
+      public void removeHandler() {
+        b.removeEventHandler(handler);
+      }
+    };
+
+    b.addKeyUpHandler(handler);
+    b.addKeyPressHandler(handler);
+    b.addFocusListener(handler);
+    b.addSelectionHandler(handler);
+    b.addValueChangeHandler(handler);
+    return b;
+  }
+}
\ No newline at end of file
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTableEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTableEvents.java
new file mode 100644
index 0000000..d6a2d15
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTableEvents.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.HTMLTable.Cell;
+
+/**
+ * Visual test for table events.
+ */
+public class VisualsForTableEvents extends AbstractIssue {
+  final Grid g = new Grid(5, 5);
+
+  public void fillInGrid() {
+    int row = 0;
+
+    for (int i = 0; i < 5; i++) {
+      g.setText(row, i, "click on cell in row to change");
+    }
+    ++row;
+    for (int i = 0; i < 5; i++) {
+      g.setText(row, i, "cell(0," + i + ")");
+    }
+    ++row;
+    for (int i = 0; i < 5; i++) {
+      g.setHTML(row, i, "<b>cell(1," + i + "</b>)");
+    }
+
+    ++row;
+    for (int i = 0; i < 5; i++) {
+      g.setWidget(row, i, new CheckBox("cell(1," + i + "</b>)"));
+    }
+
+    ++row;
+    for (int i = 0; i < 5; i++) {
+      final CheckBox box = new CheckBox("eventful cell(1," + i + "</b>)");
+      box.addFocusHandler(new FocusHandler() {
+        public void onFocus(FocusEvent event) {
+          Window.setTitle(box.getText() + " has focus");
+        }
+      });
+      final int index = i;
+      box.addClickHandler(new ClickHandler() {
+
+        public void onClick(ClickEvent event) {
+          g.setText(0, index, "checkbox click");
+        }
+      });
+
+      g.setWidget(row, i, box);
+    }
+  }
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+    fillInGrid();
+    p.add(g);
+    g.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        Cell cell = g.getCellForEvent(event);
+        g.setText(0, cell.getCellIndex(), "clicked on " + cell.getCellIndex()
+            + "," + cell.getRowIndex());
+      }
+
+    });
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Click on the cells";
+  }
+
+  @Override
+  public String getSummary() {
+    return "table events";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTextEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTextEvents.java
new file mode 100644
index 0000000..5bff5ec
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTextEvents.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.EventReporter;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.RichTextArea;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * Visual testing of rich text box events.
+ */
+public class VisualsForTextEvents extends AbstractIssue {
+  private VerticalPanel p = new VerticalPanel();
+
+  @SuppressWarnings("deprecation")
+  @Override
+  public Widget createIssue() {
+    p.setWidth("500px");
+    p.setBorderWidth(1);
+    // TextBox
+    final TextBox b = new TextBox();
+    b.setTitle("text box");
+    p.add(b);
+    EventReporter<String, Object> handler = new EventReporter<String, Object>(p);
+    p.add(new Button("change value with event", new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        b.setValue("emily", true);
+      }
+    }));
+    b.addKeyboardListener(handler);
+    handler.addKeyHandlersTo(b);
+    b.addChangeHandler(handler);
+    b.addChangeListener(handler);
+    b.addFocusHandler(handler);
+    b.addBlurHandler(handler);
+    b.addFocusListener(handler);
+    b.addValueChangeHandler(handler);
+    b.addMouseListener(handler);
+    // Rich text box:
+    RichTextArea rich = new RichTextArea();
+    rich.setTitle("rich text box");
+    p.add(rich);
+    handler = new EventReporter<String, Object>(p);
+    rich.addKeyboardListener(handler);
+    handler.addKeyHandlersTo(rich);
+    rich.addBlurHandler(handler);
+    rich.addFocusHandler(handler);
+    rich.addClickHandler(handler);
+    rich.addClickListener(handler);
+
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "type and click into text boxes, see that correct events show up";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Text widget event tests";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TreeVisuals.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTree.java
similarity index 93%
rename from reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TreeVisuals.java
rename to reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTree.java
index aaa9f5c..fde6b1b 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/TreeVisuals.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTree.java
@@ -1,69 +1,73 @@
-/*

- * Copyright 2008 Google Inc.

- * 

- * Licensed under the Apache License, Version 2.0 (the "License"); you may not

- * use this file except in compliance with the License. You may obtain a copy of

- * the License at

- * 

- * http://www.apache.org/licenses/LICENSE-2.0

- * 

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

- * License for the specific language governing permissions and limitations under

- * the License.

- */

-

-package com.google.gwt.museum.client.defaultmuseum;

-

-import com.google.gwt.museum.client.common.AbstractIssue;

-import com.google.gwt.user.client.ui.Tree;

-import com.google.gwt.user.client.ui.TreeItem;

-import com.google.gwt.user.client.ui.VerticalPanel;

-import com.google.gwt.user.client.ui.Widget;

-

-/**

- * A simple tree used to quickly exercise tree behavior.

- */

-public class TreeVisuals extends AbstractIssue {

-

-  @Override

-  public Widget createIssue() {

-    VerticalPanel p = new VerticalPanel();

-    Tree t = new Tree();

-    TreeItem a = new TreeItem("a");

-    TreeItem b = new TreeItem(

-        "b, though this is a very, very long text field in order to trigger text wrapping bugs, if there are any such bugs currently in the tree.");

-    TreeItem ba = new TreeItem("b.a");

-    TreeItem bb = new TreeItem("b.b");

-    TreeItem bba = new TreeItem("b.b.a");

-    TreeItem bc = new TreeItem("b.c");

-    TreeItem c = new TreeItem("c");

-    t.setSelectedItem(b);

-    t.addItem(a);

-    t.addItem(b);

-    t.addItem(c);

-    b.addItem(ba);

-    b.addItem(bb);

-    bb.addItem(bba);

-    b.addItem(bc);

-    p.add(t);

-    return p;

-  }

-

-  @Override

-  public String getInstructions() {

-    return "Open each node, make sure everything looks right";

-  }

-

-  @Override

-  public String getSummary() {

-    return "simple tree, used for generic tree tests";

-  }

-

-  @Override

-  public boolean hasCSS() {

-    return false;

-  }

-

-}

+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeItem;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A simple tree used to quickly exercise tree behavior.
+ */
+public class VisualsForTree extends AbstractIssue {
+  public static Tree createTree() {
+    Tree t = new Tree();
+    TreeItem a = new TreeItem("a");
+    TreeItem b = new TreeItem(
+        "b, though this is a very, very long text field in order to trigger text wrapping bugs, if there are any such bugs currently in the tree.");
+    TreeItem ba = new TreeItem("b.a");
+    TreeItem bb = new TreeItem("b.b");
+    TreeItem bba = new TreeItem("b.b.a");
+    TreeItem bc = new TreeItem("b.c");
+    TreeItem c = new TreeItem("c");
+
+    t.setSelectedItem(b);
+    t.addItem(a);
+    t.addItem(b);
+    t.addItem(c);
+    b.addItem(ba);
+    b.addItem(bb);
+    bb.addItem(bba);
+    b.addItem(bc);
+    return t;
+  }
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+    p.add(createTree());
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open each node, make sure everything looks right";
+  }
+
+  @Override
+  public String getSummary() {
+    return "simple tree, used for generic tree tests";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTreeEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTreeEvents.java
new file mode 100644
index 0000000..601eb05
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForTreeEvents.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.museum.client.common.EventReporter;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.TreeItem;
+import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+/**
+ * A simple tree used to quickly exercise tree behavior.
+ */
+public class VisualsForTreeEvents extends AbstractIssue {
+
+  @Override
+  public Widget createIssue() {
+    VerticalPanel p = new VerticalPanel();
+    Tree t = VisualsForTree.createTree();
+    p.add(t);
+    EventReporter<Object, TreeItem> handler = new EventReporter<Object, TreeItem>(
+        p);
+    t.addKeyboardListener(handler);
+    t.addMouseListener(handler);
+
+    t.addSelectionHandler(new SelectionHandler<TreeItem>() {
+      public void onSelection(SelectionEvent<TreeItem> event) {
+        Window.setTitle("select " + prettyPrint(event.getSelectedItem()));
+      }
+    });
+
+    t.addCloseHandler(new CloseHandler<TreeItem>() {
+
+      public void onClose(CloseEvent<TreeItem> event) {
+        Window.setTitle("close " + prettyPrint(event.getTarget()));
+      }
+
+    });
+
+    t.addOpenHandler(new OpenHandler<TreeItem>() {
+
+      public void onOpen(OpenEvent<TreeItem> event) {
+        Window.setTitle("open " + prettyPrint(event.getTarget()));
+      }
+
+    });
+
+    return p;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Open each node, ensure you see the right events in the window title";
+  }
+
+  @Override
+  public String getSummary() {
+    return "Event Tree tests";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  private String prettyPrint(TreeItem item) {
+    return item.getText();
+  }
+
+}
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java
new file mode 100644
index 0000000..56fffb6
--- /dev/null
+++ b/reference/code-museum/src/com/google/gwt/museum/client/defaultmuseum/VisualsForWindowEvents.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.museum.client.defaultmuseum;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.museum.client.common.AbstractIssue;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.Window.ClosingEvent;
+import com.google.gwt.user.client.Window.ScrollEvent;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+import java.util.ArrayList;
+
+/**
+ * Simple visual test for checking up on window events with Handlers.
+ */
+public class VisualsForWindowEvents extends AbstractIssue implements
+    CloseHandler<Window>, Window.ClosingHandler, Window.ScrollHandler,
+    ResizeHandler {
+  static int numResizes = 0;
+
+  private ArrayList<HandlerRegistration> registrations = new ArrayList<HandlerRegistration>();
+  private FlowPanel messages = new FlowPanel();
+
+  @Override
+  public Widget createIssue() {
+    FlowPanel out = new FlowPanel();
+
+    FlowPanel body = new FlowPanel();
+    FlowPanel buttons = new FlowPanel();
+
+    Button addHandlersButton = new Button("Add window handlers.");
+    addHandlersButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        setupWindowHandlers();
+      }
+    });
+
+    Button removeHandlersButton = new Button("Remove window handlers.");
+    removeHandlersButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        removeWindowHandlers();
+      }
+    });
+
+    Button clearButton = new Button("Clear events");
+    clearButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        messages.clear();
+      }
+    });
+
+    buttons.add(addHandlersButton);
+    buttons.add(removeHandlersButton);
+    buttons.add(clearButton);
+
+    body.add(buttons);
+    body.add(messages);
+
+    out.add(body);
+
+    return out;
+  }
+
+  @Override
+  public String getInstructions() {
+    return "Click on the button to add all the window handlers. "
+        + "Then click the other button to remove them all. "
+        + "With handlers enabled, you should get messages for scrolling or "
+        + "resizing the window, a \"do you want to navigate away?\" message"
+        + "if you're about to navigate away, and an alert when you do navigate"
+        + "away or close the window.";
+  }
+
+  @Override
+  public String getSummary() {
+    return "window events";
+  }
+
+  @Override
+  public boolean hasCSS() {
+    return false;
+  }
+
+  public void onClose(CloseEvent<Window> event) {
+    Window.alert("Closing the window.");
+  }
+
+  public void onResize(ResizeEvent event) {
+    Window.setTitle("Got resize " + numResizes++);
+  }
+
+  public void onWindowClosing(ClosingEvent event) {
+    event.setMessage("Are you sure you want to navigate away?");
+  }
+
+  public void onWindowScroll(ScrollEvent event) {
+    addMessage("Got a window scroll!");
+  }
+
+  private void addMessage(String msg) {
+    messages.add(new Label(msg));
+  }
+
+  private void removeWindowHandlers() {
+    for (HandlerRegistration reg : registrations) {
+      reg.removeHandler();
+    }
+  }
+
+  private void setupWindowHandlers() {
+    registrations.add(Window.addCloseHandler(this));
+    registrations.add(Window.addResizeHandler(this));
+    registrations.add(Window.addWindowClosingHandler(this));
+    registrations.add(Window.addWindowScrollHandler(this));
+  }
+}
\ No newline at end of file
diff --git a/reference/code-museum/src/com/google/gwt/museum/client/viewer/Museum.java b/reference/code-museum/src/com/google/gwt/museum/client/viewer/Museum.java
index b8e07e6..c934a9c 100644
--- a/reference/code-museum/src/com/google/gwt/museum/client/viewer/Museum.java
+++ b/reference/code-museum/src/com/google/gwt/museum/client/viewer/Museum.java
@@ -18,6 +18,12 @@
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.LinkElement;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
 import com.google.gwt.museum.client.common.AbstractIssue;
 import com.google.gwt.museum.client.common.Utility;
 import com.google.gwt.user.client.DeferredCommand;
@@ -25,8 +31,6 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
 import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -38,9 +42,8 @@
 import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.SuggestBox;
 import com.google.gwt.user.client.ui.SuggestOracle;
-import com.google.gwt.user.client.ui.SuggestionEvent;
-import com.google.gwt.user.client.ui.SuggestionHandler;
 import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -189,14 +192,13 @@
     };
 
     SuggestBox box = new SuggestBox(oracle);
-    box.addEventHandler(new SuggestionHandler() {
-      public void onSuggestionSelected(SuggestionEvent event) {
-        AbstractIssue issue = ((IssueSuggestion) event.getSelectedSuggestion()).getIssue();
+    box.addSelectionHandler(new SelectionHandler<Suggestion>() {
+      public void onSelection(SelectionEvent<Suggestion> event) {
+        AbstractIssue issue = ((IssueSuggestion) event.getSelectedItem()).getIssue();
         int index = issues.indexOf(issue);
         issueList.setSelectedIndex(index);
         refreshIssue();
       }
-
     });
     box.setAnimationEnabled(false);
     return box;
@@ -212,15 +214,15 @@
     for (AbstractIssue issue : issues) {
       issueList.addItem(issue.getHeadline());
     }
-    issueList.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    issueList.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         refreshIssue();
       }
     });
 
     // Create a button to refresh the current issue
-    Button refreshIssueButton = new Button("Refresh", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button refreshIssueButton = new Button("Refresh", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         refreshIssue();
       }
     });
@@ -231,8 +233,8 @@
     // Create a button to move to the previous issue
     Image prevButton = IMAGES.prevButton().createImage();
     prevButton.setStyleName("prevButton");
-    prevButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    prevButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         int selectedIndex = issueList.getSelectedIndex();
         if (selectedIndex > 0) {
           issueList.setSelectedIndex(selectedIndex - 1);
@@ -246,8 +248,8 @@
     // Create a button to move to the next issue
     Image nextButton = IMAGES.nextButton().createImage();
     nextButton.setStyleName("nextButton");
-    nextButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    nextButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         int selectedIndex = issueList.getSelectedIndex();
         if (selectedIndex < issueList.getItemCount() - 1) {
           issueList.setSelectedIndex(selectedIndex + 1);
diff --git a/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DayFilterWidget.java b/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DayFilterWidget.java
index c91b1eb..674d739 100644
--- a/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DayFilterWidget.java
+++ b/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DayFilterWidget.java
@@ -15,9 +15,10 @@
  */
 package com.google.gwt.sample.dynatable.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HasAlignment;
 import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -39,17 +40,20 @@
       // Remember custom data for this widget.
       this.day = day;
 
-      // Use a shared listener to save memory.
-      addClickListener(dayCheckBoxListener);
+      // Use a shared handler to save memory.
+      addClickHandler(dayCheckBoxHandler);
 
       // Initialize based on the calendar's current value.
       setChecked(calendar.getDayIncluded(day));
     }
   }
 
-  private class DayCheckBoxListener implements ClickListener {
-    public void onClick(Widget sender) {
-      DayCheckBox dayCheckBox = ((DayCheckBox) sender);
+  private class DayCheckBoxHandler implements ClickHandler {
+    public void onClick(ClickEvent event) {
+      onClick((DayCheckBox) event.getSource());
+    }
+    
+    public void onClick(DayCheckBox dayCheckBox) {
       calendar.setDayIncluded(dayCheckBox.day, dayCheckBox.isChecked());
     }
   }
@@ -58,7 +62,7 @@
 
   private final VerticalPanel outer = new VerticalPanel();
 
-  private final DayCheckBoxListener dayCheckBoxListener = new DayCheckBoxListener();
+  private final DayCheckBoxHandler dayCheckBoxHandler = new DayCheckBoxHandler();
 
   public DayFilterWidget(SchoolCalendarWidget calendar) {
     this.calendar = calendar;
@@ -72,14 +76,14 @@
     outer.add(new DayCheckBox("Friday", 5));
     outer.add(new DayCheckBox("Saturday", 6));
 
-    Button buttonAll = new Button("All", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button buttonAll = new Button("All", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         setAllCheckBoxes(true);
       }
     });
 
-    Button buttonNone = new Button("None", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button buttonNone = new Button("None", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         setAllCheckBoxes(false);
       }
     });
@@ -99,7 +103,7 @@
       Widget w = outer.getWidget(i);
       if (w instanceof DayCheckBox) {
         ((DayCheckBox) w).setChecked(checked);
-        dayCheckBoxListener.onClick(w);
+        dayCheckBoxHandler.onClick((DayCheckBox) w);
       }
     }
   }
diff --git a/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DynaTableWidget.java b/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DynaTableWidget.java
index a0367e0..6d19391 100644
--- a/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DynaTableWidget.java
+++ b/samples/dynatable/src/com/google/gwt/sample/dynatable/client/DynaTableWidget.java
@@ -15,10 +15,11 @@
  */
 package com.google.gwt.sample.dynatable.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.sample.dynatable.client.DynaTableDataProvider.RowDataAcceptor;
 import com.google.gwt.user.client.rpc.InvocationException;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.DockPanel;
@@ -27,7 +28,6 @@
 import com.google.gwt.user.client.ui.HasAlignment;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * A composite Widget that implements the main interface for the dynamic table,
@@ -38,7 +38,7 @@
   /**
    * A dialog box for displaying an error.
    */
-  private static class ErrorDialog extends DialogBox implements ClickListener {
+  private static class ErrorDialog extends DialogBox implements ClickHandler {
     private HTML body = new HTML("");
 
     public ErrorDialog() {
@@ -56,7 +56,7 @@
       return body.getHTML();
     }
 
-    public void onClick(Widget sender) {
+    public void onClick(ClickEvent event) {
       hide();
     }
 
@@ -65,7 +65,7 @@
     }
   }
 
-  private class NavBar extends Composite implements ClickListener {
+  private class NavBar extends Composite implements ClickHandler {
 
     public final DockPanel bar = new DockPanel();
     public final Button gotoFirst = new Button("&lt;&lt;", this);
@@ -96,17 +96,18 @@
       gotoFirst.setEnabled(false);
     }
 
-    public void onClick(Widget sender) {
-      if (sender == gotoNext) {
+    public void onClick(ClickEvent event) {
+      Object source = event.getSource();
+      if (source == gotoNext) {
         startRow += getDataRowCount();
         refresh();
-      } else if (sender == gotoPrev) {
+      } else if (source == gotoPrev) {
         startRow -= getDataRowCount();
         if (startRow < 0) {
           startRow = 0;
         }
         refresh();
-      } else if (sender == gotoFirst) {
+      } else if (source == gotoFirst) {
         startRow = 0;
         refresh();
       }
diff --git a/samples/hello/src/com/google/gwt/sample/hello/client/Hello.java b/samples/hello/src/com/google/gwt/sample/hello/client/Hello.java
index 877d2da..8ad7aec 100644
--- a/samples/hello/src/com/google/gwt/sample/hello/client/Hello.java
+++ b/samples/hello/src/com/google/gwt/sample/hello/client/Hello.java
@@ -16,11 +16,11 @@
 package com.google.gwt.sample.hello.client;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * HelloWorld application.
@@ -28,8 +28,8 @@
 public class Hello implements EntryPoint {
 
   public void onModuleLoad() {
-    Button b = new Button("Click me", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button b = new Button("Click me", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("Hello, AJAX");
       }
     });
diff --git a/samples/i18n/src/com/google/gwt/sample/i18n/client/AbstractFormatExampleController.java b/samples/i18n/src/com/google/gwt/sample/i18n/client/AbstractFormatExampleController.java
index 30c4852..a4c7437 100644
--- a/samples/i18n/src/com/google/gwt/sample/i18n/client/AbstractFormatExampleController.java
+++ b/samples/i18n/src/com/google/gwt/sample/i18n/client/AbstractFormatExampleController.java
@@ -15,13 +15,14 @@
  */
 package com.google.gwt.sample.i18n.client;
 
-import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.user.client.ui.HasText;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
 
 import java.util.Map;
 
@@ -63,18 +64,16 @@
       HasText error);
 
   private void initWidgetsForInput() {
-    txtInput.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    txtInput.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         tryToParseInput(false);
       }
     });
   }
 
   private void initWidgetsForPattern(Map<String, String> patternMap) {
-    txtCurrentPattern.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    txtCurrentPattern.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         String pattern = txtCurrentPattern.getText();
 
         // Update the active pattern.
@@ -90,10 +89,10 @@
       lstSamplePatterns.addItem(caption, patternKey);
     }
 
-    lstSamplePatterns.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    lstSamplePatterns.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         syncPatternToList();
-      }
+             }
     });
 
     lstSamplePatterns.setSelectedIndex(0);
diff --git a/samples/i18n/src/com/google/gwt/sample/i18n/client/ConstantsWithLookupExampleController.java b/samples/i18n/src/com/google/gwt/sample/i18n/client/ConstantsWithLookupExampleController.java
index 7d08296..86808bc 100644
--- a/samples/i18n/src/com/google/gwt/sample/i18n/client/ConstantsWithLookupExampleController.java
+++ b/samples/i18n/src/com/google/gwt/sample/i18n/client/ConstantsWithLookupExampleController.java
@@ -16,9 +16,9 @@
 package com.google.gwt.sample.i18n.client;
 
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
 
 import java.util.MissingResourceException;
 
@@ -42,9 +42,8 @@
     txtResult.setText(constants.noInputResult());
     txtResult.setReadOnly(true);
 
-    txtInput.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    txtInput.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         maybeRefreshLookup(constants);
       }
     });
diff --git a/samples/i18n/src/com/google/gwt/sample/i18n/client/MessagesExampleController.java b/samples/i18n/src/com/google/gwt/sample/i18n/client/MessagesExampleController.java
index c984419..7970e12 100644
--- a/samples/i18n/src/com/google/gwt/sample/i18n/client/MessagesExampleController.java
+++ b/samples/i18n/src/com/google/gwt/sample/i18n/client/MessagesExampleController.java
@@ -16,10 +16,10 @@
 package com.google.gwt.sample.i18n.client;
 
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * Demonstrates how to use {@link com.google.gwt.i18n.client.Messages}.
@@ -49,16 +49,15 @@
     String messageTemplate = ERRORS.permissionDenied("{0}", "{1}", "{2}");
     lblMessageTemplate.setText(messageTemplate);
 
-    KeyboardListenerAdapter listener = new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    KeyUpHandler handler = new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         maybeRefreshFormattedMessage();
       }
     };
-    txtArg1.addKeyboardListener(listener);
-    txtArg2.addKeyboardListener(listener);
-    txtArg3.addKeyboardListener(listener);
-    pluralCount.addKeyboardListener(listener);
+    txtArg1.addKeyUpHandler(handler);
+    txtArg2.addKeyUpHandler(handler);
+    txtArg3.addKeyUpHandler(handler);
+    pluralCount.addKeyUpHandler(handler);
 
     txtArg1.setText("amelie");
     txtArg2.setText("guest");
diff --git a/samples/json/src/com/google/gwt/sample/json/client/JSON.java b/samples/json/src/com/google/gwt/sample/json/client/JSON.java
index 6a77746..7c20f98 100644
--- a/samples/json/src/com/google/gwt/sample/json/client/JSON.java
+++ b/samples/json/src/com/google/gwt/sample/json/client/JSON.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.sample.json.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.http.client.Request;
 import com.google.gwt.http.client.RequestBuilder;
 import com.google.gwt.http.client.RequestCallback;
@@ -28,11 +30,9 @@
 import com.google.gwt.json.client.JSONValue;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.Tree;
 import com.google.gwt.user.client.ui.TreeItem;
-import com.google.gwt.user.client.ui.Widget;
 
 import java.util.Set;
 
@@ -73,8 +73,8 @@
   /*
    * Class for handling the fetch button's click event.
    */
-  private class SearchButtonClickListener implements ClickListener {
-    public void onClick(Widget sender) {
+  private class SearchButtonHandler implements ClickHandler {
+    public void onClick(ClickEvent event) {
       jsonTree.setVisible(false);
       doFetchURL();
     }
@@ -84,8 +84,11 @@
    * Default URL to use to fetch JSON objects. Note that the contents of this
    * JSON result were as a result of requesting the following URL:
    * 
-   * http://api.search.yahoo.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=potato&results=2&output=json
    * 
+   * 
+   * 
+   * http://api.search.yahoo.com/ImageSearchService/V1/imageSearch?appid=YahooDemo
+   * &query=potato&results=2&output=json
    */
   private static final String DEFAULT_SEARCH_URL = "search-results.js";
 
@@ -206,7 +209,7 @@
   private void initializeMainForm() {
     searchButton.setStyleName("JSON-SearchButton");
     searchButton.setText(SEARCH_BUTTON_DEFAULT_TEXT);
-    searchButton.addClickListener(new SearchButtonClickListener());
+    searchButton.addClickHandler(new SearchButtonHandler());
 
     // Avoids showing an "empty" cell
     jsonTree.setVisible(false);
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java b/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
index a6299a5..f371ee0 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/AboutDialog.java
@@ -15,13 +15,13 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.KeyboardListener;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * A simple example of an 'about' dialog box.
@@ -44,10 +44,10 @@
     text.setStyleName("mail-AboutText");
     outer.add(text);
 
-    // Create the 'OK' button, along with a listener that hides the dialog
+    // Create the 'OK' button, along with a handler that hides the dialog
     // when the button is clicked.
-    outer.add(new Button("Close", new ClickListener() {
-      public void onClick(Widget sender) {
+    outer.add(new Button("Close", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         hide();
       }
     }));
@@ -60,8 +60,8 @@
     // Use the popup's key preview hooks to close the dialog when either
     // enter or escape is pressed.
     switch (key) {
-      case KeyboardListener.KEY_ENTER:
-      case KeyboardListener.KEY_ESCAPE:
+      case KeyCodes.KEY_ENTER:
+      case KeyCodes.KEY_ESCAPE:
         hide();
         break;
     }
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java b/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
index fec1a78..799463c 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Contacts.java
@@ -15,8 +15,9 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -25,8 +26,6 @@
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.SimplePanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.ImageBundle.Resource;
 
 /**
  * A component that displays a list of contacts.
@@ -114,9 +113,9 @@
         + "</a>");
     panel.add(link);
 
-    // Add a click listener that displays a ContactPopup when it is clicked.
-    link.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    // Add a click handler that displays a ContactPopup when it is clicked.
+    link.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         ContactPopup popup = new ContactPopup(contact);
         int left = link.getAbsoluteLeft() + 14;
         int top = link.getAbsoluteTop() + 14;
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java b/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
index a530cca..2995159 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/Mail.java
@@ -17,10 +17,11 @@
 
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.WindowResizeListener;
 import com.google.gwt.user.client.ui.DockPanel;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
@@ -30,7 +31,7 @@
  * interface, similar to many common email readers. It has no back-end,
  * populating its components with hard-coded data.
  */
-public class Mail implements EntryPoint, WindowResizeListener {
+public class Mail implements EntryPoint, ResizeHandler {
 
   private static Mail singleton;
 
@@ -71,7 +72,7 @@
 
   /**
    * This method constructs the application user interface by instantiating
-   * controls and hooking up event listeners.
+   * controls and hooking up event handler.
    */
   public void onModuleLoad() {
     singleton = this;
@@ -101,7 +102,7 @@
     outer.setCellWidth(rightPanel, "100%");
 
     // Hook the window resize event, so that we can adjust the UI.
-    Window.addWindowResizeListener(this);
+    Window.addResizeHandler(this);
 
     // Get rid of scrollbars, and clear out the window's built-in margin,
     // because we want to take advantage of the entire client area.
@@ -124,6 +125,10 @@
     onWindowResized(Window.getClientWidth(), Window.getClientHeight());
   }
 
+  public void onResize(ResizeEvent event) {
+    onWindowResized(event.getWidth(), event.getHeight());
+  }
+
   public void onWindowResized(int width, int height) {
     // Adjust the shortcut panel and detail area to take up the available room
     // in the window.
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java b/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
index 7b10bc8..92f8330 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/MailList.java
@@ -15,19 +15,17 @@
  */
 package com.google.gwt.sample.mail.client;
 
-import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.SourcesTableEvents;
-import com.google.gwt.user.client.ui.TableListener;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * A composite that displays a list of emails that can be selected.
  */
-public class MailList extends Composite implements TableListener, ClickListener {
+public class MailList extends Composite implements ClickHandler {
 
   private static final int VISIBLE_EMAIL_COUNT = 10;
 
@@ -47,9 +45,9 @@
     table.setWidth("100%");
 
     // Hook up events.
-    table.addTableListener(this);
-    newerButton.addClickListener(this);
-    olderButton.addClickListener(this);
+    table.addClickHandler(this);
+    newerButton.addClickHandler(this);
+    olderButton.addClickHandler(this);
 
     // Create the 'navigation' bar at the upper-right.
     HorizontalPanel innerNavBar = new HorizontalPanel();
@@ -69,14 +67,8 @@
     update();
   }
 
-  public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
-    // Select the row that was clicked (-1 to account for header row).
-    if (row > 0) {
-      selectRow(row - 1);
-    }
-  }
-
-  public void onClick(Widget sender) {
+  public void onClick(ClickEvent event) {
+    Object sender = event.getSource();
     if (sender == olderButton) {
       // Move forward a page.
       startIndex += VISIBLE_EMAIL_COUNT;
@@ -97,6 +89,12 @@
         selectedRow = -1;
         update();
       }
+    } else if (sender == table) {
+      // Select the row that was clicked (-1 to account for header row).
+      int row = table.getCellForEvent(event).getRowIndex();
+      if (row > 0) {
+        selectRow(row - 1);
+      }
     }
   }
 
diff --git a/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java b/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
index 7618146..0d6d178 100644
--- a/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
+++ b/samples/mail/src/com/google/gwt/sample/mail/client/TopPanel.java
@@ -15,21 +15,21 @@
  */
 package com.google.gwt.sample.mail.client;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.ImageBundle;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 /**
  * The top panel, which contains the 'welcome' message and various links.
  */
-public class TopPanel extends Composite implements ClickListener {
+public class TopPanel extends Composite implements ClickHandler {
 
   /**
    * An image bundle for this widgets images.
@@ -61,15 +61,16 @@
     inner.add(new HTML("<b>Welcome back, foo@example.com</b>"));
     inner.add(links);
 
-    signOutLink.addClickListener(this);
-    aboutLink.addClickListener(this);
+    signOutLink.addClickHandler(this);
+    aboutLink.addClickHandler(this);
 
     initWidget(outer);
     setStyleName("mail-TopPanel");
     links.setStyleName("mail-TopPanelLinks");
   }
 
-  public void onClick(Widget sender) {
+  public void onClick(ClickEvent event) {
+    Object sender = event.getSource();
     if (sender == signOutLink) {
       Window.alert("If this were implemented, you would be signed out now.");
     } else if (sender == aboutLink) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
index dbc326d..2791dcc 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Application.java
@@ -16,9 +16,13 @@
 package com.google.gwt.sample.showcase.client;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.WindowResizeListener;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DecoratorPanel;
@@ -33,7 +37,6 @@
 import com.google.gwt.user.client.ui.Tree;
 import com.google.gwt.user.client.ui.TreeImages;
 import com.google.gwt.user.client.ui.TreeItem;
-import com.google.gwt.user.client.ui.TreeListener;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
@@ -44,17 +47,28 @@
  * some external links at the top.
  * </p>
  * <h3>CSS Style Rules</h3>
+ * 
  * <ul class="css">
+ * 
  * <li>.Application { Applied to the entire Application }</li>
+ * 
  * <li>.Application-top { The top portion of the Application }</li>
+ * 
  * <li>.Application-title { The title widget }</li>
+ * 
  * <li>.Application-links { The main external links }</li>
+ * 
  * <li>.Application-options { The options widget }</li>
+ * 
  * <li>.Application-menu { The main menu }</li>
- * <li>.Application-content-wrapper { The scrollable element around the content }</li>
+ * 
+ * <li>.Application-content-wrapper { The scrollable element around the content
+ * }</li>
+ * 
  * </ul>
  */
-public class Application extends Composite implements WindowResizeListener {
+public class Application extends Composite implements ResizeHandler,
+    HasSelectionHandlers<TreeItem> {
   /**
    * Images used in the {@link Application}.
    */
@@ -69,18 +83,6 @@
   }
 
   /**
-   * A listener to handle events from the Application.
-   */
-  public interface ApplicationListener {
-    /**
-     * Fired when a menu item is selected.
-     * 
-     * @param item the item that was selected
-     */
-    void onMenuItemSelected(com.google.gwt.user.client.ui.TreeItem item);
-  }
-
-  /**
    * The base style name.
    */
   public static final String DEFAULT_STYLE_NAME = "Application";
@@ -111,11 +113,6 @@
   private HorizontalPanel linksPanel;
 
   /**
-   * The {@link ApplicationListener}.
-   */
-  private ApplicationListener listener = null;
-
-  /**
    * The main menu.
    */
   private Tree mainMenu;
@@ -179,6 +176,9 @@
     contentLayout.setWidget(1, 0, contentWrapper);
     formatter.setStyleName(1, 0, DEFAULT_STYLE_NAME + "-content-wrapper");
     setContent(null);
+
+    // Add a window resize handler
+    Window.addResizeHandler(this);
   }
 
   /**
@@ -193,6 +193,11 @@
     linksPanel.add(link);
   }
 
+  public HandlerRegistration addSelectionHandler(
+      SelectionHandler<TreeItem> handler) {
+    return mainMenu.addSelectionHandler(handler);
+  }
+
   /**
    * @return the {@link Widget} in the content area
    */
@@ -221,8 +226,12 @@
     return topPanel.getWidget(0, 0);
   }
 
+  public void onResize(ResizeEvent event) {
+    onWindowResized(event.getWidth(), event.getHeight());
+  }
+
   public void onWindowResized(int width, int height) {
-    if (width == windowWidth) {
+    if (width == windowWidth || width < 1) {
       return;
     }
     windowWidth = width;
@@ -252,15 +261,6 @@
   }
 
   /**
-   * Set the {@link ApplicationListener}.
-   * 
-   * @param listener the listener
-   */
-  public void setListener(ApplicationListener listener) {
-    this.listener = listener;
-  }
-
-  /**
    * Set the {@link Widget} to use as options, which appear to the right of the
    * title bar.
    * 
@@ -282,14 +282,12 @@
   @Override
   protected void onLoad() {
     super.onLoad();
-    Window.addWindowResizeListener(this);
     onWindowResized(Window.getClientWidth(), Window.getClientHeight());
   }
 
   @Override
   protected void onUnload() {
     super.onUnload();
-    Window.removeWindowResizeListener(this);
     windowWidth = -1;
   }
 
@@ -312,16 +310,6 @@
     mainMenu = new Tree(treeImages);
     mainMenu.setAnimationEnabled(true);
     mainMenu.addStyleName(DEFAULT_STYLE_NAME + "-menu");
-    mainMenu.addTreeListener(new TreeListener() {
-      public void onTreeItemSelected(TreeItem item) {
-        if (listener != null) {
-          listener.onMenuItemSelected(item);
-        }
-      }
-
-      public void onTreeItemStateChanged(TreeItem item) {
-      }
-    });
   }
 
   /**
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
index f89e59b..9d656ad 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/ContentWidget.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.sample.showcase.client;
 
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
 import com.google.gwt.http.client.Request;
 import com.google.gwt.http.client.RequestBuilder;
 import com.google.gwt.http.client.RequestCallback;
@@ -29,9 +31,7 @@
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.DeckPanel;
 import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.SourcesTabEvents;
 import com.google.gwt.user.client.ui.TabBar;
-import com.google.gwt.user.client.ui.TabListener;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -59,7 +59,8 @@
  * <li>.sc-ContentWidget-description { Applied to the description }</li>
  * </ul>
  */
-public abstract class ContentWidget extends Composite implements TabListener {
+public abstract class ContentWidget extends Composite implements
+    SelectionHandler<Integer> {
   /**
    * The constants used in this Content Widget.
    */
@@ -193,8 +194,8 @@
     if (initialized == false) {
       initialized = true;
 
-      // Add a tab listener
-      tabBar.addTabListener(this);
+      // Add a tab handler
+      tabBar.addSelectionHandler(this);
 
       // Create a container for the main example
       final VerticalPanel vPanel = new VerticalPanel();
@@ -243,10 +244,6 @@
     }
   }
 
-  public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
-    return true;
-  }
-
   /**
    * When the widget is first initialize, this method is called. If it returns a
    * Widget, the widget will be added as the first tab. Return null to disable
@@ -263,8 +260,9 @@
   public void onInitializeComplete() {
   }
 
-  public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
+  public void onSelection(SelectionEvent<Integer> event) {
     // Show the associated widget in the deck panel
+    int tabIndex = event.getSelectedItem().intValue();
     deckPanel.showWidget(tabIndex);
 
     // Load the source code
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
index e56d898..f00e966 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/Showcase.java
@@ -21,8 +21,15 @@
 import com.google.gwt.dom.client.HeadElement;
 import com.google.gwt.dom.client.Node;
 import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.sample.showcase.client.Application.ApplicationListener;
 import com.google.gwt.sample.showcase.client.content.i18n.CwConstantsExample;
 import com.google.gwt.sample.showcase.client.content.i18n.CwConstantsWithLookupExample;
 import com.google.gwt.sample.showcase.client.content.i18n.CwDateTimeFormat;
@@ -60,11 +67,8 @@
 import com.google.gwt.sample.showcase.client.content.widgets.CwRadioButton;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.HistoryListener;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
@@ -76,7 +80,6 @@
 import com.google.gwt.user.client.ui.Tree;
 import com.google.gwt.user.client.ui.TreeItem;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -130,7 +133,7 @@
           }
         }
 
-        // Fire the click listeners
+        // Fire the click handlers
         super.onClick();
       }
     }
@@ -154,17 +157,17 @@
   private static native String getHostPageLocation()
   /*-{
     var s = $doc.location.href;
-  
+
     // Pull off any hash.
     var i = s.indexOf('#');
     if (i != -1)
       s = s.substring(0, i);
-  
+
     // Pull off any query string.
     i = s.indexOf('?');
     if (i != -1)
       s = s.substring(0, i);
-  
+
     // Ensure a final slash if non-empty.
     return s;
   }-*/;
@@ -203,10 +206,10 @@
     setupOptionsPanel();
     setupMainMenu(constants);
 
-    // Setup a history listener to reselect the associate menu item
-    final HistoryListener historyListener = new HistoryListener() {
-      public void onHistoryChanged(String historyToken) {
-        TreeItem item = itemTokens.get(historyToken);
+    // Setup a history handler to reselect the associate menu item
+    final ValueChangeHandler<String> historyHandler = new ValueChangeHandler<String>() {
+      public void onValueChange(ValueChangeEvent<String> event) {
+        TreeItem item = itemTokens.get(event.getValue());
         if (item == null) {
           item = app.getMainMenu().getItem(0).getChild(0);
         }
@@ -219,11 +222,12 @@
         displayContentWidget(itemWidgets.get(item));
       }
     };
-    History.addHistoryListener(historyListener);
+    History.addValueChangeHandler(historyHandler);
 
-    // Add an listener that sets the content widget when a menu item is selected
-    app.setListener(new ApplicationListener() {
-      public void onMenuItemSelected(TreeItem item) {
+    // Add a handler that sets the content widget when a menu item is selected
+    app.addSelectionHandler(new SelectionHandler<TreeItem>() {
+      public void onSelection(SelectionEvent<TreeItem> event) {
+        TreeItem item = event.getSelectedItem();
         ContentWidget content = itemWidgets.get(item);
         if (content != null && !content.equals(app.getContent())) {
           History.newItem(getContentWidgetToken(content));
@@ -232,9 +236,8 @@
     });
 
     // Show the initial example
-    String initToken = History.getToken();
-    if (initToken.length() > 0) {
-      historyListener.onHistoryChanged(initToken);
+    if (History.getToken().length() > 0) {
+      History.fireCurrentHistoryState();
     } else {
       // Use the first token available
       TreeItem firstItem = app.getMainMenu().getItem(0).getChild(0);
@@ -440,8 +443,8 @@
         }
       }
     }
-    localeBox.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    localeBox.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         String localeName = localeBox.getValue(localeBox.getSelectedIndex());
         Window.open(getHostPageLocation() + "?locale=" + localeName, "_self",
             "");
@@ -459,8 +462,8 @@
       final ThemeButton button = new ThemeButton(
           ShowcaseConstants.STYLE_THEMES[i]);
       styleWrapper.add(button);
-      button.addClickListener(new ClickListener() {
-        public void onClick(Widget sender) {
+      button.addClickHandler(new ClickHandler() {
+        public void onClick(ClickEvent event) {
           // Update the current theme
           CUR_THEME = button.getTheme();
 
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsExample.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsExample.java
index 6db6ae0..42d5ab1 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsExample.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsExample.java
@@ -17,6 +17,9 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseConstants;
@@ -24,12 +27,10 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseRaw;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.SourcesTabEvents;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
@@ -124,8 +125,8 @@
     // Add a link to the source code of the Interface
     HTML link = new HTML(
         " <a href=\"javascript:void(0);\">ExampleConstants</a>");
-    link.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    link.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         selectTab(2);
       }
     });
@@ -171,9 +172,10 @@
   }
 
   @Override
-  public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
-    super.onTabSelected(sender, tabIndex);
+  public void onSelection(SelectionEvent<Integer> event) {
+    super.onSelection(event);
 
+    int tabIndex = event.getSelectedItem().intValue();
     if (!javaLoaded && tabIndex == 2) {
       // Load ErrorMessages.java
       javaLoaded = true;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsWithLookupExample.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsWithLookupExample.java
index 38e55db..574c873 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsWithLookupExample.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwConstantsWithLookupExample.java
@@ -17,6 +17,11 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseConstants;
@@ -24,12 +29,9 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseRaw;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
-import com.google.gwt.user.client.ui.SourcesTabEvents;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
@@ -148,8 +150,8 @@
 
     // Add a link to the source code of the Interface
     HTML link = new HTML(" <a href=\"javascript:void(0);\">ColorConstants</a>");
-    link.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    link.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         selectTab(2);
       }
     });
@@ -174,10 +176,9 @@
     layout.setHTML(2, 0, constants.cwConstantsWithLookupExampleResults());
     layout.setWidget(2, 1, colorResultsBox);
 
-    // Add a listener to update the color as the user types a lookup value
-    colorBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    // Add a handler to update the color as the user types a lookup value
+    colorBox.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         updateColor();
       }
     });
@@ -193,9 +194,10 @@
   }
 
   @Override
-  public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
-    super.onTabSelected(sender, tabIndex);
+  public void onSelection(SelectionEvent<Integer> event) {
+    super.onSelection(event);
 
+    int tabIndex = event.getSelectedItem().intValue();
     if (!javaLoaded && tabIndex == 2) {
       // Load ErrorMessages.java
       javaLoaded = true;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
index 7789094..677bcb9 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwDateTimeFormat.java
@@ -17,6 +17,10 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.i18n.client.DateTimeFormat;
 import com.google.gwt.sample.showcase.client.ContentWidget;
@@ -24,10 +28,8 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.TextBox;
@@ -137,8 +139,8 @@
     for (String pattern : patterns) {
       patternList.addItem(pattern);
     }
-    patternList.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    patternList.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         updatePattern();
       }
     });
@@ -148,24 +150,26 @@
     // Add a field to display the pattern
     patternBox = new TextBox();
     patternBox.setWidth("17em");
-    patternBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    patternBox.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         updatePattern();
       }
     });
+
     layout.setWidget(1, 1, patternBox);
 
     // Add a field to set the value
     valueBox = new TextBox();
     valueBox.setWidth("17em");
     valueBox.setText("13 September 1999 12:34:56");
-    valueBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    valueBox.addKeyUpHandler(new KeyUpHandler() {
+
+      public void onKeyUp(KeyUpEvent event) {
         updateFormattedValue();
       }
+
     });
+
     layout.setHTML(2, 0, constants.cwDateTimeFormatValueLabel());
     layout.setWidget(2, 1, valueBox);
 
@@ -213,6 +217,7 @@
   /**
    * Update the formatted value based on the user entered value and pattern.
    */
+  @SuppressWarnings("deprecation")
   @ShowcaseSource
   private void updateFormattedValue() {
     String sValue = valueBox.getText();
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwMessagesExample.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwMessagesExample.java
index 11e771b..6e58216 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwMessagesExample.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwMessagesExample.java
@@ -17,6 +17,11 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseConstants;
@@ -24,13 +29,10 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseRaw;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
-import com.google.gwt.user.client.ui.SourcesTabEvents;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
@@ -162,8 +164,8 @@
 
     // Add a link to the source code of the Interface
     HTML link = new HTML(" <a href=\"javascript:void(0);\">ErrorMessages</a>");
-    link.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    link.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         selectTab(2);
       }
     });
@@ -203,16 +205,15 @@
     layout.setWidget(5, 1, formattedMessage);
     formatter.setVerticalAlignment(5, 0, HasVerticalAlignment.ALIGN_TOP);
 
-    // Add listeners to all of the argument boxes
-    KeyboardListenerAdapter keyListener = new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    // Add handlers to all of the argument boxes
+    KeyUpHandler keyUpHandler = new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         updateMessage();
       }
     };
-    arg0Box.addKeyboardListener(keyListener);
-    arg1Box.addKeyboardListener(keyListener);
-    arg2Box.addKeyboardListener(keyListener);
+    arg0Box.addKeyUpHandler(keyUpHandler);
+    arg1Box.addKeyUpHandler(keyUpHandler);
+    arg2Box.addKeyUpHandler(keyUpHandler);
 
     // Return the layout Widget
     updateMessage();
@@ -225,9 +226,10 @@
   }
 
   @Override
-  public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
-    super.onTabSelected(sender, tabIndex);
+  public void onSelection(SelectionEvent<Integer> event) {
+    super.onSelection(event);
 
+    int tabIndex = event.getSelectedItem().intValue();
     if (!javaLoaded && tabIndex == 2) {
       // Load ErrorMessages.java
       javaLoaded = true;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwNumberFormat.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwNumberFormat.java
index 32ac953..b90490b 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwNumberFormat.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/i18n/CwNumberFormat.java
@@ -17,6 +17,10 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.i18n.client.NumberFormat;
 import com.google.gwt.sample.showcase.client.ContentWidget;
@@ -24,9 +28,7 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.TextBox;
@@ -132,8 +134,8 @@
     for (String pattern : patterns) {
       patternList.addItem(pattern);
     }
-    patternList.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    patternList.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         updatePattern();
       }
     });
@@ -143,9 +145,8 @@
     // Add a field to display the pattern
     patternBox = new TextBox();
     patternBox.setWidth("17em");
-    patternBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    patternBox.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         updatePattern();
       }
     });
@@ -155,9 +156,8 @@
     valueBox = new TextBox();
     valueBox.setWidth("17em");
     valueBox.setText("31415926535.897932");
-    valueBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    valueBox.addKeyUpHandler(new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         updateFormattedValue();
       }
     });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwListBox.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwListBox.java
index 2a98d82..ed632cc 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwListBox.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwListBox.java
@@ -17,13 +17,14 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.ListBox;
@@ -118,9 +119,9 @@
     multiBoxPanel.add(multiBox);
     hPanel.add(multiBoxPanel);
 
-    // Add a listener to handle drop box events
-    dropBox.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    // Add a handler to handle drop box events
+    dropBox.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         showCategory(multiBox, dropBox.getSelectedIndex());
         multiBox.ensureDebugId("cwListBox-multiBox");
       }
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
index cbe4706..08050f9 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwStackPanel.java
@@ -25,7 +25,8 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
 import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.user.client.ui.DecoratedStackPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
@@ -211,8 +212,8 @@
       contactsPanel.add(contactLink);
 
       // Open the contact info popup when the user clicks a contact
-      contactLink.addClickListener(new ClickListener() {
-        public void onClick(Widget sender) {
+      contactLink.addClickHandler(new ClickHandler() {
+        public void onClick(ClickEvent event) {
           // Set the info about the contact
           contactInfo.setHTML(contactName + "<br><i>" + contactEmail + "</i>");
 
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
index 62f480b..a17ae8a 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/lists/CwTree.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
@@ -30,7 +32,6 @@
 import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.Tree;
 import com.google.gwt.user.client.ui.TreeItem;
-import com.google.gwt.user.client.ui.TreeListener;
 import com.google.gwt.user.client.ui.Widget;
 
 /**
@@ -202,13 +203,11 @@
       item.addItem("");
     }
 
-    // Add a listener that automatically generates some children
-    dynamicTree.addTreeListener(new TreeListener() {
-      public void onTreeItemSelected(TreeItem item) {
-      }
-
-      public void onTreeItemStateChanged(TreeItem item) {
-        if (item.getState() && item.getChildCount() == 1) {
+    // Add a handler that automatically generates some children
+    dynamicTree.addOpenHandler(new OpenHandler<TreeItem>() {
+      public void onOpen(OpenEvent<TreeItem> event) {
+        TreeItem item = event.getTarget();
+        if (item.getChildCount() == 1) {
           // Close the item immediately
           item.setState(false, false);
 
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
index 409a587..aeb6509 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwAnimation.java
@@ -26,7 +26,8 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.AbsolutePanel;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.user.client.ui.DecoratorPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
@@ -273,8 +274,8 @@
 
     // Add start button
     startButton = new Button(constants.cwAnimationStart());
-    startButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    startButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         animation.run(2000);
       }
     });
@@ -282,8 +283,8 @@
 
     // Add cancel button
     cancelButton = new Button(constants.cwAnimationCancel());
-    cancelButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    cancelButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         animation.cancel();
       }
     });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwCookies.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwCookies.java
index b660bb8..68ecdcc 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwCookies.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwCookies.java
@@ -17,6 +17,10 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
@@ -27,8 +31,6 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.TextBox;
@@ -148,9 +150,9 @@
     mainLayout.setWidget(2, 1, cookieValueBox);
     mainLayout.setWidget(2, 2, setCookieButton);
 
-    // Add a listener to set the cookie value
-    setCookieButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    // Add a handler to set the cookie value
+    setCookieButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         String name = cookieNameBox.getText();
         String value = cookieValueBox.getText();
         Date expires = new Date((new Date()).getTime() + COOKIE_TIMEOUT);
@@ -167,16 +169,16 @@
       }
     });
 
-    // Add a listener to select an existing cookie
-    existingCookiesBox.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    // Add a handler to select an existing cookie
+    existingCookiesBox.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         updateExstingCookie();
       }
     });
 
-    // Add a listener to delete an existing cookie
-    deleteCookieButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    // Add a handler to delete an existing cookie
+    deleteCookieButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         int selectedIndex = existingCookiesBox.getSelectedIndex();
         if (selectedIndex > -1
             && selectedIndex < existingCookiesBox.getItemCount()) {
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwFrame.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwFrame.java
index b6dbcb3..2e14568 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwFrame.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/other/CwFrame.java
@@ -17,16 +17,19 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Frame;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
@@ -101,20 +104,20 @@
     optionsPanel.add(setLocationButton);
 
     // Change the location when the user clicks the button
-    setLocationButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    setLocationButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         frame.setUrl(locationBox.getText());
       }
     });
 
     // Change the location when the user presses enter
-    locationBox.addKeyboardListener(new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyPress(Widget sender, char keyCode, int modifiers) {
-        if (keyCode == KEY_ENTER) {
+    locationBox.addKeyDownHandler(new KeyDownHandler() {
+      public void onKeyDown(KeyDownEvent event) {
+        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
           frame.setUrl(locationBox.getText());
         }
       }
+
     });
 
     // Add everything to a panel and return it
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
index 3342df2..e385072 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/panels/CwAbsolutePanel.java
@@ -17,6 +17,10 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.Showcase;
@@ -27,13 +31,11 @@
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.AbsolutePanel;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.DecoratorPanel;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.Widget;
@@ -237,21 +239,20 @@
     }
 
     // Set the current item position when the user selects an item
-    listBox.addChangeListener(new ChangeListener() {
-      public void onChange(Widget sender) {
+    listBox.addChangeHandler(new ChangeHandler() {
+      public void onChange(ChangeEvent event) {
         updateSelectedItem();
       }
     });
 
     // Move the item as the user changes the value in the left and top boxes
-    KeyboardListenerAdapter repositionListener = new KeyboardListenerAdapter() {
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    KeyUpHandler repositionHandler = new KeyUpHandler() {
+      public void onKeyUp(KeyUpEvent event) {
         repositionItem();
       }
     };
-    topPosBox.addKeyboardListener(repositionListener);
-    leftPosBox.addKeyboardListener(repositionListener);
+    topPosBox.addKeyUpHandler(repositionHandler);
+    leftPosBox.addKeyUpHandler(repositionHandler);
 
     // Return the options bar
     return optionsBar;
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
index 91e5c5c..3223fc1 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwBasicPopup.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.Showcase;
@@ -25,7 +27,6 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DecoratedPopupPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Image;
@@ -99,11 +100,12 @@
 
     // Create a button to show the popup
     Button openButton = new Button(constants.cwBasicPopupShowButton(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             // Reposition the popup relative to the button
-            int left = sender.getAbsoluteLeft() + 10;
-            int top = sender.getAbsoluteTop() + 10;
+            Widget source = (Widget) event.getSource();
+            int left = source.getAbsoluteLeft() + 10;
+            int top = source.getAbsoluteTop() + 10;
             simplePopup.setPopupPosition(left, top);
 
             // Show the popup
@@ -117,8 +119,8 @@
     imagePopup.setAnimationEnabled(true);
     imagePopup.ensureDebugId("cwBasicPopup-imagePopup");
     imagePopup.setWidget(jimmyFull);
-    jimmyFull.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    jimmyFull.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         imagePopup.hide();
       }
     });
@@ -127,8 +129,8 @@
     Image jimmyThumb = Showcase.images.jimmyThumb().createImage();
     jimmyThumb.ensureDebugId("cwBasicPopup-thumb");
     jimmyThumb.addStyleName("cw-BasicPopup-thumb");
-    jimmyThumb.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    jimmyThumb.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         imagePopup.center();
       }
     });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
index 9d06e55..69ab631 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/popups/CwDialogBox.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.sample.showcase.client.ContentWidget;
@@ -26,7 +28,6 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
@@ -38,7 +39,7 @@
 /**
  * Example file.
  */
-@ShowcaseStyle({
+@ShowcaseStyle(/* styles */{
     ".gwt-DialogBox", "html>body .gwt-DialogBox", "* html .gwt-DialogBox",
     ".cw-DialogBox"})
 public class CwDialogBox extends ContentWidget {
@@ -105,8 +106,8 @@
 
     // Create a button to show the dialog Box
     Button openButton = new Button(constants.cwDialogBoxShowButton(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent sender) {
             dialogBox.center();
             dialogBox.show();
           }
@@ -178,8 +179,8 @@
 
     // Add a close button at the bottom of the dialog
     Button closeButton = new Button(constants.cwDialogBoxClose(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             dialogBox.hide();
           }
         });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
index 1e41a7c..6005481 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/tables/CwFlexTable.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.Showcase;
@@ -25,7 +27,6 @@
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.HasVerticalAlignment;
@@ -103,14 +104,15 @@
 
     // Add a button that will add more rows to the table
     Button addRowButton = new Button(constants.cwFlexTableAddRow(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             addRow(flexTable);
           }
         });
+
     Button removeRowButton = new Button(constants.cwFlexTableRemoveRow(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             removeRow(flexTable);
           }
         });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java
index f2f9d3d..5d586d7 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/CwBasicText.java
@@ -17,16 +17,18 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseSource;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseStyle;
 import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PasswordTextBox;
 import com.google.gwt.user.client.ui.TextArea;
@@ -38,7 +40,8 @@
 /**
  * Example file.
  */
-@ShowcaseStyle({".gwt-TextBox", ".gwt-PasswordTextBox", ".gwt-TextArea"})
+@ShowcaseStyle(/* css style names */{
+    ".gwt-TextBox", ".gwt-PasswordTextBox", ".gwt-TextArea"})
 public class CwBasicText extends ContentWidget {
   /**
    * The constants used in this Content Widget.
@@ -145,10 +148,10 @@
 
   /**
    * Create a TextBox example that includes the text box and an optional
-   * listener that updates a Label with the currently selected text.
+   * handler that updates a Label with the currently selected text.
    * 
-   * @param textBox the text box to listen to
-   * @param addSelection add listeners to update label
+   * @param textBox the text box to handle
+   * @param addSelection add handlers to update label
    * @return the Label that will be updated
    */
   @ShowcaseSource
@@ -159,22 +162,21 @@
     hPanel.setSpacing(4);
     hPanel.add(textBox);
 
-    // Add listeners
+    // Add handlers
     if (addSelection) {
       // Create the new label
       final Label label = new Label(constants.cwBasicTextSelected() + ": 0, 0");
 
-      // Add a KeyboardListener
-      textBox.addKeyboardListener(new KeyboardListenerAdapter() {
-        @Override
-        public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+      // Add a KeyUpHandler
+      textBox.addKeyUpHandler(new KeyUpHandler() {
+        public void onKeyUp(KeyUpEvent event) {
           updateSelectionLabel(textBox, label);
         }
       });
 
-      // Add a ClickListener
-      textBox.addClickListener(new ClickListener() {
-        public void onClick(Widget sender) {
+      // Add a ClickHandler
+      textBox.addClickHandler(new ClickHandler() {
+        public void onClick(ClickEvent event) {
           updateSelectionLabel(textBox, label);
         }
       });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/RichTextToolbar.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/RichTextToolbar.java
index d9346d4..2a5816b 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/RichTextToolbar.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/text/RichTextToolbar.java
@@ -16,15 +16,18 @@
 package com.google.gwt.sample.showcase.client.content.text;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.AbstractImagePrototype;
-import com.google.gwt.user.client.ui.ChangeListener;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.ImageBundle;
-import com.google.gwt.user.client.ui.KeyboardListener;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.PushButton;
 import com.google.gwt.user.client.ui.RichTextArea;
@@ -161,13 +164,15 @@
   }
 
   /**
-   * We use an inner EventListener class to avoid exposing event methods on the
+   * We use an inner EventHandler class to avoid exposing event methods on the
    * RichTextToolbar itself.
    */
-  private class EventListener implements ClickListener, ChangeListener,
-      KeyboardListener {
+  private class EventHandler implements ClickHandler, ChangeHandler,
+      KeyUpHandler {
 
-    public void onChange(Widget sender) {
+    public void onChange(ChangeEvent event) {
+      Widget sender = (Widget) event.getSource();
+
       if (sender == backColors) {
         basic.setBackColor(backColors.getValue(backColors.getSelectedIndex()));
         backColors.setSelectedIndex(0);
@@ -183,7 +188,9 @@
       }
     }
 
-    public void onClick(Widget sender) {
+    public void onClick(ClickEvent event) {
+      Widget sender = (Widget) event.getSource();
+
       if (sender == bold) {
         basic.toggleBold();
       } else if (sender == italic) {
@@ -234,13 +241,8 @@
       }
     }
 
-    public void onKeyDown(Widget sender, char keyCode, int modifiers) {
-    }
-
-    public void onKeyPress(Widget sender, char keyCode, int modifiers) {
-    }
-
-    public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+    public void onKeyUp(KeyUpEvent event) {
+      Widget sender = (Widget) event.getSource();
       if (sender == richText) {
         // We use the RichTextArea's onKeyUp event to update the toolbar status.
         // This will catch any cases where the user moves the cursur using the
@@ -258,7 +260,7 @@
 
   private Images images = (Images) GWT.create(Images.class);
   private Strings strings = (Strings) GWT.create(Strings.class);
-  private EventListener listener = new EventListener();
+  private EventHandler handler = new EventHandler();
 
   private RichTextArea richText;
   private RichTextArea.BasicFormatter basic;
@@ -312,7 +314,8 @@
 
     if (basic != null) {
       topPanel.add(bold = createToggleButton(images.bold(), strings.bold()));
-      topPanel.add(italic = createToggleButton(images.italic(), strings.italic()));
+      topPanel.add(italic = createToggleButton(images.italic(),
+          strings.italic()));
       topPanel.add(underline = createToggleButton(images.underline(),
           strings.underline()));
       topPanel.add(subscript = createToggleButton(images.subscript(),
@@ -331,7 +334,8 @@
       topPanel.add(strikethrough = createToggleButton(images.strikeThrough(),
           strings.strikeThrough()));
       topPanel.add(indent = createPushButton(images.indent(), strings.indent()));
-      topPanel.add(outdent = createPushButton(images.outdent(), strings.outdent()));
+      topPanel.add(outdent = createPushButton(images.outdent(),
+          strings.outdent()));
       topPanel.add(hr = createPushButton(images.hr(), strings.hr()));
       topPanel.add(ol = createPushButton(images.ol(), strings.ol()));
       topPanel.add(ul = createPushButton(images.ul(), strings.ul()));
@@ -351,16 +355,16 @@
       bottomPanel.add(fonts = createFontList());
       bottomPanel.add(fontSizes = createFontSizes());
 
-      // We only use these listeners for updating status, so don't hook them up
+      // We only use these handlers for updating status, so don't hook them up
       // unless at least basic editing is supported.
-      richText.addKeyboardListener(listener);
-      richText.addClickListener(listener);
+      richText.addKeyUpHandler(handler);
+      richText.addClickHandler(handler);
     }
   }
 
   private ListBox createColorList(String caption) {
     ListBox lb = new ListBox();
-    lb.addChangeListener(listener);
+    lb.addChangeHandler(handler);
     lb.setVisibleItemCount(1);
 
     lb.addItem(caption);
@@ -375,7 +379,7 @@
 
   private ListBox createFontList() {
     ListBox lb = new ListBox();
-    lb.addChangeListener(listener);
+    lb.addChangeHandler(handler);
     lb.setVisibleItemCount(1);
 
     lb.addItem(strings.font(), "");
@@ -391,7 +395,7 @@
 
   private ListBox createFontSizes() {
     ListBox lb = new ListBox();
-    lb.addChangeListener(listener);
+    lb.addChangeHandler(handler);
     lb.setVisibleItemCount(1);
 
     lb.addItem(strings.size());
@@ -407,14 +411,14 @@
 
   private PushButton createPushButton(AbstractImagePrototype img, String tip) {
     PushButton pb = new PushButton(img.createImage());
-    pb.addClickListener(listener);
+    pb.addClickHandler(handler);
     pb.setTitle(tip);
     return pb;
   }
 
   private ToggleButton createToggleButton(AbstractImagePrototype img, String tip) {
     ToggleButton tb = new ToggleButton(img.createImage());
-    tb.addClickListener(listener);
+    tb.addClickHandler(handler);
     tb.setTitle(tip);
     return tb;
   }
@@ -436,4 +440,3 @@
     }
   }
 }
-
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwBasicButton.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwBasicButton.java
index e90f6ef..1217cd3 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwBasicButton.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwBasicButton.java
@@ -17,6 +17,8 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.Constants;
 import com.google.gwt.sample.showcase.client.ContentWidget;
 import com.google.gwt.sample.showcase.client.ShowcaseAnnotations.ShowcaseData;
@@ -25,7 +27,6 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Widget;
 
@@ -89,8 +90,8 @@
 
     // Add a normal button
     Button normalButton = new Button(constants.cwBasicButtonNormal(),
-        new ClickListener() {
-          public void onClick(Widget sender) {
+        new ClickHandler() {
+          public void onClick(ClickEvent event) {
             Window.alert(constants.cwBasicButtonClickMessage());
           }
         });
diff --git a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwFileUpload.java b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwFileUpload.java
index 6760125..f6b84f7 100644
--- a/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwFileUpload.java
+++ b/samples/showcase/src/com/google/gwt/sample/showcase/client/content/widgets/CwFileUpload.java
@@ -25,7 +25,8 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.user.client.ui.FileUpload;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.VerticalPanel;
@@ -100,8 +101,8 @@
 
     // Add a button to upload the file
     Button uploadButton = new Button(constants.cwFileUploadButton());
-    uploadButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    uploadButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         String filename = fileUpload.getFilename();
         if (filename.length() == 0) {
           Window.alert(constants.cwFileUploadNoFileError());
diff --git a/tools/api-checker/config/gwt15_16userApi.conf b/tools/api-checker/config/gwt15_16userApi.conf
index d7f65d5..e42fa8f 100644
--- a/tools/api-checker/config/gwt15_16userApi.conf
+++ b/tools/api-checker/config/gwt15_16userApi.conf
@@ -29,3 +29,5 @@
 # TODO(amitmanjhi): Solving this issue correctly in all cases seems
 # to be hard. Come back and fix this issue, if more such cases come up. 
 java.lang.StringBuilder::append(Ljava/lang/StringBuffer;) OVERRIDABLE_METHOD_ARGUMENT_TYPE_CHANGE
+com.google.gwt.user.client.ui.Button::Button(Ljava/lang/String;Lcom/google/gwt/user/client/ui/ClickListener;) OVERLOADED_METHOD_CALL
+com.google.gwt.user.client.ui.ToggleButton::ToggleButton(Lcom/google/gwt/user/client/ui/Image;Lcom/google/gwt/user/client/ui/Image;Lcom/google/gwt/user/client/ui/ClickListener;) OVERLOADED_METHOD_CALL 
diff --git a/user/javadoc/com/example/foo/client/FooTest.java b/user/javadoc/com/example/foo/client/FooTest.java
index 8f459c4..263e894 100644
--- a/user/javadoc/com/example/foo/client/FooTest.java
+++ b/user/javadoc/com/example/foo/client/FooTest.java
@@ -10,6 +10,7 @@
    * 
    * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
    */
+  @Override
   public String getModuleName() {
     return "com.example.foo.Foo";
   }
diff --git a/user/javadoc/com/google/gwt/examples/AsyncJUnitExample.java b/user/javadoc/com/google/gwt/examples/AsyncJUnitExample.java
index b45dd78..fb73afb 100644
--- a/user/javadoc/com/google/gwt/examples/AsyncJUnitExample.java
+++ b/user/javadoc/com/google/gwt/examples/AsyncJUnitExample.java
@@ -20,6 +20,7 @@
 
 public class AsyncJUnitExample extends GWTTestCase {
 
+  @Override
   public String getModuleName() {
     // TODO Auto-generated method stub
     return null;
@@ -31,6 +32,7 @@
   public void testTimer() {
     // Setup an asynchronous event handler.
     Timer timer = new Timer() {
+      @Override
       public void run() {
         // do some validation logic
 
diff --git a/user/javadoc/com/google/gwt/examples/ButtonExample.java b/user/javadoc/com/google/gwt/examples/ButtonExample.java
index 848d6cd..a6274ef 100644
--- a/user/javadoc/com/google/gwt/examples/ButtonExample.java
+++ b/user/javadoc/com/google/gwt/examples/ButtonExample.java
@@ -16,18 +16,18 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 public class ButtonExample implements EntryPoint {
 
   public void onModuleLoad() {
     // Make a new button that does something when you click it.
-    Button b = new Button("Jump!", new ClickListener() {
-      public void onClick(Widget sender) {
+    Button b = new Button("Jump!", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("How high?");
       }
     });
diff --git a/user/javadoc/com/google/gwt/examples/CheckBoxExample.java b/user/javadoc/com/google/gwt/examples/CheckBoxExample.java
index a2fdc4e..9e5eab4 100644
--- a/user/javadoc/com/google/gwt/examples/CheckBoxExample.java
+++ b/user/javadoc/com/google/gwt/examples/CheckBoxExample.java
@@ -16,11 +16,11 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 public class CheckBoxExample implements EntryPoint {
 
@@ -29,11 +29,11 @@
     CheckBox cb = new CheckBox("Foo");
     cb.setChecked(true);
 
-    // Hook up a listener to find out when it's clicked.
-    cb.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
-        boolean checked = ((CheckBox) sender).isChecked();
-        Window.alert("It is " + (checked ? "" : "not") + "checked");
+    // Hook up a handler to find out when it's clicked.
+    cb.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
+        boolean checked = ((CheckBox) event.getSource()).isChecked();
+        Window.alert("It is " + (checked ? "" : "not ") + "checked");
       }
     });
 
diff --git a/user/javadoc/com/google/gwt/examples/CompositeExample.java b/user/javadoc/com/google/gwt/examples/CompositeExample.java
index 9749a86..3c206e5 100644
--- a/user/javadoc/com/google/gwt/examples/CompositeExample.java
+++ b/user/javadoc/com/google/gwt/examples/CompositeExample.java
@@ -16,13 +16,13 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 public class CompositeExample implements EntryPoint {
 
@@ -30,7 +30,7 @@
    * A composite of a TextBox and a CheckBox that optionally enables it.
    */
   private static class OptionalTextBox extends Composite implements
-      ClickListener {
+      ClickHandler {
 
     private TextBox textBox = new TextBox();
     private CheckBox checkBox = new CheckBox();
@@ -49,7 +49,7 @@
       // Set the check box's caption, and check it by default.
       checkBox.setText(caption);
       checkBox.setChecked(true);
-      checkBox.addClickListener(this);
+      checkBox.addClickHandler(this);
 
       // All composites must call initWidget() in their constructors.
       initWidget(panel);
@@ -58,8 +58,8 @@
       setStyleName("example-OptionalCheckBox");
     }
 
-    public void onClick(Widget sender) {
-      if (sender == checkBox) {
+    public void onClick(ClickEvent event) {
+      if (event.getSource() == checkBox) {
         // When the check box is clicked, update the text box's enabled state.
         textBox.setEnabled(checkBox.isChecked());
       }
diff --git a/user/javadoc/com/google/gwt/examples/DialogBoxExample.java b/user/javadoc/com/google/gwt/examples/DialogBoxExample.java
index 08889f4..e1adac3 100644
--- a/user/javadoc/com/google/gwt/examples/DialogBoxExample.java
+++ b/user/javadoc/com/google/gwt/examples/DialogBoxExample.java
@@ -16,13 +16,13 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
-public class DialogBoxExample implements EntryPoint, ClickListener {
+public class DialogBoxExample implements EntryPoint, ClickHandler {
 
   private static class MyDialog extends DialogBox {
 
@@ -33,8 +33,8 @@
       // DialogBox is a SimplePanel, so you have to set its widget property to
       // whatever you want its contents to be.
       Button ok = new Button("OK");
-      ok.addClickListener(new ClickListener() {
-        public void onClick(Widget sender) {
+      ok.addClickHandler(new ClickHandler() {
+        public void onClick(ClickEvent event) {
           MyDialog.this.hide();
         }
       });
@@ -44,12 +44,12 @@
 
   public void onModuleLoad() {
     Button b = new Button("Click me");
-    b.addClickListener(this);
+    b.addClickHandler(this);
 
     RootPanel.get().add(b);
   }
 
-  public void onClick(Widget sender) {
+  public void onClick(ClickEvent event) {
     // Instantiate the dialog box and show it.
     new MyDialog().show();
   }
diff --git a/user/javadoc/com/google/gwt/examples/FormPanelExample.java b/user/javadoc/com/google/gwt/examples/FormPanelExample.java
index 76f7ba4..4001aa4 100644
--- a/user/javadoc/com/google/gwt/examples/FormPanelExample.java
+++ b/user/javadoc/com/google/gwt/examples/FormPanelExample.java
@@ -16,19 +16,18 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.FileUpload;
-import com.google.gwt.user.client.ui.FormHandler;
 import com.google.gwt.user.client.ui.FormPanel;
-import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
-import com.google.gwt.user.client.ui.FormSubmitEvent;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
+import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 
 public class FormPanelExample implements EntryPoint {
 
@@ -66,24 +65,25 @@
     panel.add(upload);
 
     // Add a 'submit' button.
-    panel.add(new Button("Submit", new ClickListener() {
-      public void onClick(Widget sender) {
+    panel.add(new Button("Submit", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         form.submit();
       }
     }));
 
     // Add an event handler to the form.
-    form.addFormHandler(new FormHandler() {
-      public void onSubmit(FormSubmitEvent event) {
+    form.addSubmitHandler(new FormPanel.SubmitHandler() {
+      public void onSubmit(SubmitEvent event) {
         // This event is fired just before the form is submitted. We can take
         // this opportunity to perform validation.
         if (tb.getText().length() == 0) {
           Window.alert("The text box must not be empty");
-          event.setCancelled(true);
+          event.cancel();
         }
       }
-
-      public void onSubmitComplete(FormSubmitCompleteEvent event) {
+    });
+    form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
+      public void onSubmitComplete(SubmitCompleteEvent event) {
         // When the form submission is successfully completed, this event is
         // fired. Assuming the service returned a response of type text/html,
         // we can get the result text here (see the FormPanel documentation for
diff --git a/user/javadoc/com/google/gwt/examples/HistoryExample.java b/user/javadoc/com/google/gwt/examples/HistoryExample.java
index 99f3d0f..fc8ce55 100644
--- a/user/javadoc/com/google/gwt/examples/HistoryExample.java
+++ b/user/javadoc/com/google/gwt/examples/HistoryExample.java
@@ -16,14 +16,15 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.HistoryListener;
 import com.google.gwt.user.client.ui.Hyperlink;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
-public class HistoryExample implements EntryPoint, HistoryListener {
+public class HistoryExample implements EntryPoint, ValueChangeHandler<String> {
 
   private Label lbl = new Label();
 
@@ -49,15 +50,15 @@
     RootPanel.get().add(panel);
 
     // Add history listener
-    History.addHistoryListener(this);
+    History.addValueChangeHandler(this);
 
     // Now that we've setup our listener, fire the initial history state.
     History.fireCurrentHistoryState();
   }
 
-  public void onHistoryChanged(String historyToken) {
+  public void onValueChange(ValueChangeEvent<String> event) {
     // This method is called whenever the application's history changes. Set
     // the label to reflect the current history token.
-    lbl.setText("The current history token is: " + historyToken);
+    lbl.setText("The current history token is: " + event.getValue());
   }
 }
diff --git a/user/javadoc/com/google/gwt/examples/ImageExample.java b/user/javadoc/com/google/gwt/examples/ImageExample.java
index e364909..7f3ce21 100644
--- a/user/javadoc/com/google/gwt/examples/ImageExample.java
+++ b/user/javadoc/com/google/gwt/examples/ImageExample.java
@@ -16,15 +16,16 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ErrorEvent;
+import com.google.gwt.event.dom.client.ErrorHandler;
+import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.LoadListener;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 
 public class ImageExample implements EntryPoint {
 
@@ -37,23 +38,20 @@
     // can manipulate the image object within the ClickHandlers for the buttons.
     final Image image = new Image();
 
-    // Hook up a load listener, so that we can be informed if the image fails
+    // Hook up an error handler, so that we can be informed if the image fails
     // to load.
-    image.addLoadListener(new LoadListener() {
-      public void onError(Widget sender) {
+    image.addErrorHandler(new ErrorHandler() {
+      public void onError(ErrorEvent event) {
         lbl.setText("An error occurred while loading.");
       }
-
-      public void onLoad(Widget sender) {
-      }
     });
 
     // Point the image at a real URL.
     image.setUrl("http://www.google.com/images/logo.gif");
 
     // When the user clicks this button, we want to clip the image.
-    btn.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    btn.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         image.setVisibleRect(70, 0, 47, 110);
       }
     });
@@ -61,8 +59,8 @@
 
     // When the user clicks this button, we want to restore the image to its
     // unclipped state.
-    btn2.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    btn2.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         image.setUrl("http://www.google.com/images/logo.gif");
       }
     });
diff --git a/user/javadoc/com/google/gwt/examples/PopupPanelExample.java b/user/javadoc/com/google/gwt/examples/PopupPanelExample.java
index c87945e..d2b983e 100644
--- a/user/javadoc/com/google/gwt/examples/PopupPanelExample.java
+++ b/user/javadoc/com/google/gwt/examples/PopupPanelExample.java
@@ -16,13 +16,13 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.Window;
 
 public class PopupPanelExample implements EntryPoint {
 
@@ -42,8 +42,8 @@
 
   public void onModuleLoad() {
     Button b1 = new Button("Click me to show popup");
-    b1.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    b1.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         // Instantiate the popup and show it.
         new MyPopup().show();
       }
@@ -53,8 +53,8 @@
 
     Button b2 = new Button("Click me to show popup partway across the screen");
 
-    b2.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    b2.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         // Create the new popup.
         final MyPopup popup = new MyPopup();
         // Position the popup 1/3rd of the way down and across the screen, and
diff --git a/user/javadoc/com/google/gwt/examples/PushButtonExample.java b/user/javadoc/com/google/gwt/examples/PushButtonExample.java
index 1e85063..e8d8d45 100644
--- a/user/javadoc/com/google/gwt/examples/PushButtonExample.java
+++ b/user/javadoc/com/google/gwt/examples/PushButtonExample.java
@@ -16,18 +16,18 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.PushButton;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 public class PushButtonExample implements EntryPoint {
 
   public void onModuleLoad() {
     // Make a new button that does something when you click it.
-    PushButton b = new PushButton("Jump", "Jump?", new ClickListener() {
-      public void onClick(Widget sender) {
+    PushButton b = new PushButton("Jump", "Jump?", new ClickHandler() {
+      public void onClick(ClickEvent event) {
         Window.alert("Crash...");
         Window.alert("Uh Oh...");
       }
diff --git a/user/javadoc/com/google/gwt/examples/TabBarExample.java b/user/javadoc/com/google/gwt/examples/TabBarExample.java
index b8e38d3..eecee86 100644
--- a/user/javadoc/com/google/gwt/examples/TabBarExample.java
+++ b/user/javadoc/com/google/gwt/examples/TabBarExample.java
@@ -16,11 +16,13 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
+import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.SourcesTabEvents;
 import com.google.gwt.user.client.ui.TabBar;
-import com.google.gwt.user.client.ui.TabListener;
 
 public class TabBarExample implements EntryPoint {
 
@@ -32,19 +34,19 @@
     bar.addTab("baz");
 
     // Hook up a tab listener to do something when the user selects a tab.
-    bar.addTabListener(new TabListener() {
-      public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
+    bar.addSelectionHandler(new SelectionHandler<Integer>() {
+      public void onSelection(SelectionEvent<Integer> event) {
         // Let the user know what they just did.
-        Window.alert("You clicked tab " + tabIndex);
+        Window.alert("You clicked tab " + event.getSelectedItem());
       }
-    
-      public boolean onBeforeTabSelected(SourcesTabEvents sender,
-          int tabIndex) {
+    });
 
-        // Just for fun, let's disallow selection of 'bar'.
-        if (tabIndex == 1)
-          return false;
-        return true;
+    // Just for fun, let's disallow selection of 'bar'.
+    bar.addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
+      public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
+        if (event.getItem().intValue() == 1) {
+          event.cancel();
+        }
       }
     });
 
diff --git a/user/javadoc/com/google/gwt/examples/TextBoxExample.java b/user/javadoc/com/google/gwt/examples/TextBoxExample.java
index 34c908b..1a5464b 100644
--- a/user/javadoc/com/google/gwt/examples/TextBoxExample.java
+++ b/user/javadoc/com/google/gwt/examples/TextBoxExample.java
@@ -16,33 +16,28 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
 import com.google.gwt.user.client.ui.PasswordTextBox;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.TextArea;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
 
 public class TextBoxExample implements EntryPoint {
 
   public void onModuleLoad() {
-    // Make some text boxes.  The password text box is identical to the text
+    // Make some text boxes. The password text box is identical to the text
     // box, except that the input is visually masked by the browser.
     PasswordTextBox ptb = new PasswordTextBox();
     TextBox tb = new TextBox();
 
-    // Let's disallow non-numeric entry in the normal text box.
-    tb.addKeyboardListener(new KeyboardListenerAdapter() {
-      public void onKeyPress(Widget sender, char keyCode, int modifiers) {
-        if ((!Character.isDigit(keyCode)) && (keyCode != (char) KEY_TAB)
-            && (keyCode != (char) KEY_BACKSPACE)
-            && (keyCode != (char) KEY_DELETE) && (keyCode != (char) KEY_ENTER) 
-            && (keyCode != (char) KEY_HOME) && (keyCode != (char) KEY_END)
-            && (keyCode != (char) KEY_LEFT) && (keyCode != (char) KEY_UP)
-            && (keyCode != (char) KEY_RIGHT) && (keyCode != (char) KEY_DOWN)) {
-          // TextBox.cancelKey() suppresses the current keyboard event.
-          ((TextBox)sender).cancelKey();
+    // TODO(ECC) must be tested.
+    tb.addKeyPressHandler(new KeyPressHandler() {
+
+      public void onKeyPress(KeyPressEvent event) {
+        if (!Character.isDigit(event.getCharCode())) {
+          ((TextBox) event.getSource()).cancelKey();
         }
       }
     });
diff --git a/user/javadoc/com/google/gwt/examples/TimerExample.java b/user/javadoc/com/google/gwt/examples/TimerExample.java
index a329fec..2325c2b 100644
--- a/user/javadoc/com/google/gwt/examples/TimerExample.java
+++ b/user/javadoc/com/google/gwt/examples/TimerExample.java
@@ -16,25 +16,26 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
 
-public class TimerExample implements EntryPoint, ClickListener {
+public class TimerExample implements EntryPoint, ClickHandler {
 
   public void onModuleLoad() {
     Button b = new Button("Click and wait 5 seconds");
-    b.addClickListener(this);
+    b.addClickHandler(this);
 
     RootPanel.get().add(b);
   }
 
-  public void onClick(Widget sender) {
+  public void onClick(ClickEvent event) {
     // Create a new timer that calls Window.alert().
     Timer t = new Timer() {
+      @Override
       public void run() {
         Window.alert("Nifty, eh?");
       }
diff --git a/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java b/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
index 5b119ea..f5ec7f4 100644
--- a/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
+++ b/user/javadoc/com/google/gwt/examples/ToggleButtonExample.java
@@ -16,18 +16,18 @@
 package com.google.gwt.examples;
 
 import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.ClickListener;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.ToggleButton;
-import com.google.gwt.user.client.ui.Widget;
 
 public class ToggleButtonExample implements EntryPoint {
   public void onModuleLoad() {
     // Make a new button that does something when you click it.
     final ToggleButton toggleButton = new ToggleButton("Up", "Down");
-    toggleButton.addClickListener(new ClickListener() {
-      public void onClick(Widget sender) {
+    toggleButton.addClickHandler(new ClickHandler() {
+      public void onClick(ClickEvent event) {
         if (toggleButton.isDown()) {
           Window.alert("I have been toggled down");
         } else {
diff --git a/user/javadoc/com/google/gwt/examples/benchmarks/AllocBenchmark.java b/user/javadoc/com/google/gwt/examples/benchmarks/AllocBenchmark.java
index 4e0d683..1ab1a89 100644
--- a/user/javadoc/com/google/gwt/examples/benchmarks/AllocBenchmark.java
+++ b/user/javadoc/com/google/gwt/examples/benchmarks/AllocBenchmark.java
@@ -26,6 +26,7 @@
 
   private static final int numAllocs = 1000;
 
+  @Override
   public String getModuleName() {
     return "com.google.gwt.examples.Benchmarks";
   }
diff --git a/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListAndVectorBenchmark.java b/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListAndVectorBenchmark.java
index 65f620e..a0a58ba 100644
--- a/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListAndVectorBenchmark.java
+++ b/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListAndVectorBenchmark.java
@@ -66,6 +66,7 @@
       this.label = label;
     }
 
+    @Override
     public String toString() {
       return " " + label;
     }
@@ -83,6 +84,7 @@
   Vector vector;
   int index = 0;
 
+  @Override
   public String getModuleName() {
     return "com.google.gwt.examples.Benchmarks";
   }
diff --git a/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListBenchmark.java b/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListBenchmark.java
index ffa9ada..4b95434 100644
--- a/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListBenchmark.java
+++ b/user/javadoc/com/google/gwt/examples/benchmarks/ArrayListBenchmark.java
@@ -59,6 +59,7 @@
      * 
      * @return a not <code>null</code> description.
      */
+    @Override
     public String toString() {
       return label;
     }
@@ -77,6 +78,7 @@
 
   int index = 0;
 
+  @Override
   public String getModuleName() {
     return "com.google.gwt.emultest.EmulSuite";
   }
diff --git a/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_en.java b/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_en.java
index 76787b0..e7c3436 100644
--- a/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_en.java
+++ b/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_en.java
@@ -1,6 +1,7 @@
 package com.google.gwt.examples.i18n;
 
 public class ColorNameLookup_en extends ColorNameLookup {
+  @Override
   public String lookupColorName(String htmlColorValue) {
     if ("#FF0000".equalsIgnoreCase(htmlColorValue))
       return "red";
diff --git a/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_ja.java b/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_ja.java
index 1dc50bb..1a2a628 100644
--- a/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_ja.java
+++ b/user/javadoc/com/google/gwt/examples/i18n/ColorNameLookup_ja.java
@@ -1,6 +1,7 @@
 package com.google.gwt.examples.i18n;
 
 public class ColorNameLookup_ja extends ColorNameLookup {
+  @Override
   public String lookupColorName(String htmlColorValue) {
     if ("#FF0000".equalsIgnoreCase(htmlColorValue))
       return "あか";
diff --git a/user/javadoc/com/google/gwt/examples/rpc/server/AdvancedExample.java b/user/javadoc/com/google/gwt/examples/rpc/server/AdvancedExample.java
index aec0916..ba82426 100644
--- a/user/javadoc/com/google/gwt/examples/rpc/server/AdvancedExample.java
+++ b/user/javadoc/com/google/gwt/examples/rpc/server/AdvancedExample.java
@@ -36,6 +36,7 @@
    * it also shows how mapping between and RPC interface and some other POJO
    * could be performed.
    */
+  @Override
   public void doPost(HttpServletRequest httpRequest,
       HttpServletResponse httpResponse) {
     String payload = readPayloadAsUtf8(httpRequest);
diff --git a/user/javadoc/com/google/gwt/examples/rpc/server/CanonicalExample.java b/user/javadoc/com/google/gwt/examples/rpc/server/CanonicalExample.java
index 1cebcf1..e99334d 100644
--- a/user/javadoc/com/google/gwt/examples/rpc/server/CanonicalExample.java
+++ b/user/javadoc/com/google/gwt/examples/rpc/server/CanonicalExample.java
@@ -29,6 +29,7 @@
    * Process the RPC request encoded into the payload string and return a string
    * that encodes either the method return or an exception thrown by it.
    */
+  @Override
   public String processCall(String payload) throws SerializationException {
     try {
       RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass());
diff --git a/user/src/com/google/gwt/event/Event.gwt.xml b/user/src/com/google/gwt/event/Event.gwt.xml
new file mode 100644
index 0000000..44c8ff4
--- /dev/null
+++ b/user/src/com/google/gwt/event/Event.gwt.xml
@@ -0,0 +1,6 @@
+<module>

+    <!-- This module could be broken down into much finer detail -->

+    <source path="shared"/> 

+    <source path="logical/shared"/>

+    <source path="dom/client"/> 

+</module>
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/BlurEvent.java b/user/src/com/google/gwt/event/dom/client/BlurEvent.java
new file mode 100644
index 0000000..d641d2e
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/BlurEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native blur event.

+ */

+public class BlurEvent extends DomEvent<BlurHandler> {

+

+  /**

+   * Event type for blur events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<BlurHandler> TYPE = new Type<BlurHandler>(

+      Event.ONBLUR, "blur", new BlurEvent());

+

+  /**

+   * Gets the event type associated with blur events.

+   * 

+   * @return the handler type

+   */

+  public static Type<BlurHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire blur events.

+   */

+  protected BlurEvent() {

+  }

+

+  @Override

+  protected void dispatch(BlurHandler handler) {

+    handler.onBlur(this);

+  }

+

+  @Override

+  protected final Type<BlurHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/BlurHandler.java b/user/src/com/google/gwt/event/dom/client/BlurHandler.java
new file mode 100644
index 0000000..acee53b
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/BlurHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link BlurEvent} events.
+ */
+public interface BlurHandler extends EventHandler {
+
+  /**
+   * Called when BlurEvent is fired.
+   * 
+   * @param event the {@link BlurEvent} that was fired
+   */
+  void onBlur(BlurEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/ChangeEvent.java b/user/src/com/google/gwt/event/dom/client/ChangeEvent.java
new file mode 100644
index 0000000..58b4278
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ChangeEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native change event.

+ */

+public class ChangeEvent extends DomEvent<ChangeHandler> {

+

+  /**

+   * Event type for change events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<ChangeHandler> TYPE = new Type<ChangeHandler>(

+      Event.ONCHANGE, "change", new ChangeEvent());

+

+  /**

+   * Gets the event type associated with change events.

+   * 

+   * @return the handler type

+   */

+  public static Type<ChangeHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire change events.

+   */

+  protected ChangeEvent() {

+  }

+

+  @Override

+  protected void dispatch(ChangeHandler handler) {

+    handler.onChange(this);

+  }

+

+  @Override

+  protected final Type<ChangeHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/ChangeHandler.java b/user/src/com/google/gwt/event/dom/client/ChangeHandler.java
new file mode 100644
index 0000000..2e53df7
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ChangeHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for {@link ChangeEvent} events.
+ */
+public interface ChangeHandler extends EventHandler {
+
+  /**
+   * Called when a change event is fired.
+   * 
+   * @param event the {@link ChangeEvent} that was fired
+   */
+  void onChange(ChangeEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/ClickEvent.java b/user/src/com/google/gwt/event/dom/client/ClickEvent.java
new file mode 100644
index 0000000..88f9a77
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ClickEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native click event.

+ */

+public class ClickEvent extends DomEvent<ClickHandler> {

+

+  /**

+   * Event type for click events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<ClickHandler> TYPE = new Type<ClickHandler>(

+      Event.ONCLICK, "click", new ClickEvent());

+

+  /**

+   * Gets the event type associated with click events.

+   * 

+   * @return the handler type

+   */

+  public static Type<ClickHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire click events.

+   */

+  protected ClickEvent() {

+  }

+

+  @Override

+  protected void dispatch(ClickHandler handler) {

+    handler.onClick(this);

+  }

+

+  @Override

+  protected final Type<ClickHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/ClickHandler.java b/user/src/com/google/gwt/event/dom/client/ClickHandler.java
new file mode 100644
index 0000000..341e3ae
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ClickHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for {@link ClickEvent} events.
+ */
+public interface ClickHandler extends EventHandler {
+  /**
+   * Called when a native click event is fired.
+   * 
+   * @param event the {@link ClickEvent} that was fired
+   */
+  void onClick(ClickEvent event);
+
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/ContextMenuEvent.java b/user/src/com/google/gwt/event/dom/client/ContextMenuEvent.java
new file mode 100644
index 0000000..126ed99
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ContextMenuEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.user.client.Event;
+
+/**
+ * Represents a native context menu event.
+ */
+public class ContextMenuEvent extends DomEvent<ContextMenuHandler> {
+
+  /**
+   * Event type for context menu events. Represents the meta-data associated
+   * with this event.
+   */
+  private static final Type<ContextMenuHandler> TYPE = new Type<ContextMenuHandler>(
+      Event.ONCONTEXTMENU, "contextmenu", new ContextMenuEvent());
+
+  /**
+   * Gets the event type associated with context menu events.
+   * 
+   * @return the handler type
+   */
+  public static Type<ContextMenuHandler> getType() {
+    return TYPE;
+  }
+
+  /**
+   * Protected constructor, use
+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}
+   * to fire context menu events.
+   */
+  protected ContextMenuEvent() {
+  }
+
+  @Override
+  protected void dispatch(ContextMenuHandler handler) {
+    handler.onContextMenu(this);
+  }
+
+  @Override
+  protected final Type<ContextMenuHandler> getAssociatedType() {
+    return TYPE;
+  }
+
+}
diff --git a/user/src/com/google/gwt/event/dom/client/ContextMenuHandler.java b/user/src/com/google/gwt/event/dom/client/ContextMenuHandler.java
new file mode 100644
index 0000000..a9ea479
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ContextMenuHandler.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for {@link ContextMenuEvent} events.
+ */
+public interface ContextMenuHandler extends EventHandler {
+  /**
+   * Called when a native context menu event is fired.
+   * 
+   * @param event the {@link ContextMenuEvent} that was fired
+   */
+  void onContextMenu(ContextMenuEvent event);
+}
diff --git a/user/src/com/google/gwt/event/dom/client/DomEvent.java b/user/src/com/google/gwt/event/dom/client/DomEvent.java
new file mode 100644
index 0000000..d751bdf
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/DomEvent.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.user.client.Event;
+
+/**
+ * {@link DomEvent} is a subclass of {@link GwtEvent} that provides events that
+ * map to DOM Level 2 Events. It provides an additional method to access the
+ * underlying native browser event object as well as a subclass of {@link Type}
+ * that understands GWT event bits used by sinkEvents().
+ * 
+ * @param <H> handler type
+ * 
+ */
+public abstract class DomEvent<H extends EventHandler> extends GwtEvent<H> {
+  /**
+   * Type class used by dom event subclasses. Type is specialized for dom in
+   * order to carry information about the native event.
+   * 
+   * @param <H> handler type
+   */
+  public static class Type<H extends EventHandler> extends GwtEvent.Type<H> {
+    private final int eventToSink;
+    private DomEvent<H> flyweight;
+
+    /**
+     * Constructor.
+     * 
+     * @param eventToSink the native event type to sink
+     * 
+     */
+    public Type(int eventToSink) {
+      this.eventToSink = eventToSink;
+    }
+
+    /**
+     * This constructor allows dom event types to be triggered by the
+     * {@link DomEvent#fireNativeEvent(Event, HandlerManager)} method. It should
+     * only be used by implementors supporting new dom events.
+     * <p>
+     * Any such dom event type must act as a flyweight around a native event
+     * object.
+     * </p>
+     * 
+     * 
+     * @param eventToSink the integer value used by sink events to set up event
+     * handling for this dom type
+     * @param eventName the raw native event name
+     * @param flyweight the instance that will be used as a flyweight to wrap a
+     * native event
+     */
+    protected Type(int eventToSink, String eventName, DomEvent<H> flyweight) {
+      this.flyweight = flyweight;
+      this.eventToSink = eventToSink;
+
+      // Until we have eager clinits implemented, we are manually initializing
+      // DomEvent here.
+      if (registered == null) {
+        init();
+      }
+      registered.unsafePut(eventName, this);
+    }
+
+    Type(int nativeEventTypeInt, String eventName, DomEvent<H> cached,
+        String... auxNames) {
+      this(nativeEventTypeInt, eventName, cached);
+      for (int i = 0; i < auxNames.length; i++) {
+        registered.unsafePut(auxNames[i], this);
+      }
+    }
+
+    /**
+     * Gets the integer defined by the native {@link Event} type needed to hook
+     * up event handling when the user calls
+     * {@link com.google.gwt.user.client.DOM#sinkEvents(com.google.gwt.user.client.Element, int)}
+     * .
+     * 
+     * @return the native event type
+     */
+    public int getEventToSink() {
+      return eventToSink;
+    }
+  }
+
+  private static PrivateMap<Type<?>> registered;
+ 
+  /**
+   * Fires the given native event on the specified handlers.
+   * 
+   * @param nativeEvent the native event
+   * @param handlers the event manager containing the handlers to fire (may be
+   *          null)
+   */
+  public static void fireNativeEvent(Event nativeEvent, HandlerManager handlers) {
+    assert nativeEvent != null : "nativeEvent must not be null";
+    if (registered != null && handlers != null) {
+      final DomEvent.Type<?> typeKey = registered.unsafeGet(nativeEvent.getType());
+      if (typeKey != null) {
+        // Store and restore native event just in case we are in recursive
+        // loop.
+        Event currentNative = typeKey.flyweight.nativeEvent;
+        typeKey.flyweight.setNativeEvent(nativeEvent);
+        handlers.fireEvent(typeKey.flyweight);
+        typeKey.flyweight.setNativeEvent(currentNative);
+      }
+    }
+  }
+ 
+  // This method can go away once we have eager clinits.
+  static void init() {
+    registered = new PrivateMap<Type<?>>();
+  }
+
+  private Event nativeEvent;
+
+  /**
+   * Gets the underlying native event for this {@link DomEvent}.
+   * 
+   * @return gets the native event
+   */
+  public final Event getNativeEvent() {
+    assertLive();
+    return nativeEvent;
+  }
+
+  /**
+   * Prevents the wrapped native event's default action.
+   */
+  public void preventDefault() {
+    assertLive();
+    nativeEvent.preventDefault();
+  }
+
+  /**
+   * Sets the native event associated with this dom event. In general, dom
+   * events should be fired using the static firing methods.
+   * 
+   * @param nativeEvent the native event
+   */
+  public final void setNativeEvent(Event nativeEvent) {
+    this.nativeEvent = nativeEvent;
+  }
+
+  /**
+   * Stops the propagation of the underlying native event.
+   */
+  public void stopPropagation() {
+    assertLive();
+    nativeEvent.cancelBubble(true);
+  }
+
+  @Override
+  protected abstract DomEvent.Type<H> getAssociatedType();
+}
diff --git a/user/src/com/google/gwt/event/dom/client/DoubleClickEvent.java b/user/src/com/google/gwt/event/dom/client/DoubleClickEvent.java
new file mode 100644
index 0000000..0d24cf4
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/DoubleClickEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native double click event.

+ */

+public class DoubleClickEvent extends DomEvent<DoubleClickHandler> {

+

+  /**

+   * Event type for double click events. Represents the meta-data associated

+   * with this event.

+   */

+  private static final Type<DoubleClickHandler> TYPE = new Type<DoubleClickHandler>(

+      Event.ONDBLCLICK, "dblclick", new DoubleClickEvent());

+

+  /**

+   * Gets the event type associated with double click events.

+   * 

+   * @return the handler type

+   */

+  public static Type<DoubleClickHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire double click events.

+   */

+  protected DoubleClickEvent() {

+  }

+

+  @Override

+  protected void dispatch(DoubleClickHandler handler) {

+    handler.onDoubleClick(this);

+  }

+

+  @Override

+  protected final Type<DoubleClickHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/DoubleClickHandler.java b/user/src/com/google/gwt/event/dom/client/DoubleClickHandler.java
new file mode 100644
index 0000000..4b3d202
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/DoubleClickHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link DoubleClickEvent} events.
+ */
+public interface DoubleClickHandler extends EventHandler {
+
+  /**
+   * Called when a {@link DoubleClickEvent} is fired.
+   * 
+   * @param event the {@link DoubleClickEvent} that was fired
+   */
+  void onDoubleClick(DoubleClickEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/ErrorEvent.java b/user/src/com/google/gwt/event/dom/client/ErrorEvent.java
new file mode 100644
index 0000000..62084de
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ErrorEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native error event.

+ */

+public class ErrorEvent extends DomEvent<ErrorHandler> {

+

+  /**

+   * Event type for error events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<ErrorHandler> TYPE = new Type<ErrorHandler>(

+      Event.ONERROR, "error", new ErrorEvent());

+

+  /**

+   * Gets the event type associated with error events.

+   * 

+   * @return the handler type

+   */

+  public static Type<ErrorHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire error events.

+   */

+  protected ErrorEvent() {

+  }

+

+  @Override

+  protected void dispatch(ErrorHandler handler) {

+    handler.onError(this);

+  }

+

+  @Override

+  protected final Type<ErrorHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/ErrorHandler.java b/user/src/com/google/gwt/event/dom/client/ErrorHandler.java
new file mode 100644
index 0000000..388865b
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ErrorHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link ErrorEvent} events.
+ */
+public interface ErrorHandler extends EventHandler {
+
+  /**
+   * Called when ErrorEvent is fired.
+   * 
+   * @param event the {@link ErrorEvent} that was fired
+   */
+  void onError(ErrorEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/FocusEvent.java b/user/src/com/google/gwt/event/dom/client/FocusEvent.java
new file mode 100644
index 0000000..898c03a
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/FocusEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native focus event.

+ */

+public class FocusEvent extends DomEvent<FocusHandler> {

+

+  /**

+   * Event type for focus events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<FocusHandler> TYPE = new Type<FocusHandler>(

+      Event.ONFOCUS, "focus", new FocusEvent());

+

+  /**

+   * Gets the event type associated with focus events.

+   * 

+   * @return the handler type

+   */

+  public static Type<FocusHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire focus events.

+   */

+  protected FocusEvent() {

+  }

+

+  @Override

+  protected void dispatch(FocusHandler handler) {

+    handler.onFocus(this);

+  }

+

+  @Override

+  protected final Type<FocusHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/FocusHandler.java b/user/src/com/google/gwt/event/dom/client/FocusHandler.java
new file mode 100644
index 0000000..ca87047
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/FocusHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link FocusEvent} events.
+ */
+public interface FocusHandler extends EventHandler {
+
+  /**
+   * Called when FocusEvent is fired.
+   * 
+   * @param event the {@link FocusEvent} that was fired
+   */
+  void onFocus(FocusEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/HandlesAllFocusEvents.java b/user/src/com/google/gwt/event/dom/client/HandlesAllFocusEvents.java
new file mode 100644
index 0000000..594b906
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HandlesAllFocusEvents.java
@@ -0,0 +1,55 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * Receiver used to handle all focus events at once.

+ */

+public abstract class HandlesAllFocusEvents implements FocusHandler,

+    BlurHandler {

+

+  /**

+   * Convenience method used to handle both focus and blur events from an event

+   * source.

+   * 

+   * @param <H> receiver type, must implement both {@link FocusHandler} and

+   * {@link BlurHandler} handlers

+   * @param eventSource the event source

+   * @param reciever the receiver implementing both focus and blur handlers

+   */

+  public static <H extends BlurHandler & FocusHandler> void handle(

+      HasAllFocusHandlers eventSource, H reciever) {

+    eventSource.addBlurHandler(reciever);

+    eventSource.addFocusHandler(reciever);

+  }

+

+  /**

+   * Constructor.

+   */

+  public HandlesAllFocusEvents() {

+  }

+

+  /**

+   * Convenience method to handle both focus and blur events from an event

+   * source.

+   * 

+   * @param source the event source

+   */

+  public void handle(HasAllFocusHandlers source) {

+    handle(source, this);

+  }

+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/HandlesAllKeyEvents.java b/user/src/com/google/gwt/event/dom/client/HandlesAllKeyEvents.java
new file mode 100644
index 0000000..73b5882
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HandlesAllKeyEvents.java
@@ -0,0 +1,58 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * Receiver used to handle all key events at once.

+ * 

+ * WARNING, PLEASE READ: As this class is intended for developers who wish to

+ * handle all key events in GWT, new key handler interfaces will be added to it.

+ * Therefore, updates to GWT could cause breaking API changes.

+ * 

+ */

+public abstract class HandlesAllKeyEvents implements KeyDownHandler,

+    KeyUpHandler, KeyPressHandler {

+

+  /**

+   * Convenience method used to handle all key events from an event source.

+   * 

+   * @param <H> receiver type, must implement all key handlers

+   * @param eventSource the event source

+   * @param reciever the receiver implementing all key handlers

+   */

+  public static <H extends KeyDownHandler & KeyUpHandler & KeyPressHandler> void addHandlers(

+      HasAllKeyHandlers eventSource, H reciever) {

+    eventSource.addKeyDownHandler(reciever);

+    eventSource.addKeyPressHandler(reciever);

+    eventSource.addKeyUpHandler(reciever);

+  }

+

+  /**

+   * Constructor.

+   */

+  public HandlesAllKeyEvents() {

+  }

+

+  /**

+   * Convenience method to handle all key events from an event source.

+   * 

+   * @param source the event source

+   */

+  public final void addKeyHandlersTo(HasAllKeyHandlers source) {

+    addHandlers(source, this);

+  }

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HandlesAllMouseEvents.java b/user/src/com/google/gwt/event/dom/client/HandlesAllMouseEvents.java
new file mode 100644
index 0000000..85cc52a
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HandlesAllMouseEvents.java
@@ -0,0 +1,62 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * Receiver used to handle all mouse events at once.

+ * 

+ * WARNING, PLEASE READ: As this class is intended for developers who wish to

+ * handle all mouse events in GWT, new mouse handler interfaces will be added to

+ * it. Therefore, updates to GWT could cause breaking API changes.

+ * 

+ */

+public abstract class HandlesAllMouseEvents implements MouseDownHandler,

+    MouseUpHandler, MouseMoveHandler, MouseOutHandler, MouseOverHandler,

+    MouseWheelHandler {

+

+  /**

+   * Convenience method used to handle all mouse events from an event source.

+   * 

+   * @param <H> receiver type, must implement all mouse handlers

+   * @param source the event source

+   * @param reciever the receiver implementing all mouse handlers

+   */

+  public static <H extends MouseDownHandler & MouseUpHandler & MouseOutHandler & MouseOverHandler & MouseMoveHandler & MouseWheelHandler> void handle(

+      HasAllMouseHandlers source, H reciever) {

+    source.addMouseDownHandler(reciever);

+    source.addMouseUpHandler(reciever);

+    source.addMouseOutHandler(reciever);

+    source.addMouseOverHandler(reciever);

+    source.addMouseMoveHandler(reciever);

+    source.addMouseWheelHandler(reciever);

+  }

+

+  /**

+   * Constructor.

+   */

+  public HandlesAllMouseEvents() {

+  }

+

+  /**

+   * Convenience method to handle all mouse events from an event source.

+   * 

+   * @param eventSource the event source

+   */

+  public void handle(HasAllMouseHandlers eventSource) {

+    handle(eventSource, this);

+  }

+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/HasAllFocusHandlers.java b/user/src/com/google/gwt/event/dom/client/HasAllFocusHandlers.java
new file mode 100644
index 0000000..7053d22
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasAllFocusHandlers.java
@@ -0,0 +1,29 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * This is a convenience interface that includes all focus handlers defined by

+ * the core GWT system.

+ * 

+ * <p> WARNING, PLEASE READ: As this interface is intended for developers who

+ * wish to handle all focus events in GWT, in the unlikely event that a new

+ * focus event is added, this interface will change.

+ * </p>

+ */

+public interface HasAllFocusHandlers extends HasFocusHandlers, HasBlurHandlers {

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasAllKeyHandlers.java b/user/src/com/google/gwt/event/dom/client/HasAllKeyHandlers.java
new file mode 100644
index 0000000..847c0a7
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasAllKeyHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * Convenience interface used to implement all key handlers at once.

+ * 

+ * <p>

+ * WARNING, PLEASE READ: In the unlikely event that more key handler subtypes

+ * are added to GWT, this interface will be expanded, so only implement this

+ * interface if you wish to have your widget break if a new key event type is

+ * introduced.

+ * </p>

+ */

+public interface HasAllKeyHandlers extends HasKeyUpHandlers,

+    HasKeyDownHandlers, HasKeyPressHandlers {

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasAllMouseHandlers.java b/user/src/com/google/gwt/event/dom/client/HasAllMouseHandlers.java
new file mode 100644
index 0000000..b82c76e
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasAllMouseHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * This is a convenience interface that includes all mouse handlers defined by

+ * the core GWT system.

+ * <p>

+ * WARNING, PLEASE READ: As this interface is intended for developers who

+ * wish to handle all mouse events in GWT, new mouse event handlers will be

+ * added to it. Therefore, updates can cause breaking API changes.

+ * </p>

+ */

+public interface HasAllMouseHandlers extends HasMouseDownHandlers,

+    HasMouseUpHandlers, HasMouseOutHandlers, HasMouseOverHandlers,

+    HasMouseMoveHandlers, HasMouseWheelHandlers {

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java b/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java
new file mode 100644
index 0000000..2892059
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasBlurHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link BlurHandler} instances.

+ */

+public interface HasBlurHandlers {

+  /**

+   * Adds a {@link BlurEvent} handler.

+   * 

+   * @param handler the blur handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addBlurHandler(BlurHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java b/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java
new file mode 100644
index 0000000..8b9b8da
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasChangeHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link ChangeHandler} instances.

+ */

+public interface HasChangeHandlers {

+  /**

+   * Adds a {@link ChangeEvent} handler.

+   * 

+   * @param handler the change handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addChangeHandler(ChangeHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java b/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java
new file mode 100644
index 0000000..26c1a9a
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasClickHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link ClickHandler} instances.

+ */

+public interface HasClickHandlers {

+  /**

+   * Adds a {@link ClickEvent} handler.

+   * 

+   * @param handler the click handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addClickHandler(ClickHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java b/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java
new file mode 100644
index 0000000..669ed5d
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasContextMenuHandlers.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * A widget that implements this interface provides registration for
+ * {@link ContextMenuHandler} instances.
+ */
+public interface HasContextMenuHandlers {
+  /**
+   * Adds a {@link ContextMenuEvent} handler.
+   * 
+   * @param handler the context menu handler
+   * @return {@link HandlerRegistration} used to remove this handler
+   */
+  HandlerRegistration addContextMenuHandler(ContextMenuHandler handler);
+}
diff --git a/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java b/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java
new file mode 100644
index 0000000..35f6d7b
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasDoubleClickHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link DoubleClickHandler} instances.

+ */

+public interface HasDoubleClickHandlers {

+  /**

+   * Adds a {@link DoubleClickEvent} handler.

+   * 

+   * @param handler the double click handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java b/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java
new file mode 100644
index 0000000..00b741c
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasErrorHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link ErrorHandler} instances.

+ */

+public interface HasErrorHandlers {

+  /**

+   * Adds a {@link ErrorEvent} handler.

+   * 

+   * @param handler the error handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addErrorHandler(ErrorHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java b/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java
new file mode 100644
index 0000000..a7d3dfd
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasFocusHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link FocusHandler} instances.

+ */

+public interface HasFocusHandlers {

+  /**

+   * Adds a {@link FocusEvent} handler.

+   * 

+   * @param handler the focus handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addFocusHandler(FocusHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java
new file mode 100644
index 0000000..5d584d7
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyDownHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link KeyDownHandler} instances.

+ */

+public interface HasKeyDownHandlers {

+  /**

+   * Adds a {@link KeyDownEvent} handler.

+   * 

+   * @param handler the key down handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addKeyDownHandler(KeyDownHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java
new file mode 100644
index 0000000..7d55449
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyPressHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link KeyPressHandler} instances.

+ */

+public interface HasKeyPressHandlers {

+  /**

+   * Adds a {@link KeyPressEvent} handler.

+   * 

+   * @param handler the key press handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addKeyPressHandler(KeyPressHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java b/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java
new file mode 100644
index 0000000..0b6bc92
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasKeyUpHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link KeyUpHandler} instances.

+ */

+public interface HasKeyUpHandlers {

+  /**

+   * Adds a {@link KeyUpEvent} handler.

+   * 

+   * @param handler the key up handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addKeyUpHandler(KeyUpHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java b/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java
new file mode 100644
index 0000000..efe2892
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasLoadHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link LoadHandler} instances.

+ */

+public interface HasLoadHandlers {

+  /**

+   * Adds a {@link LoadEvent} handler.

+   * 

+   * @param handler the load handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addLoadHandler(LoadHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java b/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java
new file mode 100644
index 0000000..dac1c4b
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasLoseCaptureHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link LoseCaptureHandler} instances.

+ */

+public interface HasLoseCaptureHandlers {

+  /**

+   * Adds a {@link LoseCaptureEvent} handler.

+   * 

+   * @param handler the lose capture handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addLoseCaptureHandler(LoseCaptureHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java
new file mode 100644
index 0000000..71853a1
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseDownHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseDownHandler} instances.

+ */

+public interface HasMouseDownHandlers {

+  /**

+   * Adds a {@link MouseDownEvent} handler.

+   * 

+   * @param handler the mouse down handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseDownHandler(MouseDownHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java
new file mode 100644
index 0000000..90f6e55
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseMoveHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseMoveHandler} instances.

+ */

+public interface HasMouseMoveHandlers {

+  /**

+   * Adds a {@link MouseMoveEvent} handler.

+   * 

+   * @param handler the mouse move handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java
new file mode 100644
index 0000000..e993c67
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseOutHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseOutHandler} instances.

+ */

+public interface HasMouseOutHandlers {

+  /**

+   * Adds a {@link MouseOutEvent} handler.

+   * 

+   * @param handler the mouse out handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseOutHandler(MouseOutHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java
new file mode 100644
index 0000000..dab97b6
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseOverHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseOverHandler} instances.

+ */

+public interface HasMouseOverHandlers {

+  /**

+   * Adds a {@link MouseOverEvent} handler.

+   * 

+   * @param handler the mouse over handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseOverHandler(MouseOverHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java
new file mode 100644
index 0000000..e04a391
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseUpHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseUpHandler} instances.

+ */

+public interface HasMouseUpHandlers {

+  /**

+   * Adds a {@link MouseUpEvent} handler.

+   * 

+   * @param handler the mouse up handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseUpHandler(MouseUpHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java b/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java
new file mode 100644
index 0000000..7aaaa41
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasMouseWheelHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link MouseWheelHandler} instances.

+ */

+public interface HasMouseWheelHandlers {

+  /**

+   * Adds a {@link MouseWheelEvent} handler.

+   * 

+   * @param handler the mouse wheel handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/HasScrollHandlers.java b/user/src/com/google/gwt/event/dom/client/HasScrollHandlers.java
new file mode 100644
index 0000000..bc229f5
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/HasScrollHandlers.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface provides registration for

+ * {@link ScrollHandler} instances.

+ */

+public interface HasScrollHandlers {

+  /**

+   * Adds a {@link ScrollEvent} handler.

+   * 

+   * @param handler the scroll handler

+   * @return {@link HandlerRegistration} used to remove this handler

+   */

+  HandlerRegistration addScrollHandler(ScrollHandler handler);

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyCodeEvent.java b/user/src/com/google/gwt/event/dom/client/KeyCodeEvent.java
new file mode 100644
index 0000000..66dfff9
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyCodeEvent.java
@@ -0,0 +1,95 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.event.shared.EventHandler;

+

+/**

+ * Key up and key down are both events based upon a given key code.

+ * 

+ * @param <H> handler type

+ */

+public abstract class KeyCodeEvent<H extends EventHandler> extends KeyEvent<H> {

+  /**

+   * Does the key code represent an arrow key?

+   * 

+   * @param keyCode the key code

+   * @return if it is an arrow key code

+   */

+  public static boolean isArrow(int keyCode) {

+    switch (keyCode) {

+      case KeyCodes.KEY_DOWN:

+      case KeyCodes.KEY_RIGHT:

+      case KeyCodes.KEY_UP:

+      case KeyCodes.KEY_LEFT:

+        return true;

+      default:

+        return false;

+    }

+  }

+

+  /**

+   * Gets the native key code. These key codes are enumerated in the

+   * {@link KeyCodes} class.

+   * 

+   * @return the key code

+   */

+  public int getNativeKeyCode() {

+    return getNativeEvent().getKeyCode();

+  }

+ 

+  /**

+   * Is this a key down arrow?

+   * 

+   * @return whether this is a down arrow key event

+   */

+  public boolean isDownArrow() {

+    return getNativeKeyCode() == KeyCodes.KEY_DOWN;

+  }

+

+  /**

+   * Is this a left arrow?

+   * 

+   * @return whether this is a left arrow key event

+   */

+  public boolean isLeftArrow() {

+    return getNativeKeyCode() == KeyCodes.KEY_LEFT;

+  }

+

+  /**

+   * Is this a right arrow?

+   * 

+   * @return whether this is a right arrow key event

+   */

+  public boolean isRightArrow() {

+    return getNativeKeyCode() == KeyCodes.KEY_RIGHT;

+  }

+

+  /**

+   * Is this a up arrow?

+   * 

+   * @return whether this is a right arrow key event

+   */

+  public boolean isUpArrow() {

+    return getNativeKeyCode() == KeyCodes.KEY_UP;

+  }

+

+  @Override

+  public String toDebugString() {

+    return super.toDebugString() + "[" + getNativeKeyCode() + "]";

+  }

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyCodes.java b/user/src/com/google/gwt/event/dom/client/KeyCodes.java
new file mode 100644
index 0000000..25a27f4
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyCodes.java
@@ -0,0 +1,107 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.dom.client;

+

+/**

+ * Contains the native key codes previously defined in

+ * {@link com.google.gwt.user.client.ui.KeyboardListener}. When converting

+ * keyboard listener instances, developers can use the following static import

+ * to access these constants:

+ * 

+ * <pre> import static com.google.gwt.event.dom.client.KeyCodes.*; </pre>

+ * 

+ * These constants are defined with an int data type in order to be compatible

+ * with the constants defined in

+ * {@link com.google.gwt.user.client.ui.KeyboardListener}.

+ */

+public class KeyCodes {

+  /**

+   * Alt key code.

+   */

+  public static final int KEY_ALT = 18;

+

+  /**

+   * Backspace key code.

+   */

+  public static final int KEY_BACKSPACE = 8;

+  /**

+   * Control key code.

+   */

+  public static final int KEY_CTRL = 17;

+

+  /**

+   * Delete key code.

+   */

+  public static final int KEY_DELETE = 46;

+

+  /**

+   * Down arrow code.

+   */

+  public static final int KEY_DOWN = 40;

+

+  /**

+   * End key code.

+   */

+  public static final int KEY_END = 35;

+

+  /**

+   * Enter key code.

+   */

+  public static final int KEY_ENTER = 13;

+  /**

+   * Escape key code.

+   */

+  public static final int KEY_ESCAPE = 27;

+  /**

+   * Home key code.

+   */

+  public static final int KEY_HOME = 36;

+  /**

+   * Left key code.

+   */

+  public static final int KEY_LEFT = 37;

+  /**

+   * Page down key code.

+   */

+  public static final int KEY_PAGEDOWN = 34;

+  /**

+   * Page up key code.

+   */

+  public static final int KEY_PAGEUP = 33;

+  /**

+   * Right arrow key code.

+   */

+  public static final int KEY_RIGHT = 39;

+  /**

+   * Shift key code.

+   */

+  public static final int KEY_SHIFT = 16;

+

+  /**

+   * Tab key code.

+   */

+  public static final int KEY_TAB = 9;

+  /**

+   * Up Arrow key code.

+   */

+  public static final int KEY_UP = 38;

+

+  // This class should never be instantiated

+  private KeyCodes() {

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyDownEvent.java b/user/src/com/google/gwt/event/dom/client/KeyDownEvent.java
new file mode 100644
index 0000000..f826bec
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyDownEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native key down event.

+ */

+public class KeyDownEvent extends KeyCodeEvent<KeyDownHandler> {

+

+  /**

+   * Event type for key down events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<KeyDownHandler> TYPE = new Type<KeyDownHandler>(

+      Event.ONKEYDOWN, "keydown", new KeyDownEvent());

+

+  /**

+   * Gets the event type associated with key down events.

+   * 

+   * @return the handler type

+   */

+  public static Type<KeyDownHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire key down events.

+   */

+  protected KeyDownEvent() {

+  }

+

+  @Override

+  protected void dispatch(KeyDownHandler handler) {

+    handler.onKeyDown(this);

+  }

+

+  @Override

+  protected final Type<KeyDownHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyDownHandler.java b/user/src/com/google/gwt/event/dom/client/KeyDownHandler.java
new file mode 100644
index 0000000..67ef308
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyDownHandler.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link KeyDownEvent} events.
+ */
+public interface KeyDownHandler extends EventHandler  {
+  /**
+   * Called when {@link KeyDownEvent} is fired.
+   * 
+   * @param event the {@link KeyDownEvent} that was fired
+   */
+  void onKeyDown(KeyDownEvent event);
+}
diff --git a/user/src/com/google/gwt/event/dom/client/KeyEvent.java b/user/src/com/google/gwt/event/dom/client/KeyEvent.java
new file mode 100644
index 0000000..6d73bdc
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyEvent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Base class for Key events. The native keyboard events are somewhat a mess
+ * (http://www.quirksmode.org/js/keys.html), we do some trivial normalization
+ * here, but do not attempt any complex patching, so user be warned.
+ * 
+ * @param <H> The event handler type 
+ */
+public abstract class KeyEvent<H extends EventHandler> extends DomEvent<H> {
+
+  /**
+   * Is the <code>alt</code> key down?
+   * 
+   * @return whether the alt key is down
+   */
+  public boolean isAltKeyDown() {
+    return getNativeEvent().getAltKey();
+  }
+
+  /**
+   * Gets the key-repeat state of this event.
+   * 
+   * @return <code>true</code> if this key event was an auto-repeat
+   */
+  public boolean isAutoRepeat() {
+    return getNativeEvent().getRepeat();
+  }
+
+  /**
+   * Is the <code>control</code> key down?
+   * 
+   * @return whether the control key is down
+   */
+  public boolean isControlKeyDown() {
+    return getNativeEvent().getCtrlKey();
+  }
+
+  /**
+   * Is the <code>meta</code> key down?
+   * 
+   * @return whether the meta key is down
+   */
+  public boolean isMetaKeyDown() {
+    return getNativeEvent().getMetaKey();
+  }
+
+  /**
+   * Is the <code>shift</code> key down?
+   * 
+   * @return whether the shift key is down
+   */
+  public boolean isShiftKeyDown() {
+    return getNativeEvent().getShiftKey();
+  }
+}
diff --git a/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java b/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java
new file mode 100644
index 0000000..1f8528e
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyPressEvent.java
@@ -0,0 +1,77 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native key press event.

+ */

+public class KeyPressEvent extends KeyEvent<KeyPressHandler> {

+

+  /**

+   * Event type for key press events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<KeyPressHandler> TYPE = new Type<KeyPressHandler>(

+      Event.ONKEYPRESS, "keypress", new KeyPressEvent());

+

+  /**

+   * Gets the event type associated with key press events.

+   * 

+   * @return the handler type

+   */

+  public static Type<KeyPressHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire key press events.

+   */

+  protected KeyPressEvent() {

+  }

+

+  /**

+   * Gets the char code for this event.

+   * 

+   * @return the char code

+   */

+  public char getCharCode() {

+    return getCharCode(getNativeEvent());

+  }

+

+  @Override

+  public String toDebugString() {

+    return super.toDebugString() + "[" + getCharCode() + "]";

+  }

+

+  @Override

+  protected void dispatch(KeyPressHandler handler) {

+    handler.onKeyPress(this);

+  }

+

+  @Override

+  protected final Type<KeyPressHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+  private native char getCharCode(Event e)/*-{

+      return e.charCode || e.keyCode;

+    }-*/;

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyPressHandler.java b/user/src/com/google/gwt/event/dom/client/KeyPressHandler.java
new file mode 100644
index 0000000..73e11f1
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyPressHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link KeyPressEvent} events.
+ */
+public interface KeyPressHandler extends EventHandler {
+
+  /**
+   * Called when KeyPressEvent is fired.
+   * 
+   * @param event the {@link KeyPressEvent} that was fired
+   */
+  void onKeyPress(KeyPressEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/KeyUpEvent.java b/user/src/com/google/gwt/event/dom/client/KeyUpEvent.java
new file mode 100644
index 0000000..f9cfdbd
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyUpEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native key up event.

+ */

+public class KeyUpEvent extends KeyCodeEvent<KeyUpHandler> {

+

+  /**

+   * Event type for key up events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<KeyUpHandler> TYPE = new Type<KeyUpHandler>(

+      Event.ONKEYUP, "keyup", new KeyUpEvent());

+

+  /**

+   * Gets the event type associated with key up events.

+   * 

+   * @return the handler type

+   */

+  public static Type<KeyUpHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire key up events.

+   */

+  protected KeyUpEvent() {

+  }

+

+  @Override

+  protected void dispatch(KeyUpHandler handler) {

+    handler.onKeyUp(this);

+  }

+

+  @Override

+  protected final Type<KeyUpHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/KeyUpHandler.java b/user/src/com/google/gwt/event/dom/client/KeyUpHandler.java
new file mode 100644
index 0000000..b2eb991
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/KeyUpHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link KeyUpEvent} events.
+ */
+public interface KeyUpHandler extends EventHandler {
+
+  /**
+   * Called when KeyUpEvent is fired.
+   * 
+   * @param event the {@link KeyUpEvent} that was fired
+   */
+  void onKeyUp(KeyUpEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/LoadEvent.java b/user/src/com/google/gwt/event/dom/client/LoadEvent.java
new file mode 100644
index 0000000..7e2bac5
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/LoadEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native load event.

+ */

+public class LoadEvent extends DomEvent<LoadHandler> {

+

+  /**

+   * Event type for load events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<LoadHandler> TYPE = new Type<LoadHandler>(

+      Event.ONLOAD, "load", new LoadEvent());

+

+  /**

+   * Gets the event type associated with load events.

+   * 

+   * @return the handler type

+   */

+  public static Type<LoadHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire load events.

+   */

+  protected LoadEvent() {

+  }

+

+  @Override

+  protected void dispatch(LoadHandler handler) {

+    handler.onLoad(this);

+  }

+

+  @Override

+  protected final Type<LoadHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/LoadHandler.java b/user/src/com/google/gwt/event/dom/client/LoadHandler.java
new file mode 100644
index 0000000..aaf9430
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/LoadHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link LoadEvent} events.
+ */
+public interface LoadHandler extends EventHandler {
+
+  /**
+   * Called when LoadEvent is fired.
+   * 
+   * @param event the {@link LoadEvent} that was fired
+   */
+  void onLoad(LoadEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/LoseCaptureEvent.java b/user/src/com/google/gwt/event/dom/client/LoseCaptureEvent.java
new file mode 100644
index 0000000..270f0cd
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/LoseCaptureEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native lose capture event.

+ */

+public class LoseCaptureEvent extends DomEvent<LoseCaptureHandler> {

+

+  /**

+   * Event type for lose capture events. Represents the meta-data associated

+   * with this event.

+   */

+  private static final Type<LoseCaptureHandler> TYPE = new Type<LoseCaptureHandler>(

+      Event.ONLOSECAPTURE, "losecapture", new LoseCaptureEvent());

+

+  /**

+   * Gets the event type associated with lose capture events.

+   * 

+   * @return the handler type

+   */

+  public static Type<LoseCaptureHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire lose capture events.

+   */

+  protected LoseCaptureEvent() {

+  }

+

+  @Override

+  protected void dispatch(LoseCaptureHandler handler) {

+    handler.onLoseCapture(this);

+  }

+

+  @Override

+  protected final Type<LoseCaptureHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/LoseCaptureHandler.java b/user/src/com/google/gwt/event/dom/client/LoseCaptureHandler.java
new file mode 100644
index 0000000..e20004c
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/LoseCaptureHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link LoseCaptureEvent} events.
+ */
+public interface LoseCaptureHandler extends EventHandler {
+
+  /**
+   * Called when LoseCaptureEvent is fired.
+   * 
+   * @param event the {@link LoseCaptureEvent} that was fired
+   */
+  void onLoseCapture(LoseCaptureEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseDownEvent.java b/user/src/com/google/gwt/event/dom/client/MouseDownEvent.java
new file mode 100644
index 0000000..23336ad
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseDownEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse down event.

+ */

+public class MouseDownEvent extends MouseEvent<MouseDownHandler> {

+

+  /**

+   * Event type for mouse down events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseDownHandler> TYPE = new Type<MouseDownHandler>(

+      Event.ONMOUSEDOWN, "mousedown", new MouseDownEvent());

+

+  /**

+   * Gets the event type associated with mouse down events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseDownHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse down events.

+   */

+  protected MouseDownEvent() {

+  }

+

+  @Override

+  protected void dispatch(MouseDownHandler handler) {

+    handler.onMouseDown(this);

+  }

+

+  @Override

+  protected final Type<MouseDownHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseDownHandler.java b/user/src/com/google/gwt/event/dom/client/MouseDownHandler.java
new file mode 100644
index 0000000..234b485
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseDownHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseDownEvent} events.
+ */
+public interface MouseDownHandler extends EventHandler {
+
+  /**
+   * Called when MouseDown is fired.
+   * 
+   * @param event the {@link MouseDownEvent} that was fired
+   */
+  void onMouseDown(MouseDownEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseEvent.java b/user/src/com/google/gwt/event/dom/client/MouseEvent.java
new file mode 100644
index 0000000..424b138
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseEvent.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Window;
+
+/**
+ * Abstract class representing mouse events.
+ * 
+ * @param <H> handler type
+ * 
+ */
+public abstract class MouseEvent<H extends EventHandler> extends DomEvent<H> {
+  /**
+   * Gets the x coordinate relative to the given element.
+   * 
+   * @param nativeEvent the native event
+   * @param relativeTo the relative element
+   * @return the relative x
+   */
+  public static int getRelativeX(Event nativeEvent, Element relativeTo) {
+    return nativeEvent.getClientX() - relativeTo.getAbsoluteLeft()
+        + relativeTo.getScrollLeft() + Window.getScrollLeft();
+  }
+
+  /**
+   * Gets the y coordinate relative to the given element.
+   * 
+   * @param nativeEvent the native event
+   * @param relativeTo the relative element
+   * @return the relative y
+   */
+  public static int getRelativeY(Event nativeEvent, Element relativeTo) {
+    return nativeEvent.getClientY() - relativeTo.getAbsoluteTop()
+        + relativeTo.getScrollTop() + Window.getScrollTop();
+  }
+
+  /**
+   * Gets the mouse x-position within the browser window's client area.
+   * 
+   * @return the mouse x-position
+   */
+  public int getClientX() {
+    return getNativeEvent().getClientX();
+  }
+
+  /**
+   * Gets the mouse y-position within the browser window's client area.
+   * 
+   * @return the mouse y-position
+   */
+  public int getClientY() {
+    return getNativeEvent().getClientY();
+  }
+
+  /**
+   * Gets the button value. Compare it to {@link Event#BUTTON_LEFT},
+   * {@link Event#BUTTON_RIGHT}, {@link Event#BUTTON_MIDDLE}
+   * 
+   * @return the button value
+   */
+  public int getNativeButton() {
+    return getNativeEvent().getButton();
+  }
+
+  /**
+   * Gets the x coordinate relative to the given element.
+   * 
+   * @param relativeTo the relative element
+   * @return the relative x
+   */
+  public int getRelativeX(Element relativeTo) {
+    return getRelativeX(getNativeEvent(), relativeTo);
+  }
+
+  /**
+   * Gets the y coordinate relative to the given element.
+   * 
+   * 
+   * @param relativeTo the relative element
+   * @return the relative y
+   */
+  public int getRelativeY(Element relativeTo) {
+    return getRelativeY(getNativeEvent(), relativeTo);
+  }
+
+  /**
+   * Gets the mouse x-position on the user's display.
+   * 
+   * @return the mouse x-position
+   */
+  public int getScreenX() {
+    return getNativeEvent().getScreenX();
+  }
+
+  /**
+   * Gets the mouse y-position on the user's display.
+   * 
+   * @return the mouse y-position
+   */
+  public int getScreenY() {
+    return getNativeEvent().getScreenY();
+  }
+
+  /**
+   * Is <code>alt</code> key down.
+   * 
+   * @return whether the alt key is down
+   */
+  public boolean isAltKeyDown() {
+    return getNativeEvent().getAltKey();
+  }
+
+  /**
+   * Is <code>control</code> key down.
+   * 
+   * @return whether the control key is down
+   */
+  public boolean isControlKeyDown() {
+    return getNativeEvent().getCtrlKey();
+  }
+
+  /**
+   * Is <code>meta</code> key down.
+   * 
+   * @return whether the meta key is down
+   */
+  public boolean isMetaKeyDown() {
+    return getNativeEvent().getMetaKey();
+  }
+
+  /**
+   * Is <code>shift</code> key down.
+   * 
+   * @return whether the shift key is down
+   */
+  public boolean isShiftKeyDown() {
+    return getNativeEvent().getShiftKey();
+  }
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseMoveEvent.java b/user/src/com/google/gwt/event/dom/client/MouseMoveEvent.java
new file mode 100644
index 0000000..fd64fbb
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseMoveEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse move event.

+ */

+public class MouseMoveEvent extends MouseEvent<MouseMoveHandler> {

+

+  /**

+   * Event type for mouse move events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseMoveHandler> TYPE = new Type<MouseMoveHandler>(

+      Event.ONMOUSEMOVE, "mousemove", new MouseMoveEvent());

+

+  /**

+   * Gets the event type associated with mouse move events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseMoveHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse move events.

+   */

+  protected MouseMoveEvent() {

+  }

+

+  @Override

+  protected void dispatch(MouseMoveHandler handler) {

+    handler.onMouseMove(this);

+  }

+

+  @Override

+  protected final Type<MouseMoveHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseMoveHandler.java b/user/src/com/google/gwt/event/dom/client/MouseMoveHandler.java
new file mode 100644
index 0000000..9e62512
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseMoveHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseMoveEvent} events.
+ */
+public interface MouseMoveHandler extends EventHandler {
+
+  /**
+   * Called when MouseMoveEvent is fired.
+   * 
+   * @param event the {@link MouseMoveEvent} that was fired
+   */
+  void onMouseMove(MouseMoveEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java b/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java
new file mode 100644
index 0000000..96d817e
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseOutEvent.java
@@ -0,0 +1,80 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.dom.client.Element;

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse out event.

+ */

+public class MouseOutEvent extends MouseEvent<MouseOutHandler> {

+

+  /**

+   * Event type for mouse out events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseOutHandler> TYPE = new Type<MouseOutHandler>(

+      Event.ONMOUSEOUT, "mouseout", new MouseOutEvent());

+

+  /**

+   * Gets the event type associated with mouse out events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseOutHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse out events.

+   */

+  protected MouseOutEvent() {

+  }

+

+  /**

+   * Gets the element from which the mouse pointer was moved.

+   * 

+   * @return the element from which the mouse pointer was moved

+   */

+  public Element getFromElement() {

+    // Use a deferred binding instead of DOMImpl's inefficient switch statement

+    return getNativeEvent().getFromElement();

+  }

+

+  /**

+   * Gets the element to which the mouse pointer was moved.

+   * 

+   * @return the element to which the mouse pointer was moved

+   */

+  public Element getToElement() {

+    // Use a deferred binding instead of DOMImpl's inefficient switch statement

+    return getNativeEvent().getToElement();

+  }

+

+  @Override

+  protected void dispatch(MouseOutHandler handler) {

+    handler.onMouseOut(this);

+  }

+

+  @Override

+  protected final Type<MouseOutHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseOutHandler.java b/user/src/com/google/gwt/event/dom/client/MouseOutHandler.java
new file mode 100644
index 0000000..92cebf6
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseOutHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseOutEvent} events.
+ */
+public interface MouseOutHandler extends EventHandler {
+
+  /**
+   * Called when MouseOutEvent is fired.
+   * 
+   * @param event the {@link MouseOutEvent} that was fired
+   */
+  void onMouseOut(MouseOutEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java b/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java
new file mode 100644
index 0000000..1925791
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseOverEvent.java
@@ -0,0 +1,80 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.dom.client.Element;

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse over event.

+ */

+public class MouseOverEvent extends MouseEvent<MouseOverHandler> {

+

+  /**

+   * Event type for mouse over events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseOverHandler> TYPE = new Type<MouseOverHandler>(

+      Event.ONMOUSEOVER, "mouseover", new MouseOverEvent());

+

+  /**

+   * Gets the event type associated with mouse over events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseOverHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse over events.

+   */

+  protected MouseOverEvent() {

+  }

+

+  /**

+   * Gets the element from which the mouse pointer was moved.

+   * 

+   * @return the element from which the mouse pointer was moved

+   */

+  public Element getFromElement() {

+    // Use a deferred binding instead of DOMImpl's inefficient switch statement

+    return getNativeEvent().getFromElement();

+  }

+

+  /**

+   * Gets the element to which the mouse pointer was moved.

+   * 

+   * @return the element to which the mouse pointer was moved

+   */

+  public Element getToElement() {

+    // Use a deferred binding instead of DOMImpl's inefficient switch statement

+    return getNativeEvent().getToElement();

+  }

+

+  @Override

+  protected void dispatch(MouseOverHandler handler) {

+    handler.onMouseOver(this);

+  }

+

+  @Override

+  protected final Type<MouseOverHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseOverHandler.java b/user/src/com/google/gwt/event/dom/client/MouseOverHandler.java
new file mode 100644
index 0000000..a3a08d4
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseOverHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseOverEvent} events.
+ */
+public interface MouseOverHandler extends EventHandler {
+
+  /**
+   * Called when MouseOverEvent is fired.
+   * 
+   * @param event the {@link MouseOverEvent} that was fired
+   */
+  void onMouseOver(MouseOverEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseUpEvent.java b/user/src/com/google/gwt/event/dom/client/MouseUpEvent.java
new file mode 100644
index 0000000..3a733db
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseUpEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse up event.

+ */

+public class MouseUpEvent extends MouseEvent<MouseUpHandler> {

+

+  /**

+   * Event type for mouse up events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseUpHandler> TYPE = new Type<MouseUpHandler>(

+      Event.ONMOUSEUP, "mouseup", new MouseUpEvent());

+

+  /**

+   * Gets the event type associated with mouse up events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseUpHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse up events.

+   */

+  protected MouseUpEvent() {

+  }

+

+  @Override

+  protected void dispatch(MouseUpHandler handler) {

+    handler.onMouseUp(this);

+  }

+

+  @Override

+  protected final Type<MouseUpHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseUpHandler.java b/user/src/com/google/gwt/event/dom/client/MouseUpHandler.java
new file mode 100644
index 0000000..4fa7321
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseUpHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseUpEvent} events.
+ */
+public interface MouseUpHandler extends EventHandler {
+
+  /**
+   * Called when MouseUpEvent is fired.
+   * 
+   * @param event the {@link MouseUpEvent} that was fired
+   */
+  void onMouseUp(MouseUpEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/MouseWheelEvent.java b/user/src/com/google/gwt/event/dom/client/MouseWheelEvent.java
new file mode 100644
index 0000000..f8248c5
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseWheelEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native mouse wheel event.

+ */

+public class MouseWheelEvent extends MouseEvent<MouseWheelHandler> {

+

+  /**

+   * Event type for mouse wheel events. Represents the meta-data associated with

+   * this event.

+   */

+  private static final Type<MouseWheelHandler> TYPE = new Type<MouseWheelHandler>(

+      Event.ONMOUSEWHEEL, "mousewheel", new MouseWheelEvent(), "DOMMouseScroll");

+

+  /**

+   * Gets the event type associated with mouse wheel events.

+   * 

+   * @return the handler type

+   */

+  public static Type<MouseWheelHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire mouse wheel events.

+   */

+  protected MouseWheelEvent() {

+  }

+

+  @Override

+  protected void dispatch(MouseWheelHandler handler) {

+    handler.onMouseWheel(this);

+  }

+

+  @Override

+  protected final Type<MouseWheelHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/MouseWheelHandler.java b/user/src/com/google/gwt/event/dom/client/MouseWheelHandler.java
new file mode 100644
index 0000000..59225be
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/MouseWheelHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link MouseWheelEvent} events.
+ */
+public interface MouseWheelHandler extends EventHandler {
+
+  /**
+   * Called when MouseWheelEvent is fired.
+   * 
+   * @param event the {@link MouseWheelEvent} that was fired
+   */
+  void onMouseWheel(MouseWheelEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/dom/client/PrivateMap.java b/user/src/com/google/gwt/event/dom/client/PrivateMap.java
new file mode 100644
index 0000000..2b136b3
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/PrivateMap.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
+
+import java.util.HashMap;
+
+/**
+ * Lightweight map implementation. Package protected due to non-final API.
+ * 
+ * @param <V> value type
+ */
+class PrivateMap<V> {
+
+  /**
+   * Js version of our map.
+   * 
+   * @param <V> value type
+   */
+  private static class JsMap<V> extends JavaScriptObject {
+
+    public static PrivateMap.JsMap<?> create() {
+      return JavaScriptObject.createObject().cast();
+    }
+
+    protected JsMap() {
+    }
+
+    public final native void put(int key, V value) /*-{
+      this[key] = value;
+    }-*/;
+
+    public final native V unsafeGet(int key) /*-{
+      return this[key];
+    }-*/;
+
+    public final native V unsafeGet(String key) /*-{
+      return this[key];
+    }-*/;
+
+    public final native void unsafePut(String key, V value) /*-{
+      this[key] = value;
+    }-*/;
+  }
+
+  private PrivateMap.JsMap<V> map;
+  private HashMap<String, V> javaMap;
+
+  public PrivateMap() {
+    if (GWT.isScript()) {
+      map = JsMap.create().cast();
+    } else {
+      javaMap = new HashMap<String, V>();
+    }
+  }
+
+  public final V get(int key) {
+    if (GWT.isScript()) {
+      return map.unsafeGet(key);
+    } else {
+      return javaMap.get(key + "");
+    }
+  }
+
+  public final void put(int key, V value) {
+    if (GWT.isScript()) {
+      map.put(key, value);
+    } else {
+      javaMap.put(key + "", value);
+    }
+  }
+
+  // ONLY use this for values put with safePut.
+  public final V safeGet(String key) {
+    return unsafeGet(":" + key);
+  }
+ 
+  // ONLY use this for values that will be accessed with safeGet.
+  public final void safePut(String key, V value) {
+    unsafePut(":" + key, value);
+  }
+  
+  // ONLY use this for values put with unsafePut.
+  public final V unsafeGet(String key) {
+    if (GWT.isScript()) {
+      return map.unsafeGet(key);
+    } else {
+      return javaMap.get(key);
+    }
+  }
+  
+  // ONLY use this for values that will be accessed with unsafeGet.
+  public final void unsafePut(String key, V value) {
+    if (GWT.isScript()) {
+      map.unsafePut(key, value);
+    } else {
+      javaMap.put(key, value);
+    }
+  }
+}
diff --git a/user/src/com/google/gwt/event/dom/client/ScrollEvent.java b/user/src/com/google/gwt/event/dom/client/ScrollEvent.java
new file mode 100644
index 0000000..ff8e836
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ScrollEvent.java
@@ -0,0 +1,59 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.dom.client;

+

+import com.google.gwt.user.client.Event;

+

+/**

+ * Represents a native scroll event.

+ */

+public class ScrollEvent extends DomEvent<ScrollHandler> {

+

+  /**

+   * Event type for scroll events. Represents the meta-data associated with this

+   * event.

+   */

+  private static final Type<ScrollHandler> TYPE = new Type<ScrollHandler>(

+      Event.ONSCROLL, "scroll", new ScrollEvent());

+

+  /**

+   * Gets the event type associated with scroll events.

+   * 

+   * @return the handler type

+   */

+  public static Type<ScrollHandler> getType() {

+    return TYPE;

+  }

+

+  /**

+   * Protected constructor, use

+   * {@link DomEvent#fireNativeEvent(Event, com.google.gwt.event.shared.HandlerManager)}

+   * to fire scroll events.

+   */

+  protected ScrollEvent() {

+  }

+

+  @Override

+  protected void dispatch(ScrollHandler handler) {

+    handler.onScroll(this);

+  }

+

+  @Override

+  protected final Type<ScrollHandler> getAssociatedType() {

+    return TYPE;

+  }

+

+}

diff --git a/user/src/com/google/gwt/event/dom/client/ScrollHandler.java b/user/src/com/google/gwt/event/dom/client/ScrollHandler.java
new file mode 100644
index 0000000..87f58a9
--- /dev/null
+++ b/user/src/com/google/gwt/event/dom/client/ScrollHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link ScrollEvent} events.
+ */
+public interface ScrollHandler extends EventHandler {
+
+  /**
+   * Called when ScrollEvent is fired.
+   * 
+   * @param event the {@link ScrollEvent} that was fired
+   */
+  void onScroll(ScrollEvent event);
+}
\ No newline at end of file
diff --git a/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java
new file mode 100644
index 0000000..d81a715
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionEvent.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+
+/**
+ * Represents a before selection event.
+ * 
+ * @param <I> the type about to be selected
+ */
+public class BeforeSelectionEvent<I> extends
+    GwtEvent<BeforeSelectionHandler<I>> {
+
+  /**
+   * Handler type.
+   */
+  private static Type<BeforeSelectionHandler<?>> TYPE;
+
+  /**
+   * Fires a before selection event on all registered handlers in the handler
+   * manager. If no such handlers exist, this method will do nothing.
+   * 
+   * @param <I> the item type
+   * @param <S> The event source type
+   * @param source the source of the handlers
+   * @param item the item
+   * @return the event so that the caller can check if it was canceled, or null
+   * if no handlers of this event type have been registered
+   */
+  public static <I, S extends HasBeforeSelectionHandlers<I> & HasHandlers> BeforeSelectionEvent<I> fire(
+      S source, I item) {
+    // If no handlers exist, then type can be null.
+    if (TYPE != null) {
+      HandlerManager handlers = source.getHandlers();
+      if (handlers != null) {
+        BeforeSelectionEvent<I> event = new BeforeSelectionEvent<I>();
+        event.setItem(item);
+        handlers.fireEvent(event);
+        return event;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Gets the type associated with this event.
+   * 
+   * @return returns the handler type
+   */
+  public static Type<BeforeSelectionHandler<?>> getType() {
+    if (TYPE == null) {
+      TYPE = new Type<BeforeSelectionHandler<?>>();
+    }
+    return TYPE;
+  }
+
+  private I item;
+
+  private boolean canceled;
+
+  /**
+   * Creates a new before selection event.
+   */
+  protected BeforeSelectionEvent() {
+  }
+
+  /**
+   * Cancel the before selection event.  
+   * 
+   * Classes overriding this method should still call super.cancel().
+   */
+  public void cancel() {
+    canceled = true;
+  }
+
+  /**
+   * Gets the item.
+   * 
+   * @return the item
+   */
+  public I getItem() {
+    return item;
+  }
+
+  /**
+   * Has the selection event already been canceled?
+   * 
+   * @return is canceled
+   */
+  public boolean isCanceled() {
+    return canceled;
+  }
+
+  @Override
+  protected void dispatch(BeforeSelectionHandler<I> handler) {
+    handler.onBeforeSelection(this);
+  }
+
+  // The instance knows its BeforeSelectionHandler is of type I, but the TYPE
+  // field itself does not, so we have to do an unsafe cast here.
+  @SuppressWarnings("unchecked")
+  @Override
+  protected Type<BeforeSelectionHandler<I>> getAssociatedType() {
+    return (Type) TYPE;
+  }
+
+  /**
+   * Sets the item.
+   * 
+   * @param item the item
+   */
+  protected final void setItem(I item) {
+    this.item = item;
+  }
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/BeforeSelectionHandler.java b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionHandler.java
new file mode 100644
index 0000000..8671139
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/BeforeSelectionHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler interface for {@link BeforeSelectionEvent} events.
+ * 
+ * @param <I> the type about to be selected
+ */
+public interface BeforeSelectionHandler<I> extends EventHandler {
+
+  /**
+   * Called when {@link BeforeSelectionEvent} is fired.
+   * 
+   * @param event the {@link BeforeSelectionEvent} that was fired
+   */
+  void onBeforeSelection(BeforeSelectionEvent<I> event);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/CloseEvent.java b/user/src/com/google/gwt/event/logical/shared/CloseEvent.java
new file mode 100644
index 0000000..25ceaba
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/CloseEvent.java
@@ -0,0 +1,121 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.GwtEvent;

+import com.google.gwt.event.shared.HandlerManager;

+

+/**

+ * Represents a close event.

+ * 

+ * @param <T> the type being closed

+ */

+public class CloseEvent<T> extends GwtEvent<CloseHandler<T>> {

+

+  /**

+   * Handler type.

+   */

+  private static Type<CloseHandler<?>> TYPE;

+

+  /**

+   * Fires a close event on all registered handlers in the handler manager. If

+   * no such handlers exist, this method will do nothing.

+   * 

+   * @param <T> the target type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param target the target

+   */

+  public static <T, S extends HasCloseHandlers<T> & HasHandlers> void fire(

+      S source, T target) {

+    fire(source, target, false);

+  }

+

+  /**

+   * Fires a close event on all registered handlers in the handler manager.

+   * 

+   * @param <T> the target type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param target the target

+   * @param autoClosed was the target closed automatically

+   */

+  public static <T, S extends HasCloseHandlers<T> & HasHandlers> void fire(

+      S source, T target, boolean autoClosed) {

+    if (TYPE != null) {

+      HandlerManager handlers = source.getHandlers();

+      if (handlers != null) {

+        CloseEvent<T> event = new CloseEvent<T>(target, autoClosed);

+        handlers.fireEvent(event);

+      }

+    }

+  }

+

+  /**

+   * Gets the type associated with this event.

+   * 

+   * @return returns the handler type

+   */

+  public static Type<CloseHandler<?>> getType() {

+    return TYPE != null ? TYPE : (TYPE = new Type<CloseHandler<?>>());

+  }

+

+  private final T target;

+

+  private final boolean autoClosed;

+

+  /**

+   * Creates a new close event.

+   * 

+   * @param target the target

+   * @param autoClosed whether it is auto closed

+   */

+  protected CloseEvent(T target, boolean autoClosed) {

+    this.autoClosed = autoClosed;

+    this.target = target;

+  }

+

+  /**

+   * Gets the target.

+   * 

+   * @return the target

+   */

+  public T getTarget() {

+    return target;

+  }

+

+  /**

+   * Was the target automatically closed?

+   * 

+   * @return auto closed

+   */

+  public boolean isAutoClosed() {

+    return autoClosed;

+  }

+

+  @Override

+  protected void dispatch(CloseHandler<T> handler) {

+    handler.onClose(this);

+  }

+

+  // The instance knows its of type T, but the TYPE

+  // field itself does not, so we have to do an unsafe cast here.

+  @SuppressWarnings("unchecked")

+  @Override

+  protected final Type<CloseHandler<T>> getAssociatedType() {

+    return (Type) TYPE;

+  }

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/CloseHandler.java b/user/src/com/google/gwt/event/logical/shared/CloseHandler.java
new file mode 100644
index 0000000..3b6e062
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/CloseHandler.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.EventHandler;

+

+/**

+ * Handler interface for {@link CloseEvent} events.

+ * 

+ * @param <T> the type being closed

+ */

+public interface CloseHandler<T> extends EventHandler {

+

+  /**

+   * Called when {@link CloseEvent} is fired.

+   * 

+   * @param event the {@link CloseEvent} that was fired

+   */

+  void onClose(CloseEvent<T> event);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java
new file mode 100644
index 0000000..96a6d71
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasBeforeSelectionHandlers.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * A widget that implements this interface is a public source of
+ * {@link BeforeSelectionEvent} events.
+ * 
+ * @param <I> the type about to be selected
+ */
+public interface HasBeforeSelectionHandlers<I> {
+  /**
+   * Adds a {@link BeforeSelectionEvent} handler.
+   * 
+   * @param handler the handler
+   * @return the registration for the event
+   */
+  HandlerRegistration addBeforeSelectionHandler(
+      BeforeSelectionHandler<I> handler);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java
new file mode 100644
index 0000000..fecdb4d
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasCloseHandlers.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface is a public source of

+ * {@link CloseEvent} events.

+ * 

+ * @param <T> the type being closed

+ */

+public interface HasCloseHandlers<T> {

+  /**

+   * Adds a {@link CloseEvent} handler.

+   * 

+   * @param handler the handler

+   * @return the registration for the event

+   */

+  HandlerRegistration addCloseHandler(CloseHandler<T> handler);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/HasHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasHandlers.java
new file mode 100644
index 0000000..ea36461
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasHandlers.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.HandlerManager;

+

+/**

+ * An object that implements this interface has a collection of handlers stored

+ * in a {@link HandlerManager}.

+ */

+

+public interface HasHandlers {

+  /**

+   * Gets this object's handlers. May return null if there are no handlers.

+   * 

+   * @return the handlers

+   */

+  HandlerManager getHandlers();

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java
new file mode 100644
index 0000000..647f270
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasOpenHandlers.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface is a public source of

+ * {@link OpenEvent} events.

+ * 

+ * @param <T> the type being opened

+ */

+public interface HasOpenHandlers<T> {

+  /**

+   * Adds a {@link OpenEvent} handler.

+   * 

+   * @param handler the handler

+   * @return the registration for the event

+   */

+  HandlerRegistration addOpenHandler(OpenHandler<T> handler);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java
new file mode 100644
index 0000000..a5cff3f
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasResizeHandlers.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * A widget that implements this interface is a public source of
+ * {@link ResizeEvent} events.
+ */
+public interface HasResizeHandlers {
+  /**
+   * Adds a {@link ResizeEvent} handler.
+   * 
+   * @param handler the handler
+   * @return the handler registration
+   */
+  HandlerRegistration addResizeHandler(ResizeHandler handler);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java
new file mode 100644
index 0000000..3d310c6
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasSelectionHandlers.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface is a public source of

+ * {@link SelectionEvent} events.

+ * 

+ * @param <I> the type being selected

+ */

+public interface HasSelectionHandlers<I> {

+  /**

+   * Adds a {@link SelectionEvent} handler.

+   * 

+   * @param handler the handler

+   * @return the registration for the event

+   */

+  HandlerRegistration addSelectionHandler(SelectionHandler<I> handler);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java b/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java
new file mode 100644
index 0000000..2ea1f12
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/HasValueChangeHandlers.java
@@ -0,0 +1,34 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.HandlerRegistration;

+

+/**

+ * A widget that implements this interface is a public source of

+ * {@link ValueChangeEvent} events.

+ * 

+ * @param <I> the value about to be changed

+ */

+public interface HasValueChangeHandlers<I> {

+  /**

+   * Adds a {@link ValueChangeEvent} handler.

+   * 

+   * @param handler the handler

+   * @return the registration for the event

+   */

+  HandlerRegistration addValueChangeHandler(ValueChangeHandler<I> handler);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/OpenEvent.java b/user/src/com/google/gwt/event/logical/shared/OpenEvent.java
new file mode 100644
index 0000000..34026f2
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/OpenEvent.java
@@ -0,0 +1,98 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.GwtEvent;

+import com.google.gwt.event.shared.HandlerManager;

+

+/**

+ * Represents a open event.

+ * 

+ * @param <T> the type being opened

+ */

+public class OpenEvent<T> extends GwtEvent<OpenHandler<T>> {

+

+  /**

+   * Handler type.

+   */

+  private static Type<OpenHandler<?>> TYPE;

+

+  /**

+   * Fires a open event on all registered handlers in the handler manager.If no

+   * such handlers exist, this method will do nothing.

+   * 

+   * @param <T> the target type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param target the target

+   */

+  public static <T, S extends HasOpenHandlers<T> & HasHandlers> void fire(

+      S source, T target) {

+    if (TYPE != null) {

+      HandlerManager handlers = source.getHandlers();

+      if (handlers != null) {

+        OpenEvent<T> event = new OpenEvent<T>(target);

+        handlers.fireEvent(event);

+      }

+    }

+  }

+

+  /**

+   * Gets the type associated with this event.

+   * 

+   * @return returns the handler type

+   */

+  public static Type<OpenHandler<?>> getType() {

+    if (TYPE == null) {

+      TYPE = new Type<OpenHandler<?>>();

+    }

+    return TYPE;

+  }

+

+  private final T target;

+

+  /**

+   * Creates a new open event.

+   * 

+   * @param target the ui object being opened

+   */

+  protected OpenEvent(T target) {

+    this.target = target;

+  }

+

+  /**

+   * Gets the target.

+   * 

+   * @return the target

+   */

+  public T getTarget() {

+    return target;

+  }

+

+  @Override

+  protected void dispatch(OpenHandler<T> handler) {

+    handler.onOpen(this);

+  }

+

+  // Because of type erasure, our static type is

+  // wild carded, yet the "real" type should use our I param.

+

+  @SuppressWarnings("unchecked")

+  @Override

+  protected final Type<OpenHandler<T>> getAssociatedType() {

+    return (Type) TYPE;

+  }

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/OpenHandler.java b/user/src/com/google/gwt/event/logical/shared/OpenHandler.java
new file mode 100644
index 0000000..c2053d6
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/OpenHandler.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.EventHandler;

+

+/**

+ * Handler interface for {@link OpenEvent} events.

+ * 

+ * @param <T> the type being opened

+ */

+public interface OpenHandler<T> extends EventHandler {

+

+  /**

+   * Called when {@link OpenEvent} is fired.

+   * 

+   * @param event the {@link OpenEvent} that was fired

+   */

+  void onOpen(OpenEvent<T> event);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/ResizeEvent.java b/user/src/com/google/gwt/event/logical/shared/ResizeEvent.java
new file mode 100644
index 0000000..ff731e8
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ResizeEvent.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+
+/**
+ * Fired when the event source is resized.
+ */
+public class ResizeEvent extends GwtEvent<ResizeHandler> {
+
+  /**
+   * The event type.
+   */
+  private static Type<ResizeHandler> TYPE;
+
+  /**
+   * Fires a resize event on all registered handlers in the handler source.
+   * 
+   * @param <S> The handler source
+   * @param source the source of the handlers
+   * @param width the new width
+   * @param height the new height
+   */
+  public static <S extends HasResizeHandlers & HasHandlers> void fire(S source,
+      int width, int height) {
+    if (TYPE != null) {
+      HandlerManager handlers = source.getHandlers();
+      if (handlers != null) {
+        ResizeEvent event = new ResizeEvent(width, height);
+        handlers.fireEvent(event);
+      }
+    }
+  }
+
+  /**
+   * Ensures the existence of the handler hook and then returns it.
+   * 
+   * @return returns a handler hook
+   */
+  public static Type<ResizeHandler> getType() {
+    if (TYPE == null) {
+      TYPE = new Type<ResizeHandler>();
+    }
+    return TYPE;
+  }
+
+  private final int width;
+  private final int height;
+
+  /**
+   * Construct a new {@link ResizeEvent}.
+   * 
+   * @param width the new width
+   * @param height the new height
+   */
+  protected ResizeEvent(int width, int height) {
+    this.width = width;
+    this.height = height;
+  }
+
+  /**
+   * Returns the new height.
+   * 
+   * @return the new height
+   */
+  public int getHeight() {
+    return height;
+  }
+
+  /**
+   * Returns the new width.
+   * 
+   * @return the new width
+   */
+  public int getWidth() {
+    return width;
+  }
+
+  @Override
+  public String toDebugString() {
+    assertLive();
+    return super.toDebugString() + " width = " + width + " height =" + height;
+  }
+
+  @Override
+  protected void dispatch(ResizeHandler handler) {
+    handler.onResize(this);
+  }
+
+  @Override
+  protected Type<ResizeHandler> getAssociatedType() {
+    return TYPE;
+  }
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/ResizeHandler.java b/user/src/com/google/gwt/event/logical/shared/ResizeHandler.java
new file mode 100644
index 0000000..d0c0531
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ResizeHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for {@link ResizeEvent} events.
+ */
+public interface ResizeHandler extends EventHandler {
+  /**
+   * Fired when the widget is resized.
+   * 
+   * @param event the event
+   */
+  void onResize(ResizeEvent event);
+}
diff --git a/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java b/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java
new file mode 100644
index 0000000..40a8423
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/SelectionEvent.java
@@ -0,0 +1,97 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.GwtEvent;

+import com.google.gwt.event.shared.HandlerManager;

+

+/**

+ * Represents a selection event.

+ * 

+ * @param <I> the type being selected

+ */

+public class SelectionEvent<I> extends GwtEvent<SelectionHandler<I>> {

+

+  /**

+   * Handler type.

+   */

+  private static Type<SelectionHandler<?>> TYPE;

+

+  /**

+   * Fires a selection event on all registered handlers in the handler

+   * manager.If no such handlers exist, this method will do nothing.

+   * 

+   * @param <I> the selected item type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param selectedItem the selected item

+   */

+  public static <I, S extends HasSelectionHandlers<I> & HasHandlers> void fire(

+      S source, I selectedItem) {

+    if (TYPE != null) {

+      HandlerManager handlers = source.getHandlers();

+      if (handlers != null) {

+        SelectionEvent<I> event = new SelectionEvent<I>(selectedItem);

+        handlers.fireEvent(event);

+      }

+    }

+  }

+

+  /**

+   * Gets the type associated with this event.

+   * 

+   * @return returns the handler type

+   */

+  public static Type<SelectionHandler<?>> getType() {

+    if (TYPE == null) {

+      TYPE = new Type<SelectionHandler<?>>();

+    }

+    return TYPE;

+  }

+

+  private final I selectedItem;

+

+  /**

+   * Creates a new selection event.

+   * 

+   * @param selectedItem selected item

+   */

+  protected SelectionEvent(I selectedItem) {

+    this.selectedItem = selectedItem;

+  }

+

+  /**

+   * Gets the selected item.

+   * 

+   * @return the selected item

+   */

+  public I getSelectedItem() {

+    return selectedItem;

+  }

+

+  @Override

+  protected void dispatch(SelectionHandler<I> handler) {

+    handler.onSelection(this);

+  }

+

+  // The instance knows its BeforeSelectionHandler is of type I, but the TYPE

+  // field itself does not, so we have to do an unsafe cast here.

+  @SuppressWarnings("unchecked")

+  @Override

+  protected Type<SelectionHandler<I>> getAssociatedType() {

+    return (Type) TYPE;

+  }

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/SelectionHandler.java b/user/src/com/google/gwt/event/logical/shared/SelectionHandler.java
new file mode 100644
index 0000000..9b83baa
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/SelectionHandler.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.EventHandler;

+

+/**

+ * Handler interface for {@link SelectionEvent} events.

+ * 

+ * @param <I> the type being selected

+ */

+public interface SelectionHandler<I> extends EventHandler {

+

+  /**

+   * Called when {@link SelectionEvent} is fired.

+   * 

+   * @param event the {@link SelectionEvent} that was fired

+   */

+  void onSelection(SelectionEvent<I> event);

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java b/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java
new file mode 100644
index 0000000..52376e8
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ValueChangeEvent.java
@@ -0,0 +1,117 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.GwtEvent;

+import com.google.gwt.event.shared.HandlerManager;

+

+/**

+ * Represents a value change event.

+ * 

+ * @param <I> the value about to be changed

+ */

+public class ValueChangeEvent<I> extends GwtEvent<ValueChangeHandler<I>> {

+

+  /**

+   * Handler type.

+   */

+  private static Type<ValueChangeHandler<?>> TYPE;

+

+  /**

+   * Fires a value change event on all registered handlers in the handler

+   * manager.If no such handlers exist, this method will do nothing.

+   * 

+   * @param <I> the old value type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param value the value

+   */

+  public static <I, S extends HasValueChangeHandlers<I> & HasHandlers> void fire(

+      S source, I value) {

+    if (TYPE != null) {

+      HandlerManager handlers = source.getHandlers();

+      if (handlers != null && handlers.isEventHandled(TYPE)) {

+        ValueChangeEvent<I> event = new ValueChangeEvent<I>(value);

+        handlers.fireEvent(event);

+      }

+    }

+  }

+

+  /**

+   * Fires value change event if the old value is not equal to the new value.

+   * Use this call rather than making the decision to short circuit yourself for

+   * safe handling of null.

+   * 

+   * @param <I> the old value type

+   * @param <S> The event source

+   * @param source the source of the handlers

+   * @param oldValue the oldValue, may be null

+   * @param newValue the newValue, may be null

+   */

+  public static <I, S extends HasValueChangeHandlers<I> & HasHandlers> void fireIfNotEqual(

+      S source, I oldValue, I newValue) {

+    if (TYPE != null) {

+      if (oldValue != newValue

+          && (oldValue == null || !oldValue.equals(newValue))) {

+        fire(source, newValue);

+      }

+    }

+  }

+

+  /**

+   * Gets the type associated with this event.

+   * 

+   * @return returns the handler type

+   */

+  public static Type<ValueChangeHandler<?>> getType() {

+    if (TYPE == null) {

+      TYPE = new Type<ValueChangeHandler<?>>();

+    }

+    return TYPE;

+  }

+

+  private final I value;

+

+  /**

+   * Creates a value change event.

+   * @param value the value

+   */

+  protected ValueChangeEvent(I value) {

+    this.value = value;

+  }

+

+  /**

+   * Gets the value.

+   * 

+   * @return the value

+   */

+  public I getValue() {

+    return value;

+  }

+

+  @Override

+  protected void dispatch(ValueChangeHandler<I> handler) {

+    handler.onValueChange(this);

+  }

+

+  // The instance knows its BeforeSelectionHandler is of type I, but the TYPE

+  // field itself does not, so we have to do an unsafe cast here.

+  @SuppressWarnings("unchecked")

+  @Override

+  protected Type<ValueChangeHandler<I>> getAssociatedType() {

+    return (Type) TYPE;

+  }

+}

diff --git a/user/src/com/google/gwt/event/logical/shared/ValueChangeHandler.java b/user/src/com/google/gwt/event/logical/shared/ValueChangeHandler.java
new file mode 100644
index 0000000..808b97e
--- /dev/null
+++ b/user/src/com/google/gwt/event/logical/shared/ValueChangeHandler.java
@@ -0,0 +1,33 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+package com.google.gwt.event.logical.shared;

+

+import com.google.gwt.event.shared.EventHandler;

+

+/**

+ * Handler interface for {@link ValueChangeEvent} events.

+ * 

+ * @param <I> the value about to be changed

+ */

+public interface ValueChangeHandler<I> extends EventHandler {

+

+  /**

+   * Called when {@link ValueChangeEvent} is fired.

+   * 

+   * @param event the {@link ValueChangeEvent} that was fired

+   */

+  void onValueChange(ValueChangeEvent<I> event);

+}

diff --git a/user/src/com/google/gwt/event/shared/DefaultHandlerRegistration.java b/user/src/com/google/gwt/event/shared/DefaultHandlerRegistration.java
new file mode 100644
index 0000000..7e79319
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/DefaultHandlerRegistration.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.shared;
+
+import com.google.gwt.event.shared.GwtEvent.Type;
+
+/**
+ * Default implementation of {@link HandlerRegistration}.
+ */
+public class DefaultHandlerRegistration implements HandlerRegistration {
+
+  private final HandlerManager manager;
+  private final EventHandler handler;
+  private final Type<?> type;
+
+  /**
+   * Creates a new handler registration.
+   * 
+   * @param <H> Handler type
+   * 
+   * @param manager the handler manager
+   * @param type the event type
+   * @param handler the handler
+   */
+  protected <H extends EventHandler> DefaultHandlerRegistration(
+      HandlerManager manager, Type<H> type, H handler) {
+    this.manager = manager;
+    this.handler = handler;
+    this.type = type;
+  }
+
+  /**
+   * Removes the given handler from its manager.
+   */
+  @SuppressWarnings({"unchecked", "deprecation"})
+  // This is safe because when the elements were passed in they conformed to
+  // Type<H>,H.
+  public void removeHandler() {
+    manager.removeHandler((Type<EventHandler>) type, handler);
+  }
+
+  EventHandler getHandler() {
+    return handler;
+  }
+}
diff --git a/user/src/com/google/gwt/event/shared/EventHandler.java b/user/src/com/google/gwt/event/shared/EventHandler.java
new file mode 100644
index 0000000..2558629
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/EventHandler.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.shared;
+
+/**
+ * Marker interface for event handlers. All GWT event handlers should extend
+ * {@link EventHandler}.
+ */
+public interface EventHandler {
+
+}
diff --git a/user/src/com/google/gwt/event/shared/GwtEvent.java b/user/src/com/google/gwt/event/shared/GwtEvent.java
new file mode 100644
index 0000000..8eaba34
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/GwtEvent.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.shared;
+
+/**
+ * Root of all GWT events. All GWT events are considered dead and should no
+ * longer be accessed once the {@link HandlerManager} which originally fired the
+ * event finishes with it. That is, don't hold on to event objects outside of
+ * your handler methods.
+ * 
+ * @param <H> handler type
+ * 
+ */
+public abstract class GwtEvent<H extends EventHandler> {
+
+  /**
+   * Type class used to register events with the {@link HandlerManager}.
+   * <p>
+   * Type is parameterized by the handler type in order to make the addHandler
+   * method type safe.
+   * </p>
+   * 
+   * @param <H> handler type
+   */
+  public static class Type<H> {
+    private final int index;
+
+    /**
+     * Constructor.
+     */
+    public Type() {
+      index = HandlerManager.createTypeHashCode();
+    }
+
+    // We override hash code to make it as efficient as possible.
+    @Override
+    public final int hashCode() {
+      return index;
+    }
+
+    @Override
+    public String toString() {
+      return "Event type";
+    }
+  }
+
+  private boolean dead;
+
+  private Object source;
+
+  /**
+   * Constructor.
+   */
+  protected GwtEvent() {
+  }
+
+  /**
+   * Returns the source that last fired this event.
+   * 
+   * @return object representing the source of this event
+   */
+  public Object getSource() {
+    assertLive();
+    return source;
+  }
+
+  /**
+   * This is a method used primarily for debugging. It gives a string
+   * representation of the event details. This does not override the toString
+   * method because the compiler cannot always optimize toString out correctly.
+   * Event types should override as desired.
+   * 
+   * @return a string representing the event's specifics.
+   */
+  public String toDebugString() {
+    String name = this.getClass().getName();
+    name = name.substring(name.lastIndexOf(".") + 1);
+    return "event: " + name + ":";
+  }
+
+  /**
+   * The toString() for abstract event is overridden to avoid accidently
+   * including class literals in the the compiled output. Use
+   * {@link GwtEvent} #toDebugString to get more information about the
+   * event.
+   */
+  @Override
+  public String toString() {
+    return "An event type";
+  }
+
+  /**
+   * Asserts that the event still should be accessed. All events are considered
+   * to be "dead" after their original handler manager finishes firing them. An
+   * event can be revived by calling {@link GwtEvent#revive()}.
+   */
+  protected void assertLive() {
+    assert (!dead) : "This event has already finished being processed by its original handler manager, so you can no longer access it";
+  }
+
+  /**
+   * Should only be called by {@link HandlerManager}. In other words, do not use
+   * or call.
+   * 
+   * @param handler handler
+   */
+  protected abstract void dispatch(H handler);
+
+  /**
+   * Returns the type used to register this event. Used by handler manager to
+   * dispatch events to the correct handlers.
+   * 
+   * @return the type
+   */
+  protected abstract Type<H> getAssociatedType();
+
+  /**
+   * Is the event current live?
+   * 
+   * @return whether the event is live
+   */
+  protected final boolean isLive() {
+    return !dead;
+  }
+
+  /**
+   * Revives the event. Used when recycling event instances.
+   */
+  protected void revive() {
+    dead = false;
+    source = null;
+  }
+
+  /**
+   * Called after the event manager has finished processing the event.
+   */
+  void onRelease() {
+    dead = true;
+    source = null;
+  }
+
+  /**
+   * Set the source that triggered this event.
+   * 
+   * @param source the source of this event, should only be set by a
+   *          {@link HandlerManager}
+   */
+  void setSource(Object source) {
+    this.source = source;
+  }
+}
diff --git a/user/src/com/google/gwt/event/shared/HandlerManager.java b/user/src/com/google/gwt/event/shared/HandlerManager.java
new file mode 100644
index 0000000..898ad91
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/HandlerManager.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.shared;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.event.shared.GwtEvent.Type;
+import com.google.gwt.user.client.Command;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Manager responsible for adding handlers to event sources and firing those
+ * handlers on passed in events.
+ */
+public class HandlerManager {
+  /**
+   * Deferred binding used to allow users to optionally chose to use the
+   * JavaScript handler registry.
+   */
+  static class WhichRegistry {
+    public boolean useJSRegistry() {
+      return false;
+    }
+  }
+
+  /**
+   * Allows users to use the JavaScript handler registry. Cut/Copy lines below
+   * to use.
+   * 
+   * <pre>
+      <replace-with
+           class="com.google.gwt.event.shared.HandlerManager.UseJsRegistry">
+         <when-type-is
+      class="com.google.gwt.event.shared.HandlerManager.WhichRegistry" />
+       </replace-with>
+     </pre>
+   */
+  static class UseJsRegistry extends WhichRegistry {
+    @Override
+    public boolean useJSRegistry() {
+      return true;
+    }
+  }
+
+  /**
+   * The default handler registry.
+   */
+  private static class JavaHandlerRegistry {
+    private final HashMap<GwtEvent.Type<?>, ArrayList<?>> map = new HashMap<GwtEvent.Type<?>, ArrayList<?>>();
+
+    private <H extends EventHandler> void addHandler(Type<H> type, H handler) {
+      ArrayList<H> l = get(type);
+      if (l == null) {
+        l = new ArrayList<H>();
+        map.put(type, l);
+      }
+      l.add(handler);
+    }
+
+    private <H extends EventHandler> void fireEvent(GwtEvent<H> event) {
+      Type<H> type = event.getAssociatedType();
+      int count = getHandlerCount(type);
+      for (int i = 0; i < count; i++) {
+        H handler = this.<H> getHandler(type, i);
+        event.dispatch(handler);
+      }
+    }
+
+    @SuppressWarnings("unchecked")
+    private <H> ArrayList<H> get(GwtEvent.Type<H> type) {
+      // This cast is safe because we control the puts.
+      return (ArrayList<H>) map.get(type);
+    }
+
+    private <H extends EventHandler> H getHandler(GwtEvent.Type<H> eventKey,
+        int index) {
+      ArrayList<H> l = get(eventKey);
+      return l.get(index);
+    }
+
+    private int getHandlerCount(GwtEvent.Type<?> eventKey) {
+      ArrayList<?> l = map.get(eventKey);
+      return l == null ? 0 : l.size();
+    }
+
+    private <H> void removeHandler(GwtEvent.Type<H> eventKey, H handler) {
+      ArrayList<H> l = get(eventKey);
+      boolean result = l.remove(handler);
+      assert result : "Tried to remove unknown handler: " + handler + " from "
+          + eventKey;
+    }
+  }
+
+  /**
+   * Optional JavaScript handler registry.
+   * 
+   * This is in the shared class but should never be called outside of a GWT
+   * runtime environment.
+   * 
+   * The JsHandlerRegistry makes use of the fact that in the large majority of
+   * cases, only one or two handlers are added for each event type. Therefore,
+   * rather than storing handlers in a list of lists, we store then in a single
+   * flattened array with an escape clause to handle the rare case where we have
+   * more handlers then expected.
+   */
+  private static class JsHandlerRegistry extends JavaScriptObject {
+
+    // Used to optimize the JavaScript handler container structure.
+    private static int EXPECTED_HANDLERS = 5;
+
+    private static int createIndex() {
+      // Need to leave space for the size and the unflattened list if we end up
+      // needing it.
+      index += EXPECTED_HANDLERS + 2;
+      return index;
+    }
+
+    /**
+     * Required constructor.
+     */
+    protected JsHandlerRegistry() {
+    }
+
+    private <H extends EventHandler> void addHandler(Type<H> type, H myHandler) {
+
+      // The base is the equivalent to a c pointer into the flattened handler
+      // data structure.
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean flattened = isFlattened(base);
+      H handler = myHandler;
+      // If we already have the maximum number of handlers we can store in the
+      // flattened data structure, store the handlers in an external list
+      // instead.
+      if ((count == EXPECTED_HANDLERS) & flattened) {
+        unflatten(base);
+        flattened = false;
+      }
+      if (flattened) {
+        setFlatHandler(base, count, handler);
+      } else {
+        setHandler(base, count, handler);
+      }
+      setCount(base, count + 1);
+    }
+
+    private <H extends EventHandler> void fireEvent(GwtEvent<H> event) {
+      Type<H> type = event.getAssociatedType();
+      int base = type.hashCode();
+      int count = getCount(base);
+      boolean isFlattened = isFlattened(base);
+      if (isFlattened) {
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire. JavaScript array has no intrinsic
+          // typing information, so cast is inherently necessary.
+          H handler = this.<H> getFlatHandler(base, i);
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      } else {
+        JavaScriptObject handlers = getHandlers(base);
+        for (int i = 0; i < count; i++) {
+          // Gets the given handler to fire. JavaScript array has no intrinsic
+          // typing information, so cast is inherently necessary.
+          H handler = this.<H> getHandler(handlers, i);
+          // Fires the handler.
+          event.dispatch(handler);
+        }
+      }
+    }
+
+    private native int getCount(int index) /*-{
+      var count = this[index];
+      return count == null? 0:count;
+    }-*/;
+
+    private native <H extends EventHandler> H getFlatHandler(int base, int index) /*-{
+      return this[base + 2 + index];
+    }-*/;
+
+    private <H extends EventHandler> H getHandler(GwtEvent.Type<H> type,
+        int index) {
+      int base = type.hashCode();
+      return this.<H> getHandler(base, index, isFlattened(base));
+    }
+
+    private native <H extends EventHandler> H getHandler(int base, int index,
+        boolean flattened) /*-{
+      return flattened? this[base + 2 + index]: this[base + 1][index];
+    }-*/;
+
+    private native <H extends EventHandler> H getHandler(
+        JavaScriptObject handlers, int index) /*-{
+      return handlers[index];
+    }-*/;
+
+    private int getHandlerCount(GwtEvent.Type<?> eventKey) {
+      return getCount(eventKey.hashCode());
+    }
+
+    private native JavaScriptObject getHandlers(int base) /*-{
+      return this[base + 1];
+    }-*/;
+
+    private native boolean isFlattened(int base) /*-{
+      return this[base + 1] == null;
+    }-*/;
+
+    private <H> void removeHandler(GwtEvent.Type<H> eventKey,
+        EventHandler handler) {
+      int base = eventKey.hashCode();
+
+      // Removing a handler is unusual, so smaller code is preferable to
+      // handling both flat and dangling list of pointers.
+      if (isFlattened(base)) {
+        unflatten(base);
+      }
+      boolean result = removeHelper(base, handler);
+      // Hiding this behind an assertion as we'd rather not force the compiler
+      // to have to include all handler.toString() instances.
+      assert result : handler + " did not exist";
+    }
+
+    private native boolean removeHelper(int base, EventHandler handler) /*-{
+      // Find the handler.
+      var count = this[base];
+      var handlerList = this[base + 1];
+      var handlerIndex = -1;
+      for(var index = 0;  index < count; index++){
+        if(handlerList[index] == handler){
+          handlerIndex = index;
+          break;
+        }
+      }
+      if(handlerIndex == -1) {
+        return false;
+      }
+
+      // Remove the handler.
+      var last = count -1;
+      for(; handlerIndex < last; handlerIndex++){
+        handlerList[handlerIndex] = handlerList[handlerIndex+1]
+      }
+      handlerList[last] = null;
+      this[base] = this[base]-1;
+      return true;
+    }-*/;
+
+    private native void setCount(int index, int count) /*-{
+      this[index] = count;
+    }-*/;
+
+    private native void setFlatHandler(int base, int index, EventHandler handler) /*-{
+      this[base + 2 + index] = handler;
+    }-*/;
+
+    private native void setHandler(int base, int index, EventHandler handler) /*-{
+      this[base + 1][index] = handler;
+    }-*/;
+
+    private native void unflatten(int base) /*-{
+      var handlerList = {};
+      var count = this[base];
+      var start = base + 2;
+       for(var i = 0; i < count; i++){
+         handlerList[i] = this[start + i];
+         this[start + i] = null;
+        }
+       this[base + 1] = handlerList;
+    }-*/;
+  }
+
+  private static final boolean useJsRegistry = GWT.isClient()
+      && ((WhichRegistry) GWT.create(WhichRegistry.class)).useJSRegistry();
+  private static int index = 0;
+
+  // Used to assign hash codes to gwt event types so they are easy to store in a
+  // js structure.
+  static int createTypeHashCode() {
+    if (useJsRegistry) {
+      return JsHandlerRegistry.createIndex();
+    } else {
+      return ++index;
+    }
+  }
+
+  private int firingDepth = 0;
+  // Only one of JsHandlerRegistry and JavaHandlerRegistry are live at once.
+  private JsHandlerRegistry javaScriptRegistry;
+  private JavaHandlerRegistry javaRegistry;
+
+  // source of the event.
+  private final Object source;
+
+  // Add and remove operations received during dispatch.
+  private List<Command> deferredDeltas;
+
+  /**
+   * Creates a handler manager with the given source.
+   * 
+   * @param source the event source
+   */
+  public HandlerManager(Object source) {
+    if (useJsRegistry) {
+      javaScriptRegistry = JavaScriptObject.createObject().cast();
+    } else {
+      javaRegistry = new JavaHandlerRegistry();
+    }
+    this.source = source;
+  }
+
+  /**
+   * Adds a handle.
+   * 
+   * @param <H> The type of handler
+   * @param type the event type associated with this handler
+   * @param handler the handler
+   * @return the handler registration, can be stored in order to remove the
+   * handler later
+   */
+  public <H extends EventHandler> HandlerRegistration addHandler(
+      GwtEvent.Type<H> type, final H handler) {
+    assert type != null : "Cannot add a handler with a null type";
+    assert handler != null : "Cannot add a null handler";
+    if (firingDepth > 0) {
+      enqueueAdd(type, handler);
+    } else {
+      doAdd(type, handler);
+    }
+    return new DefaultHandlerRegistration(this, type, handler);
+  }
+
+  /**
+   * Fires the given event to the handlers listening to the event's type.
+   * 
+   * Note, any subclass should be very careful about overriding this method, as
+   * adds/removes of handlers will not be safe except within this
+   * implementation.
+   * 
+   * @param event the event
+   */
+
+  public void fireEvent(GwtEvent<?> event) {
+    // If it not live we should revive it.
+    if (!event.isLive()) {
+      event.revive();
+    }
+    Object oldSource = event.getSource();
+    event.setSource(source);
+    try {
+      firingDepth++;
+      if (useJsRegistry) {
+        javaScriptRegistry.fireEvent(event);
+      } else {
+        javaRegistry.fireEvent(event);
+      }
+    } finally {
+      firingDepth--;
+      if (firingDepth == 0) {
+        handleQueuedAddsAndRemoves();
+      }
+    }
+    if (oldSource == null) {
+      // This was my event, so I should kill it now that I'm done.
+      event.onRelease();
+    } else {
+      // Restoring the source for the next handler to use.
+      event.setSource(oldSource);
+    }
+  }
+
+  /**
+   * Gets the handler at the given index.
+   * 
+   * @param <H> the event handler type
+   * @param index the index
+   * @param type the handler's event type
+   * @return the given handler
+   */
+  public <H extends EventHandler> H getHandler(GwtEvent.Type<H> type, int index) {
+    assert index < getHandlerCount(type) : "handlers for " + type.getClass()
+        + " have size: " + getHandlerCount(type)
+        + " so do not have a handler at index: " + index;
+    if (useJsRegistry) {
+      return javaScriptRegistry.getHandler(type, index);
+    } else {
+      return javaRegistry.getHandler(type, index);
+    }
+  }
+
+  /**
+   * Gets the number of handlers listening to the event type.
+   * 
+   * @param type the event type
+   * @return the number of registered handlers
+   */
+  public int getHandlerCount(Type<?> type) {
+    if (useJsRegistry) {
+      return javaScriptRegistry.getHandlerCount(type);
+    } else {
+      return javaRegistry.getHandlerCount(type);
+    }
+  }
+
+  /**
+   * Are there handlers in this manager listening to the given event type?
+   * 
+   * @param type the event type
+   * @return are handlers listening on the given event type
+   */
+  public boolean isEventHandled(Type<?> type) {
+    return getHandlerCount(type) > 0;
+  }
+
+  /**
+   * Removes the given handler from the specified event type. Normally,
+   * applications should call {@link HandlerRegistration#removeHandler()}
+   * instead.
+   * 
+   * @param <H> handler type
+   * 
+   * @param type the event type
+   * @param handler the handler
+   * @deprecated We currently believe this method will not be needed after
+   * listeners are removed in GWT 2.0. If you have a use case for it after that
+   * time, please add your comments to issue
+   * http://code.google.com/p/google-web-toolkit/issues/detail?id=3102
+   */
+  public <H extends EventHandler> void removeHandler(GwtEvent.Type<H> type,
+      final H handler) {
+    if (firingDepth > 0) {
+      enqueueRemove(type, handler);
+    } else {
+      doRemove(type, handler);
+    }
+  }
+
+  private void defer(Command command) {
+    if (deferredDeltas == null) {
+      deferredDeltas = new ArrayList<Command>();
+    }
+    deferredDeltas.add(command);
+  }
+
+  private <H extends EventHandler> void doAdd(GwtEvent.Type<H> type,
+      final H handler) {
+    if (useJsRegistry) {
+      javaScriptRegistry.addHandler(type, handler);
+    } else {
+      javaRegistry.addHandler(type, handler);
+    }
+  }
+
+  private <H extends EventHandler> void doRemove(GwtEvent.Type<H> type,
+      final H handler) {
+    if (useJsRegistry) {
+      javaScriptRegistry.removeHandler(type, handler);
+    } else {
+      javaRegistry.removeHandler(type, handler);
+    }
+  }
+
+  private <H extends EventHandler> void enqueueAdd(final GwtEvent.Type<H> type,
+      final H handler) {
+    defer(new Command() {
+      public void execute() {
+        doAdd(type, handler);
+      }
+    });
+  }
+
+  private <H extends EventHandler> void enqueueRemove(
+      final GwtEvent.Type<H> type, final H handler) {
+    defer(new Command() {
+      public void execute() {
+        doRemove(type, handler);
+      }
+    });
+  }
+
+  private void handleQueuedAddsAndRemoves() {
+    if (deferredDeltas != null) {
+      try {
+        for (Command c : deferredDeltas) {
+          c.execute();
+        }
+      } finally {
+        deferredDeltas = null;
+      }
+    }
+  }
+}
diff --git a/user/src/com/google/gwt/event/shared/HandlerRegistration.java b/user/src/com/google/gwt/event/shared/HandlerRegistration.java
new file mode 100644
index 0000000..13344de
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/HandlerRegistration.java
@@ -0,0 +1,35 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.shared;

+

+/**

+ * Registration returned from a call to

+ * {@link HandlerManager#addHandler(com.google.gwt.event.shared.GwtEvent.Type, EventHandler)}

+ * . Use the handler registration to remove handlers when they are no longer

+ * needed.

+ * 

+ * Note, this interface is under the control of the {@link HandlerManager} class

+ * and may be expanded over time, so extend {@link DefaultHandlerRegistration}

+ * if you do not wish to get compiler errors if we extend the handler registry

+ * functionality.

+ */

+public interface HandlerRegistration {

+  /**

+   * Removes the given handler from its manager.

+   */

+  void removeHandler();

+}

diff --git a/user/src/com/google/gwt/event/shared/HasHandlerManager.java b/user/src/com/google/gwt/event/shared/HasHandlerManager.java
new file mode 100644
index 0000000..906258b
--- /dev/null
+++ b/user/src/com/google/gwt/event/shared/HasHandlerManager.java
@@ -0,0 +1,32 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.shared;

+

+/**

+ * 

+ * Characteristic interface indicating that the given widget fires events via a

+ * {@link HandlerManager}.

+ * 

+ */

+public interface HasHandlerManager {

+  /**

+   * Gets this widget's handler manager.

+   * 

+   * @return the manager

+   */

+  HandlerManager getHandlerManager();

+}

diff --git a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
index 91e77e4..56d6436 100644
--- a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
+++ b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
@@ -175,12 +175,12 @@
  * 
  * <dt>Number</dt>
  * <dd>the minimum number of digits. Shorter numbers are zero-padded to this
- * amount (e.g. if <code>"m"</code> produces <code>"6"</code>,
- * <code>"mm"</code> produces <code>"06"</code>). Year is handled
- * specially; that is, if the count of 'y' is 2, the Year will be truncated to 2
- * digits. (e.g., if <code>"yyyy"</code> produces <code>"1997"</code>,
- * <code>"yy"</code> produces <code>"97"</code>.) Unlike other fields,
- * fractional seconds are padded on the right with zero.</dd>
+ * amount (e.g. if <code>"m"</code> produces <code>"6"</code>, <code>"mm"</code>
+ * produces <code>"06"</code>). Year is handled specially; that is, if the count
+ * of 'y' is 2, the Year will be truncated to 2 digits. (e.g., if
+ * <code>"yyyy"</code> produces <code>"1997"</code>, <code>"yy"</code> produces
+ * <code>"97"</code>.) Unlike other fields, fractional seconds are padded on the
+ * right with zero.</dd>
  * 
  * <dt>Text or Number</dt>
  * <dd>3 or more, use text, otherwise use number. (e.g. <code>"M"</code>
@@ -190,27 +190,27 @@
  * </dl>
  * 
  * <p>
- * Any characters in the pattern that are not in the ranges of ['<code>a</code>'..'<code>z</code>']
- * and ['<code>A</code>'..'<code>Z</code>'] will be treated as quoted
- * text. For instance, characters like '<code>:</code>', '<code>.</code>', '<code> </code>'
- * (space), '<code>#</code>' and '<code>@</code>' will appear in the
- * resulting time text even they are not embraced within single quotes.
+ * Any characters in the pattern that are not in the ranges of ['<code>a</code>
+ * '..'<code>z</code>'] and ['<code>A</code>'..'<code>Z</code>'] will be treated
+ * as quoted text. For instance, characters like '<code>:</code>', '
+ * <code>.</code>', '<code> </code>' (space), '<code>#</code>' and '
+ * <code>@</code>' will appear in the resulting time text even they are not
+ * embraced within single quotes.
  * </p>
  * 
  * <p>
  * [Time Zone Handling] Web browsers don't provide all the information we need
  * for proper time zone formating -- so GWT has a copy of the required data, for
  * your convenience. For simpler cases, one can also use a fallback
- * implementation that only keeps track of the current timezone offset. These two
- * approaches are called, respectively, Common TimeZones and Simple TimeZones,
- * although both are implemented with the same TimeZone class.
+ * implementation that only keeps track of the current timezone offset. These
+ * two approaches are called, respectively, Common TimeZones and Simple
+ * TimeZones, although both are implemented with the same TimeZone class.
  * 
- *  "TimeZone createTimeZone(String timezoneData)"
- * returns a Common TimeZone object, and  
- * "TimeZone createTimeZone(int timeZoneOffsetInMinutes)" returns a Simple
- * TimeZone object. The one provided by OS fall into to Simple TimeZone category.
- * For formatting purpose, following table shows the behavior of GWT 
- * DateTimeFormat.  
+ * "TimeZone createTimeZone(String timezoneData)" returns a Common TimeZone
+ * object, and "TimeZone createTimeZone(int timeZoneOffsetInMinutes)" returns a
+ * Simple TimeZone object. The one provided by OS fall into to Simple TimeZone
+ * category. For formatting purpose, following table shows the behavior of GWT
+ * DateTimeFormat.
  * </p>
  * <table>
  * <tr>
@@ -247,8 +247,8 @@
  * 
  * <h3>Parsing Dates and Times</h3>
  * <p>
- * This implementation can parse partial date/time. Current date will be used
- * to fill in an unspecified date part. 00:00:00 will be used to fill in an
+ * This implementation can parse partial date/time. Current date will be used to
+ * fill in an unspecified date part. 00:00:00 will be used to fill in an
  * unspecified time.
  * </p>
  * 
@@ -277,13 +277,13 @@
  * </p>
  * <p>
  * [Note on TimeZone] The time zone support for parsing is limited. Only
- * standard GMT and RFC format are supported. Time zone specification using
- * time zone id (like America/Los_Angeles), time zone names (like PST, Pacific
+ * standard GMT and RFC format are supported. Time zone specification using time
+ * zone id (like America/Los_Angeles), time zone names (like PST, Pacific
  * Standard Time) are not supported. Normally, it is too much a burden for a
- * client application to load all the time zone symbols. And in almost all
- * those cases, it is a better choice to do such parsing on server side
- * through certain RPC mechanism. This decision is based on particular use
- * cases we have studied; in principle, it could be changed in future versions.
+ * client application to load all the time zone symbols. And in almost all those
+ * cases, it is a better choice to do such parsing on server side through
+ * certain RPC mechanism. This decision is based on particular use cases we have
+ * studied; in principle, it could be changed in future versions.
  * </p>
  * 
  * <h3>Examples</h3>
@@ -326,19 +326,19 @@
  * 
  * <h3>Additional Parsing Considerations</h3>
  * <p>
- * When parsing a date string using the abbreviated year pattern (<code>"yy"</code>),
- * the parser must interpret the abbreviated year relative to some century. It
- * does this by adjusting dates to be within 80 years before and 20 years after
- * the time the parser instance is created. For example, using a pattern of
- * <code>"MM/dd/yy"</code> and a <code>DateTimeFormat</code> object created
- * on Jan 1, 1997, the string <code>"01/11/12"</code> would be interpreted as
- * Jan 11, 2012 while the string <code>"05/04/64"</code> would be interpreted
- * as May 4, 1964. During parsing, only strings consisting of exactly two
- * digits, as defined by {@link java.lang.Character#isDigit(char)}, will be
- * parsed into the default century. If the year pattern does not have exactly
- * two 'y' characters, the year is interpreted literally, regardless of the
- * number of digits. For example, using the pattern <code>"MM/dd/yyyy"</code>,
- * "01/11/12" parses to Jan 11, 12 A.D.
+ * When parsing a date string using the abbreviated year pattern (
+ * <code>"yy"</code>), the parser must interpret the abbreviated year relative
+ * to some century. It does this by adjusting dates to be within 80 years before
+ * and 20 years after the time the parser instance is created. For example,
+ * using a pattern of <code>"MM/dd/yy"</code> and a <code>DateTimeFormat</code>
+ * object created on Jan 1, 1997, the string <code>"01/11/12"</code> would be
+ * interpreted as Jan 11, 2012 while the string <code>"05/04/64"</code> would be
+ * interpreted as May 4, 1964. During parsing, only strings consisting of
+ * exactly two digits, as defined by {@link java.lang.Character#isDigit(char)},
+ * will be parsed into the default century. If the year pattern does not have
+ * exactly two 'y' characters, the year is interpreted literally, regardless of
+ * the number of digits. For example, using the pattern
+ * <code>"MM/dd/yyyy"</code>, "01/11/12" parses to Jan 11, 12 A.D.
  * </p>
  * 
  * <p>
@@ -356,13 +356,13 @@
  * 
  * <p>
  * In the current implementation, timezone parsing only supports
- * <code>GMT:hhmm</code>, <code>GMT:+hhmm</code>, and
- * <code>GMT:-hhmm</code>.
+ * <code>GMT:hhmm</code>, <code>GMT:+hhmm</code>, and <code>GMT:-hhmm</code>.
  * </p>
  * 
  * <h3>Example</h3> {@example com.google.gwt.examples.DateTimeFormatExample}
- *
+ * 
  */
+@SuppressWarnings("deprecation")
 public class DateTimeFormat {
   /**
    * Class PatternPart holds a "compiled" pattern part.
@@ -405,7 +405,7 @@
   private static DateTimeFormat cachedLongDateTimeFormat;
   private static DateTimeFormat cachedMediumDateTimeFormat;
   private static DateTimeFormat cachedShortDateTimeFormat;
-  
+
   private static final int NUM_MILLISECONDS_IN_DAY = 24 * 60 * 60000;
   private static final DateTimeConstants defaultDateTimeConstants = (DateTimeConstants) GWT.create(DateTimeConstants.class);
 
@@ -420,15 +420,15 @@
   private static final int MINUTES_PER_HOUR = 60;
 
   /**
-   * Returns a DateTimeFormat object using the specified pattern. If you need 
-   * to format or parse repeatedly using the same pattern, it is highly 
-   * recommended that you cache the returned <code>DateTimeFormat</code> 
-   * object and reuse it rather than calling this method repeatedly.
+   * Returns a DateTimeFormat object using the specified pattern. If you need to
+   * format or parse repeatedly using the same pattern, it is highly recommended
+   * that you cache the returned <code>DateTimeFormat</code> object and reuse it
+   * rather than calling this method repeatedly.
    * 
    * @param pattern string to specify how the date should be formatted
    * 
-   * @return a <code>DateTimeFormat</code> object that can be used for format
-   *         or parse date/time values matching the specified pattern
+   * @return a <code>DateTimeFormat</code> object that can be used for format or
+   *         parse date/time values matching the specified pattern
    * 
    * @throws IllegalArgumentException if the specified pattern could not be
    *           parsed
@@ -438,8 +438,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for full date format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for full date format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -452,7 +452,7 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for full date and time format. The 
+   * Retrieve the DateTimeFormat object for full date and time format. The
    * pattern for this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
@@ -467,8 +467,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for full time format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for full time format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -481,8 +481,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for long date format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for long date format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -495,7 +495,7 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for long date and time format. The 
+   * Retrieve the DateTimeFormat object for long date and time format. The
    * pattern for this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
@@ -510,8 +510,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for long time format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for long time format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -524,8 +524,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for medium date format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for medium date format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -538,7 +538,7 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for medium date and time format. The 
+   * Retrieve the DateTimeFormat object for medium date and time format. The
    * pattern for this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
@@ -553,8 +553,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for medium time format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for medium time format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -567,8 +567,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for short date format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for short date format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -581,7 +581,7 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for short date and time format. The 
+   * Retrieve the DateTimeFormat object for short date and time format. The
    * pattern for this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
@@ -596,8 +596,8 @@
   }
 
   /**
-   * Retrieve the DateTimeFormat object for short time format. The pattern
-   * for this format is predefined for each locale.
+   * Retrieve the DateTimeFormat object for short time format. The pattern for
+   * this format is predefined for each locale.
    * 
    * @return A DateTimeFormat object.
    */
@@ -655,14 +655,15 @@
     TimeZone timeZone = TimeZone.createTimeZone(date.getTimezoneOffset());
     return format(date, timeZone);
   }
-  
+
   /**
    * Format a date object using specified time zone.
    * 
    * @param date the date object being formatted
    * @param timeZone a TimeZone object that holds time zone information
    * 
-   * @return string representation for this date in the format defined by this object
+   * @return string representation for this date in the format defined by this
+   *         object
    */
   public String format(Date date, TimeZone timeZone) {
     // We use the Date class to calculate each date/time field in order
@@ -676,20 +677,20 @@
     // has the same date/time fields (year, month, date, hour, minutes, etc)
     // in GMT-0800 as original date in our target time zone (GMT-0400). We
     // just need to take care of time zone display, but that's needed anyway.
- 
-    // Things get a little bit more tricky when a daylight time transition 
-    // happens. For example, if the OS timezone is America/Los_Angeles, 
+
+    // Things get a little bit more tricky when a daylight time transition
+    // happens. For example, if the OS timezone is America/Los_Angeles,
     // it is just impossible to have a Date represent 2006/4/2 02:30, because
-    // 2:00 to 3:00 on that day does not exist in  US Pacific time zone because
+    // 2:00 to 3:00 on that day does not exist in US Pacific time zone because
     // of the daylight time switch.
-    
+
     // But we can use 2 separate date objects, one to represent 2006/4/2, one
     // to represent 02:30. Of course, for the 2nd date object its date can be
     // any other day in that year, except 2006/4/2. So we end up have 3 Date
     // objects: one for resolving "Year, month, day", one for time within that
     // day, and the original date object, which is needed for figuring out
     // actual time zone offset.
-    
+
     int diff = (date.getTimezoneOffset() - timeZone.getOffset(date)) * 60000;
     Date keepDate = new Date(date.getTime() + diff);
     Date keepTime = keepDate;
@@ -701,7 +702,7 @@
       }
       keepTime = new Date(date.getTime() + diff);
     }
-    
+
     StringBuffer toAppendTo = new StringBuffer(64);
     int j, n = pattern.length();
     for (int i = 0; i < n;) {
@@ -759,7 +760,7 @@
 
     return toAppendTo.toString();
   }
-  
+
   /**
    * Retrieve the pattern used in this DateTimeFormat object.
    * 
@@ -1295,7 +1296,8 @@
   }
 
   /**
-   * This method parses the input string and fills its value into a {@link Date}.
+   * This method parses the input string and fills its value into a {@link Date}
+   * .
    * 
    * If using lenient parsing, certain invalid dates and times will be parsed.
    * For example, February 32nd would be parsed as March 4th in lenient mode,
@@ -1577,8 +1579,8 @@
    * Formats a single field according to pattern specified.
    * 
    * @param ch pattern character for this field
-   * @param count number of time pattern char repeats; this controls how a field 
-   * should be formatted
+   * @param count number of time pattern char repeats; this controls how a field
+   *          should be formatted
    * @param date the date object to be formatted
    * @param adjustedDate holds the time zone adjusted date fields
    * @param adjustedTime holds the time zone adjusted time fields
diff --git a/user/src/com/google/gwt/i18n/client/impl/DateRecord.java b/user/src/com/google/gwt/i18n/client/impl/DateRecord.java
index 124e229..2c8158b 100644
--- a/user/src/com/google/gwt/i18n/client/impl/DateRecord.java
+++ b/user/src/com/google/gwt/i18n/client/impl/DateRecord.java
@@ -27,6 +27,7 @@
  * during parsing phase and resolve them in a later time when all information
  * can be processed together.
  */
+@SuppressWarnings("deprecation")
 public class DateRecord extends Date {
 
   /*
diff --git a/user/src/com/google/gwt/junit/JUnitMessageQueue.java b/user/src/com/google/gwt/junit/JUnitMessageQueue.java
index e412721..e45ac3f 100644
--- a/user/src/com/google/gwt/junit/JUnitMessageQueue.java
+++ b/user/src/com/google/gwt/junit/JUnitMessageQueue.java
@@ -99,39 +99,6 @@
   }
 
   /**
-   * Returns a human-formatted message identifying what clients have connected
-   * but have not yet reported results for this test.  It is used in a timeout
-   * condition, to identify what we're still waiting on.
-   * 
-   * @return human readable message
-   */
-  public String getWorkingClients() {
-    synchronized (clientStatusesLock) {
-      StringBuilder buf = new StringBuilder();
-      int itemCount = 0;
-      for (ClientStatus clientStatus : clientStatuses.values()) {
-        if (clientStatus.hasRequestedCurrentTest 
-            && clientStatus.currentTestResults == null) {
-          if (itemCount > 0) {
-            buf.append(", ");
-          }
-          buf.append(clientStatus.clientId);
-          ++itemCount;
-        }
-      }
-      int difference = numClients - itemCount;
-      if (difference > 0) {
-        if (itemCount > 0) {
-          buf.append('\n');
-        }
-        buf.append(difference + 
-            " other client(s) haven't responded back to JUnitShell since the start of the test.");
-      }
-      return buf.toString();
-    }
-  }
-
-  /**
    * Called by the servlet to query for for the next method to test.
    * 
    * @param timeout how long to wait for an answer
@@ -179,6 +146,39 @@
   }
 
   /**
+   * Returns a human-formatted message identifying what clients have connected
+   * but have not yet reported results for this test.  It is used in a timeout
+   * condition, to identify what we're still waiting on.
+   * 
+   * @return human readable message
+   */
+  public String getWorkingClients() {
+    synchronized (clientStatusesLock) {
+      StringBuilder buf = new StringBuilder();
+      int itemCount = 0;
+      for (ClientStatus clientStatus : clientStatuses.values()) {
+        if (clientStatus.hasRequestedCurrentTest 
+            && clientStatus.currentTestResults == null) {
+          if (itemCount > 0) {
+            buf.append(", ");
+          }
+          buf.append(clientStatus.clientId);
+          ++itemCount;
+        }
+      }
+      int difference = numClients - itemCount;
+      if (difference > 0) {
+        if (itemCount > 0) {
+          buf.append('\n');
+        }
+        buf.append(difference + 
+            " other client(s) haven't responded back to JUnitShell since the start of the test.");
+      }
+      return buf.toString();
+    }
+  }
+
+  /**
    * Called by the servlet to report the results of the last test to run.
    * 
    * @param testInfo the testInfo the result is for
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index 45eecf2..396df3d 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -563,7 +563,7 @@
       lastModule = currentModule;
       if (testMethodTimeout == 0) {
         testMethodTimeout = currentTimeMillis + TEST_METHOD_TIMEOUT_MILLIS;
-      } else if (testMethodTimeout < currentTimeMillis){
+      } else if (testMethodTimeout < currentTimeMillis) {
         double elapsed = (currentTimeMillis - testBeginTime) / 1000.0;
         throw new TimeoutException(
             "The browser did not complete the test method " 
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index f40bcf0..3010bef 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -19,6 +19,7 @@
 <!--                                                                        -->
 <module>
    <inherits name="com.google.gwt.core.Core"/>
+   <inherits name="com.google.gwt.event.Event"/>
    <inherits name="com.google.gwt.animation.Animation"/>
    <inherits name="com.google.gwt.user.RemoteService"/>
    <inherits name="com.google.gwt.user.DocumentRoot" />
diff --git a/user/src/com/google/gwt/user/client/CommandExecutor.java b/user/src/com/google/gwt/user/client/CommandExecutor.java
index 5b2a57f..f2181a0 100644
--- a/user/src/com/google/gwt/user/client/CommandExecutor.java
+++ b/user/src/com/google/gwt/user/client/CommandExecutor.java
@@ -41,7 +41,7 @@
  * TODO(mmendez): Can an SSW be detected without using a timer? Currently, if a
  * {@link Command} or an {@link IncrementalCommand} calls either
  * {@link Window#alert(String)} or the JavaScript <code>alert(String)</code>
- * methods directly or indirectly then the {@link #cancellationTimer} can fire,
+ * methods directly or indirectly then the  cancellation timer can fire,
  * resulting in a false SSW cancellation detection.
  */
 class CommandExecutor {
@@ -95,7 +95,6 @@
     /**
      * Removes the command which was previously returned by {@link #next()}.
      * 
-     * @return the command which was previously returned by {@link #next()}.
      */
     public void remove() {
       assert (last >= 0);
diff --git a/user/src/com/google/gwt/user/client/History.java b/user/src/com/google/gwt/user/client/History.java
index d3e0612..bbac932 100644
--- a/user/src/com/google/gwt/user/client/History.java
+++ b/user/src/com/google/gwt/user/client/History.java
@@ -16,6 +16,8 @@
 package com.google.gwt.user.client;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.impl.HistoryImpl;
 
 /**
@@ -27,9 +29,8 @@
  * 
  * <p>
  * In order to receive notification of user-directed changes to the current
- * history item, implement the
- * {@link com.google.gwt.user.client.HistoryListener} interface and attach it
- * via {@link #addHistoryListener}.
+ * history item, implement the {@link ValueChangeHandler} interface and attach
+ * it via {@link #addValueChangeHandler(ValueChangeHandler)}.
  * </p>
  * 
  * <p>
@@ -40,8 +41,9 @@
  * <p>
  * <h3>URL Encoding</h3>
  * Any valid characters may be used in the history token and will survive
- * round-trips through {@link #newItem(String)} to {@link #getToken()}/{@link HistoryListener#onHistoryChanged(String)},
- * but most will be encoded in the user-visible URL. The following US-ASCII
+ * round-trips through {@link #newItem(String)} to {@link #getToken()}/
+ * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+ * , but most will be encoded in the user-visible URL. The following US-ASCII
  * characters are not encoded on any currently supported browser (but may be in
  * the future due to future browser changes):
  * <ul>
@@ -76,8 +78,20 @@
    * 
    * @param listener the listener to be added
    */
+  @Deprecated
   public static void addHistoryListener(HistoryListener listener) {
-    HistoryImpl.addHistoryListener(listener);
+    ListenerWrapper.HistoryChange.add(listener);
+  }
+
+  /**
+   * Adds a {@link com.google.gwt.event.logical.shared.ValueChangeEvent} handler
+   * to be informed of changes to the browser's history stack.
+   * 
+   * @param handler the handler
+   */
+  public static HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<String> handler) {
+    return impl.addValueChangeHandler(handler);
   }
 
   /**
@@ -90,13 +104,16 @@
   }-*/;
 
   /**
-   * Fire {@link HistoryListener#onHistoryChanged(String)} events with the
-   * current history state. This is most often called at the end of an
-   * application's {@link com.google.gwt.core.client.EntryPoint#onModuleLoad()}
-   * to inform history listeners of the initial application state.
+   * Fire
+   * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+   * events with the current history state. This is most often called at the end
+   * of an application's
+   * {@link com.google.gwt.core.client.EntryPoint#onModuleLoad()} to inform
+   * history handlers of the initial application state.
    */
   public static void fireCurrentHistoryState() {
-    HistoryImpl.fireHistoryChangedImpl(getToken());
+    String token = getToken();
+    impl.fireHistoryChangedImpl(token);
   }
 
   /**
@@ -108,11 +125,11 @@
   }-*/;
 
   /**
-   * Gets the current history token. The listener will not receive a
-   * {@link HistoryListener#onHistoryChanged(String)} event for the initial
-   * token; requiring that an application request the token explicitly on
-   * startup gives it an opportunity to run different initialization code in the
-   * presence or absence of an initial token.
+   * Gets the current history token. The handler will not receive a
+   * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+   * event for the initial token; requiring that an application request the
+   * token explicitly on startup gives it an opportunity to run different
+   * initialization code in the presence or absence of an initial token.
    * 
    * @return the initial token, or the empty string if none is present.
    */
@@ -124,7 +141,8 @@
    * Adds a new browser history entry. In hosted mode, the 'back' and 'forward'
    * actions are accessible via the standard Alt-Left and Alt-Right keystrokes.
    * Calling this method will cause
-   * {@link HistoryListener#onHistoryChanged(String)} to be called as well.
+   * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+   * to be called as well.
    * 
    * @param historyToken the token to associate with the new history item
    */
@@ -136,13 +154,13 @@
    * Adds a new browser history entry. In hosted mode, the 'back' and 'forward'
    * actions are accessible via the standard Alt-Left and Alt-Right keystrokes.
    * Calling this method will cause
-   * {@link HistoryListener#onHistoryChanged(String)} to be called as well if
-   * and only if issueEvent is true.
+   * {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+   * to be called as well if and only if issueEvent is true.
    * 
    * @param historyToken the token to associate with the new history item
    * @param issueEvent true if a
-   *          {@link HistoryListener#onHistoryChanged(String)} event should be
-   *          issued
+   *          {@link ValueChangeHandler#onValueChange(com.google.gwt.event.logical.shared.ValueChangeEvent)}
+   *          event should be issued
    */
   public static void newItem(String historyToken, boolean issueEvent) {
     if (impl != null) {
@@ -151,10 +169,10 @@
   }
 
   /**
-   * Call all history listeners with the specified token. Note that this does
-   * not change the history system's idea of the current state and is only kept
-   * for backward compatibility. To fire history events for the initial state of
-   * the application, instead call {@link #fireCurrentHistoryState()} from the
+   * Call all history handlers with the specified token. Note that this does not
+   * change the history system's idea of the current state and is only kept for
+   * backward compatibility. To fire history events for the initial state of the
+   * application, instead call {@link #fireCurrentHistoryState()} from the
    * application {@link com.google.gwt.core.client.EntryPoint#onModuleLoad()}
    * method.
    * 
@@ -163,7 +181,7 @@
    */
   @Deprecated
   public static void onHistoryChanged(String historyToken) {
-    HistoryImpl.fireHistoryChangedImpl(historyToken);
+    impl.fireHistoryChangedImpl(historyToken);
   }
 
   /**
@@ -171,7 +189,8 @@
    * 
    * @param listener the listener to be removed
    */
+  @Deprecated
   public static void removeHistoryListener(HistoryListener listener) {
-    HistoryImpl.removeHistoryListener(listener);
+    ListenerWrapper.HistoryChange.remove(impl.getHandlers(), listener);
   }
 }
diff --git a/user/src/com/google/gwt/user/client/HistoryListener.java b/user/src/com/google/gwt/user/client/HistoryListener.java
index e3a0bab..b4a607f 100644
--- a/user/src/com/google/gwt/user/client/HistoryListener.java
+++ b/user/src/com/google/gwt/user/client/HistoryListener.java
@@ -19,6 +19,7 @@
  * Implement this interface to receive notification of changes to the browser
  * history state. It is used with {@link com.google.gwt.user.client.History}.
  */
+@Deprecated
 public interface HistoryListener extends java.util.EventListener {
 
   /**
@@ -26,5 +27,6 @@
    * 
    * @param historyToken the token representing the current history state
    */
+  @Deprecated
   void onHistoryChanged(String historyToken);
 }
diff --git a/user/src/com/google/gwt/user/client/ListenerWrapper.java b/user/src/com/google/gwt/user/client/ListenerWrapper.java
new file mode 100644
index 0000000..45bf6ac
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ListenerWrapper.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.user.client;
+
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.GwtEvent.Type;
+
+import java.util.EventListener;
+
+/**
+ * Legacy listener support hierarchy for <code>com.google.gwt.user.client</code>.
+ * Gathers the bulk of the legacy glue code in one place, for easy deletion when
+ * Listener methods are deleted. 
+ * 
+ * @see com.google.gwt.user.ListenerWrapper
+ * @param <T> listener type
+ */
+@Deprecated
+abstract class ListenerWrapper<T> implements EventHandler {
+  public static class HistoryChange extends ListenerWrapper<HistoryListener> implements
+      ValueChangeHandler<String> {
+    @Deprecated
+    public static void add(HistoryListener listener) {
+      History.addValueChangeHandler(new HistoryChange(listener));
+    }
+
+    public static void remove(HandlerManager manager, HistoryListener listener) {
+      baseRemove(manager, listener, ValueChangeEvent.getType());
+    }
+
+    private HistoryChange(HistoryListener listener) {
+      super(listener);
+    }
+
+    public void onValueChange(ValueChangeEvent<String> event) {
+      listener.onHistoryChanged(event.getValue());
+    }
+  }
+
+  public static class WindowClose extends ListenerWrapper<WindowCloseListener> implements
+      Window.ClosingHandler, CloseHandler<Window> {
+    @Deprecated
+    public static void add(WindowCloseListener listener) {
+      WindowClose handler = new WindowClose(listener);
+      Window.addWindowClosingHandler(handler);
+      Window.addCloseHandler(handler);
+    }
+
+    public static void remove(HandlerManager manager,
+        WindowCloseListener listener) {
+      baseRemove(manager, listener, Window.ClosingEvent.getType(),
+          CloseEvent.getType());
+    }
+
+    private WindowClose(WindowCloseListener listener) {
+      super(listener);
+    }
+
+    public void onClose(CloseEvent<Window> event) {
+      listener.onWindowClosed();
+    }
+
+    public void onWindowClosing(Window.ClosingEvent event) {
+      String message = listener.onWindowClosing();
+      if (event.getMessage() == null) {
+        event.setMessage(message);
+      }
+    }
+  }
+
+  public static class WindowResize extends ListenerWrapper<WindowResizeListener> implements
+      ResizeHandler {
+    @Deprecated
+    public static void add(WindowResizeListener listener) {
+      Window.addResizeHandler(new WindowResize(listener));
+    }
+
+    public static void remove(HandlerManager manager,
+        WindowResizeListener listener) {
+      baseRemove(manager, listener, ResizeEvent.getType());
+    }
+
+    private WindowResize(WindowResizeListener listener) {
+      super(listener);
+    }
+
+    public void onResize(ResizeEvent event) {
+      listener.onWindowResized(event.getWidth(), event.getHeight());
+    }
+  }
+
+  public static class WindowScroll extends ListenerWrapper<WindowScrollListener> implements
+      Window.ScrollHandler {
+    @Deprecated
+    public static void add(WindowScrollListener listener) {
+      Window.addWindowScrollHandler(new WindowScroll(listener));
+    }
+
+    public static void remove(HandlerManager manager,
+        WindowScrollListener listener) {
+      baseRemove(manager, listener, Window.ScrollEvent.getType());
+    }
+
+    private WindowScroll(WindowScrollListener listener) {
+      super(listener);
+    }
+
+    public void onWindowScroll(Window.ScrollEvent event) {
+      listener.onWindowScrolled(event.getScrollLeft(), event.getScrollTop());
+    }
+  }
+
+  // This is an internal helper method with the current formulation, we have
+  // lost the info needed to make it safe by this point.
+  @SuppressWarnings("unchecked")
+  protected static void baseRemove(HandlerManager manager,
+      EventListener listener, Type... keys) {
+    if (manager != null) {
+      for (Type key : keys) {
+        int handlerCount = manager.getHandlerCount(key);
+        for (int i = 0; i < handlerCount; i++) {
+          EventHandler handler = manager.getHandler(key, i);
+          if (handler instanceof ListenerWrapper && ((ListenerWrapper) handler).listener.equals(listener)) {
+            manager.removeHandler(key, handler);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Listener being wrapped.
+   */
+  protected final T listener;
+
+  protected ListenerWrapper(T listener) {
+    this.listener = listener;
+  }
+}
diff --git a/user/src/com/google/gwt/user/client/Timer.java b/user/src/com/google/gwt/user/client/Timer.java
index 443520f..4cbceed 100644
--- a/user/src/com/google/gwt/user/client/Timer.java
+++ b/user/src/com/google/gwt/user/client/Timer.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
+import com.google.gwt.user.client.Window.ClosingEvent;
 
 import java.util.ArrayList;
 
@@ -63,19 +64,13 @@
 
   private static void hookWindowClosing() {
     // Catch the window closing event.
-    Window.addWindowCloseListener(new WindowCloseListener() {
-      public void onWindowClosed() {
-        // When the window is closing, cancel all extant timers. This ensures
-        // that no leftover timers can cause memory leaks by leaving links from
-        // the window's timeout closures back into Java objects.
+    Window.addWindowClosingHandler(new Window.ClosingHandler() {
+
+      public void onWindowClosing(ClosingEvent event) {
         while (timers.size() > 0) {
           timers.get(0).cancel();
         }
       }
-
-      public String onWindowClosing() {
-        return null;
-      }
     });
   }
 
diff --git a/user/src/com/google/gwt/user/client/Window.java b/user/src/com/google/gwt/user/client/Window.java
index 7667fd9..50b2fc4 100644
--- a/user/src/com/google/gwt/user/client/Window.java
+++ b/user/src/com/google/gwt/user/client/Window.java
@@ -17,6 +17,17 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.HasCloseHandlers;
+import com.google.gwt.event.logical.shared.HasHandlers;
+import com.google.gwt.event.logical.shared.HasResizeHandlers;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.http.client.URL;
 import com.google.gwt.user.client.impl.WindowImpl;
 
@@ -33,6 +44,73 @@
 public class Window {
 
   /**
+   * Fired just before the browser window closes or navigates to a different
+   * site.
+   */
+  public static class ClosingEvent extends GwtEvent<Window.ClosingHandler> {
+    /**
+     * The event type.
+     */
+    private static final Type<ClosingHandler> TYPE = new Type<ClosingHandler>();
+
+    static Type<ClosingHandler> getType() {
+      return TYPE;
+    }
+
+    /**
+     * The message to display to the user to see whether they really want to
+     * leave the page.
+     */
+    private String message = null;
+
+    /**
+     * Get the message that will be presented to the user in a confirmation
+     * dialog that asks the user whether or not she wishes to navigate away from
+     * the page.
+     * 
+     * @return the message to display to the user, or null
+     */
+    public String getMessage() {
+      return message;
+    }
+
+    /**
+     * Set the message to a <code>non-null</code> value to present a
+     * confirmation dialog that asks the user whether or not she wishes to
+     * navigate away from the page. If multiple handlers set the message, the
+     * last message will be displayed; all others will be ignored.
+     * 
+     * @param message the message to display to the user, or null
+     */
+    public void setMessage(String message) {
+      this.message = message;
+    }
+
+    @Override
+    protected void dispatch(ClosingHandler handler) {
+      handler.onWindowClosing(this);
+    }
+
+    @Override
+    protected Type<ClosingHandler> getAssociatedType() {
+      return TYPE;
+    }
+  }
+
+  /**
+   * Handler for {@link Window.ClosingEvent} events.
+   */
+  public interface ClosingHandler extends EventHandler {
+    /**
+     * Fired just before the browser window closes or navigates to a different
+     * site. No user-interface may be displayed during shutdown.
+     * 
+     * @param event the event
+     */
+    void onWindowClosing(Window.ClosingEvent event);
+  }
+
+  /**
    * This class provides access to the browser's location's object. The location
    * object contains information about the current URL and methods to manipulate
    * it. <code>Location</code> is a very simple wrapper, so not all browser
@@ -90,8 +168,8 @@
 
     /**
      * Gets the URL's parameter of the specified name. Note that if multiple
-     * parameters have been specified with the same name, the last one will
-     * be returned.
+     * parameters have been specified with the same name, the last one will be
+     * returned.
      * 
      * @param name the name of the URL's parameter
      * @return the value of the URL's parameter
@@ -169,12 +247,13 @@
     }-*/;
 
     /**
-     * Builds the immutable map from String to List<String> that we'll return
-     * in getParameterMap(). Package-protected for testing.
-     * @return a map from the 
+     * Builds the immutable map from String to List<String> that we'll return in
+     * getParameterMap(). Package-protected for testing.
+     * 
+     * @return a map from the
      */
-    static Map<String,List<String>> buildListParamMap(String queryString) {
-      Map<String,List<String>> out = new HashMap<String, List<String>>();
+    static Map<String, List<String>> buildListParamMap(String queryString) {
+      Map<String, List<String>> out = new HashMap<String, List<String>>();
 
       if (queryString != null && queryString.length() > 1) {
         String qs = queryString.substring(1);
@@ -202,7 +281,7 @@
 
       return out;
     }
-    
+
     private static void ensureParameterMap() {
       if (paramMap == null) {
         paramMap = new HashMap<String, String>();
@@ -225,24 +304,144 @@
     }
   }
 
-  private static boolean handlersAreInitialized;
+  /**
+   * Fired when the browser window is scrolled.
+   */
+  public static class ScrollEvent extends GwtEvent<Window.ScrollHandler> {
+    /**
+     * The event type.
+     */
+    static final Type<Window.ScrollHandler> TYPE = new Type<Window.ScrollHandler>();
+
+    static Type<Window.ScrollHandler> getType() {
+      return TYPE;
+    }
+
+    private int scrollLeft;
+    private int scrollTop;
+
+    /**
+     * Construct a new {@link Window.ScrollEvent}.
+     * 
+     * @param scrollLeft the left scroll position
+     * @param scrollTop the top scroll position
+     */
+    private ScrollEvent(int scrollLeft, int scrollTop) {
+      this.scrollLeft = scrollLeft;
+      this.scrollTop = scrollTop;
+    }
+
+    /**
+     * Gets the window's scroll left.
+     * 
+     * @return window's scroll left
+     */
+    public int getScrollLeft() {
+      return scrollLeft;
+    }
+
+    /**
+     * Get the window's scroll top.
+     * 
+     * @return the window's scroll top
+     */
+    public int getScrollTop() {
+      return scrollTop;
+    }
+
+    @Override
+    protected void dispatch(ScrollHandler handler) {
+      handler.onWindowScroll(this);
+    }
+
+    @Override
+    protected Type<ScrollHandler> getAssociatedType() {
+      return TYPE;
+    }
+  }
+
+  /**
+   * Handler for {@link Window.ScrollEvent} events.
+   */
+  public interface ScrollHandler extends EventHandler {
+    /**
+     * Fired when the browser window is scrolled.
+     * 
+     * @param event the event
+     */
+    void onWindowScroll(Window.ScrollEvent event);
+  }
+
+  private static class WindowHandlers extends HandlerManager implements
+      HasCloseHandlers<Window>, HasResizeHandlers, HasHandlers {
+
+    public WindowHandlers() {
+      super(null);
+    }
+
+    public HandlerRegistration addCloseHandler(CloseHandler<Window> handler) {
+      return addHandler(CloseEvent.getType(), handler);
+    }
+
+    public HandlerRegistration addResizeHandler(ResizeHandler handler) {
+      return addHandler(ResizeEvent.getType(), handler);
+    }
+
+    public HandlerManager getHandlers() {
+      return this;
+    }
+  }
+
+  private static boolean closeHandlersInitialized;
+  private static boolean scrollHandlersInitialized;
+  private static boolean resizeHandlersInitialized;
   private static final WindowImpl impl = GWT.create(WindowImpl.class);
 
-  private static ArrayList<WindowCloseListener> closingListeners;
-  private static ArrayList<WindowResizeListener> resizeListeners;
-  private static ArrayList<WindowScrollListener> scrollListeners;
+  private static WindowHandlers handlers;
+
+  /**
+   * Adds a {@link CloseEvent} handler.
+   * 
+   * @param handler the handler
+   * @return returns the handler registration
+   */
+  public static HandlerRegistration addCloseHandler(CloseHandler<Window> handler) {
+    maybeInitializeCloseHandlers();
+    return addHandler(CloseEvent.getType(), handler);
+  }
+
+  /**
+   * Adds a {@link ResizeEvent} handler.
+   * 
+   * @param handler the handler
+   * @return returns the handler registration
+   */
+  public static HandlerRegistration addResizeHandler(ResizeHandler handler) {
+    maybeInitializeCloseHandlers();
+    maybeInitializeResizeHandlers();
+    return addHandler(ResizeEvent.getType(), handler);
+  }
 
   /**
    * Adds a listener to receive window closing events.
    * 
    * @param listener the listener to be informed when the window is closing
    */
+  @Deprecated
   public static void addWindowCloseListener(WindowCloseListener listener) {
+    ListenerWrapper.WindowClose.add(listener);
+  }
+
+  /**
+   * Adds a {@link Window.ClosingEvent} handler.
+   * 
+   * @param handler the handler
+   * @return returns the handler registration
+   */
+  public static HandlerRegistration addWindowClosingHandler(
+      ClosingHandler handler) {
     maybeInitializeCloseHandlers();
-    if (closingListeners == null) {
-      closingListeners = new ArrayList<WindowCloseListener>();
-    }
-    closingListeners.add(listener);
+    return addHandler(Window.ClosingEvent.getType(), handler);
   }
 
   /**
@@ -250,13 +449,22 @@
    * 
    * @param listener the listener to be informed when the window is resized
    */
+  @Deprecated
   public static void addWindowResizeListener(WindowResizeListener listener) {
-    if (resizeListeners == null) {
-      resizeListeners = new ArrayList<WindowResizeListener>();
-      maybeInitializeCloseHandlers();
-      impl.initWindowResizeHandler();
-    }
-    resizeListeners.add(listener);
+    ListenerWrapper.WindowResize.add(listener);
+  }
+
+  /**
+   * Adds a {@link Window.ScrollEvent} handler.
+   * 
+   * @param handler the handler
+   * @return returns the handler registration
+   */
+  public static HandlerRegistration addWindowScrollHandler(
+      Window.ScrollHandler handler) {
+    maybeInitializeCloseHandlers();
+    maybeInitializeScrollHandlers();
+    return addHandler(Window.ScrollEvent.getType(), handler);
   }
 
   /**
@@ -264,13 +472,9 @@
    * 
    * @param listener the listener to be informed when the window is scrolled
    */
+  @Deprecated
   public static void addWindowScrollListener(WindowScrollListener listener) {
-    if (scrollListeners == null) {
-      scrollListeners = new ArrayList<WindowScrollListener>();
-      maybeInitializeCloseHandlers();
-      impl.initWindowScrollHandler();
-    }
-    scrollListeners.add(listener);
+    ListenerWrapper.WindowScroll.add(listener);
   }
 
   /**
@@ -391,10 +595,9 @@
    * 
    * @param listener the listener to be removed
    */
+  @Deprecated
   public static void removeWindowCloseListener(WindowCloseListener listener) {
-    if (closingListeners != null) {
-      closingListeners.remove(listener);
-    }
+    ListenerWrapper.WindowClose.remove(handlers, listener);
   }
 
   /**
@@ -402,10 +605,9 @@
    * 
    * @param listener the listener to be removed
    */
+  @Deprecated
   public static void removeWindowResizeListener(WindowResizeListener listener) {
-    if (resizeListeners != null) {
-      resizeListeners.remove(listener);
-    }
+    ListenerWrapper.WindowResize.remove(handlers, listener);
   }
 
   /**
@@ -413,10 +615,9 @@
    * 
    * @param listener the listener to be removed
    */
+  @Deprecated
   public static void removeWindowScrollListener(WindowScrollListener listener) {
-    if (scrollListeners != null) {
-      scrollListeners.remove(listener);
-    }
+    ListenerWrapper.WindowScroll.remove(handlers, listener);
   }
 
   /**
@@ -496,6 +697,19 @@
     }
   }
 
+  /**
+   * Adds this handler to the Window.
+   * 
+   * @param <H> the type of handler to add
+   * @param type the event type
+   * @param handler the handler
+   * @return {@link HandlerRegistration} used to remove the handler
+   */
+  private static <H extends EventHandler> HandlerRegistration addHandler(
+      GwtEvent.Type<H> type, final H handler) {
+    return getHandlers().addHandler(type, handler);
+  }
+
   private static void fireClosedAndCatch(UncaughtExceptionHandler handler) {
     try {
       fireClosedImpl();
@@ -505,10 +719,8 @@
   }
 
   private static void fireClosedImpl() {
-    if (closingListeners != null) {
-      for (WindowCloseListener listener : closingListeners) {
-        listener.onWindowClosed();
-      }
+    if (closeHandlersInitialized) {
+      CloseEvent.fire(getHandlers(), null);
     }
   }
 
@@ -522,19 +734,23 @@
   }
 
   private static String fireClosingImpl() {
-    String ret = null;
-    if (closingListeners != null) {
-      for (WindowCloseListener listener : closingListeners) {
-        // If any listener wants to suppress the window closing event, then do
-        // so.
-        String msg = listener.onWindowClosing();
-        if (ret == null) {
-          ret = msg;
-        }
-      }
+    if (closeHandlersInitialized) {
+      Window.ClosingEvent event = new Window.ClosingEvent();
+      fireEvent(event);
+      return event.getMessage();
     }
+    return null;
+  }
 
-    return ret;
+  /**
+   * Fires an event.
+   * 
+   * @param event the event
+   */
+  private static void fireEvent(GwtEvent<?> event) {
+    if (handlers != null) {
+      handlers.fireEvent(event);
+    }
   }
 
   private static void fireResizedAndCatch(UncaughtExceptionHandler handler) {
@@ -546,10 +762,8 @@
   }
 
   private static void fireResizedImpl() {
-    if (resizeListeners != null) {
-      for (WindowResizeListener listener : resizeListeners) {
-        listener.onWindowResized(getClientWidth(), getClientHeight());
-      }
+    if (resizeHandlersInitialized) {
+      ResizeEvent.fire(getHandlers(), getClientWidth(), getClientHeight());
     }
   }
 
@@ -562,17 +776,36 @@
   }
 
   private static void fireScrollImpl() {
-    if (scrollListeners != null) {
-      for (WindowScrollListener listener : scrollListeners) {
-        listener.onWindowScrolled(getScrollLeft(), getScrollTop());
-      }
+    if (scrollHandlersInitialized) {
+      fireEvent(new Window.ScrollEvent(getScrollLeft(), getScrollTop()));
     }
   }
 
+  private static WindowHandlers getHandlers() {
+    if (handlers == null) {
+      handlers = new WindowHandlers();
+    }
+    return handlers;
+  }
+
   private static void maybeInitializeCloseHandlers() {
-    if (GWT.isClient() && !handlersAreInitialized) {
-      handlersAreInitialized = true;
+    if (GWT.isClient() && !closeHandlersInitialized) {
       impl.initWindowCloseHandler();
+      closeHandlersInitialized = true;
+    }
+  }
+
+  private static void maybeInitializeResizeHandlers() {
+    if (GWT.isClient() && !resizeHandlersInitialized) {
+      impl.initWindowResizeHandler();
+      resizeHandlersInitialized = true;
+    }
+  }
+
+  private static void maybeInitializeScrollHandlers() {
+    if (GWT.isClient() && !scrollHandlersInitialized) {
+      impl.initWindowScrollHandler();
+      scrollHandlersInitialized = true;
     }
   }
 
diff --git a/user/src/com/google/gwt/user/client/WindowCloseListener.java b/user/src/com/google/gwt/user/client/WindowCloseListener.java
index bb1d1c7..aa5806c 100644
--- a/user/src/com/google/gwt/user/client/WindowCloseListener.java
+++ b/user/src/com/google/gwt/user/client/WindowCloseListener.java
@@ -20,6 +20,7 @@
  * 
  * @see com.google.gwt.user.client.Window#addWindowCloseListener(WindowCloseListener)
  */
+@Deprecated
 public interface WindowCloseListener extends java.util.EventListener {
 
   /**
@@ -32,6 +33,7 @@
    *         dialog box. If multiple listeners return messages, the first will
    *         be displayed; all others will be ignored.
    */
+  @Deprecated
   String onWindowClosing();
 
   /**
@@ -39,5 +41,6 @@
    * This event cannot be cancelled, and is used mainly to clean up application
    * state and/or save state to the server.
    */
+  @Deprecated
   void onWindowClosed();
 }
diff --git a/user/src/com/google/gwt/user/client/WindowResizeListener.java b/user/src/com/google/gwt/user/client/WindowResizeListener.java
index 40be41c..04cfd25 100644
--- a/user/src/com/google/gwt/user/client/WindowResizeListener.java
+++ b/user/src/com/google/gwt/user/client/WindowResizeListener.java
@@ -20,6 +20,7 @@
  * 
  * @see com.google.gwt.user.client.Window#addWindowResizeListener(WindowResizeListener)
  */
+@Deprecated
 public interface WindowResizeListener extends java.util.EventListener {
 
   /**
@@ -28,5 +29,6 @@
    * @param width the width of the window's client area.
    * @param height the height of the window's client area.
    */
+  @Deprecated
   void onWindowResized(int width, int height);
 }
diff --git a/user/src/com/google/gwt/user/client/WindowScrollListener.java b/user/src/com/google/gwt/user/client/WindowScrollListener.java
index ce4ded4..bf3f3a1 100644
--- a/user/src/com/google/gwt/user/client/WindowScrollListener.java
+++ b/user/src/com/google/gwt/user/client/WindowScrollListener.java
@@ -20,6 +20,7 @@
  * 
  * @see com.google.gwt.user.client.Window#addWindowScrollListener(WindowScrollListener)
  */
+@Deprecated
 public interface WindowScrollListener extends java.util.EventListener {
 
   /**
@@ -28,5 +29,6 @@
    * @param scrollLeft the left scroll position
    * @param scrollTop the top scroll position
    */
+  @Deprecated
   void onWindowScrolled(int scrollLeft, int scrollTop);
 }
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java b/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
index ba0cf6c..5d2be3c 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
@@ -172,7 +172,7 @@
             evt.stopPropagation();
           }
         }
-      }
+      }  
     };
 
     @com.google.gwt.user.client.impl.DOMImplStandard::dispatchCapturedEvent = function(evt) {
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
index a1a1147..d5c8800 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
@@ -17,9 +17,12 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
-import com.google.gwt.user.client.HistoryListener;
-
-import java.util.ArrayList;
+import com.google.gwt.event.logical.shared.HasHandlers;
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
 
 /**
  * Native implementation associated with
@@ -27,69 +30,39 @@
  * 
  * User classes should not use this class directly.
  */
-public abstract class HistoryImpl {
-
-  private static ArrayList<HistoryListener> historyListeners = new ArrayList<HistoryListener>();
-
-  /**
-   * Adds a listener to be informed of changes to the browser's history stack.
-   * 
-   * @param listener the listener to be added
-   */
-  public static void addHistoryListener(HistoryListener listener) {
-    historyListeners.add(listener);
-  }
-
-  /**
-   * Fires the {@link HistoryListener#onHistoryChanged(String)} event to all
-   * listeners with the given token.
-   */
-  public static void fireHistoryChangedImpl(String historyToken) {
-    // TODO: replace this copy when a more general solution to event handlers
-    // wanting to remove themselves from the listener list is implemented.
-
-    // This is necessary to avoid a CurrentModificationException in hosted
-    // mode, as the listeners may try to remove themselves from the list while
-    // it is being iterated, such as in HistoryTest.
-    HistoryListener[] listenersToInvoke = historyListeners.toArray(new HistoryListener[historyListeners.size()]);
-    for (HistoryListener listener : listenersToInvoke) {
-      listener.onHistoryChanged(historyToken);
-    }
-  }
+public abstract class HistoryImpl implements HasValueChangeHandlers<String>,
+    HasHandlers {
 
   public static native String getToken() /*-{
     return $wnd.__gwt_historyToken || "";
   }-*/;
 
-  /**
-   * Removes a history listener.
-   * 
-   * @param listener the listener to be removed
-   */
-  public static void removeHistoryListener(HistoryListener listener) {
-    historyListeners.remove(listener);
-  }
-
   protected static native void setToken(String token) /*-{
     $wnd.__gwt_historyToken = token;
   }-*/;
 
-  private static void fireHistoryChanged(String historyToken) {
-    UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
-    if (handler != null) {
-      fireHistoryChangedAndCatch(historyToken, handler);
-    } else {
-      fireHistoryChangedImpl(historyToken);
-    }
+  private HandlerManager handlers = new HandlerManager(null);
+
+  /**
+   * Adds a {@link ValueChangeEvent} handler to be informed of changes to the
+   * browser's history stack.
+   * 
+   * @param handler the handler
+   */
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<String> handler) {
+    return handlers.addHandler(ValueChangeEvent.getType(), handler);
   }
 
-  private static void fireHistoryChangedAndCatch(String historyToken,
-      UncaughtExceptionHandler handler) {
-    try {
-      fireHistoryChangedImpl(historyToken);
-    } catch (Throwable e) {
-      handler.onUncaughtException(e);
-    }
+  /**
+   * Fires the {@link ValueChangeEvent} to all handlers with the given tokens.
+   */
+  public void fireHistoryChangedImpl(String newToken) {
+    ValueChangeEvent.fire(this, newToken);
+  }
+
+  public HandlerManager getHandlers() {
+    return handlers;
   }
 
   public abstract boolean init();
@@ -127,4 +100,22 @@
   protected abstract void nativeUpdate(String historyToken);
 
   protected abstract void nativeUpdateOnEvent(String historyToken);
+
+  private void fireHistoryChanged(String newToken) {
+    UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
+    if (handler != null) {
+      fireHistoryChangedAndCatch(newToken, handler);
+    } else {
+      fireHistoryChangedImpl(newToken);
+    }
+  }
+
+  private void fireHistoryChangedAndCatch(String newToken,
+      UncaughtExceptionHandler handler) {
+    try {
+      fireHistoryChangedImpl(newToken);
+    } catch (Throwable e) {
+      handler.onUncaughtException(e);
+    }
+  }
 }
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
index 69624ec..f2e3606 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
@@ -19,8 +19,7 @@
 import com.google.gwt.user.client.Element;
 
 /**
- * Internet Explorer 6 implementation of
- * {@link com.google.gwt.user.client.impl.HistoryImplFrame}.
+ * Internet Explorer 6 implementation HistoryImplFrame.
  */
 class HistoryImplIE6 extends HistoryImplFrame {
 
@@ -89,6 +88,7 @@
     };
   }-*/;
 
+  @Override
   protected native void navigateFrame(String token) /*-{
     var escaped = @com.google.gwt.user.client.impl.HistoryImplIE6::escapeHtml(Ljava/lang/String;)(token);
     var doc = this.@com.google.gwt.user.client.impl.HistoryImplFrame::historyFrame.contentWindow.document;
@@ -97,6 +97,7 @@
     doc.close();
   }-*/;
 
+  @Override
   protected native void updateHash(String token) /*-{
     $wnd.location.hash = this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(token);
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
index 2f72256..6986312 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
@@ -64,6 +64,7 @@
       newNativeUpdate(historyToken);
     }
   }
+  // HasXHandler(Selection.Handler
 
   private native void initImpl() /*-{
     var token = '';
@@ -75,8 +76,7 @@
     }
 
     @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token);
-
-    @com.google.gwt.user.client.impl.HistoryImpl::fireHistoryChangedImpl(Ljava/lang/String;)($wnd.__gwt_historyToken);
+    this.@com.google.gwt.user.client.impl.HistoryImpl::fireHistoryChangedImpl(Ljava/lang/String;)($wnd.__gwt_historyToken);
   }-*/;
 
   private native void newNativeUpdate(String historyToken) /*-{
diff --git a/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java b/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
index 97dbd2e..188dc6a 100644
--- a/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
+++ b/user/src/com/google/gwt/user/client/ui/AbsolutePanel.java
@@ -64,7 +64,7 @@
    * it can be used by {@link RootPanel} or a subclass that wants to substitute
    * another element. The element is presumed to be a &lt;div&gt;.
    * 
-   * @param elem the element to be used for this panel.
+   * @param elem the element to be used for this panel
    */
   protected AbsolutePanel(Element elem) {
     setElement(elem);
diff --git a/user/src/com/google/gwt/user/client/ui/Anchor.java b/user/src/com/google/gwt/user/client/ui/Anchor.java
index 8910305..dc2ec2b 100644
--- a/user/src/com/google/gwt/user/client/ui/Anchor.java
+++ b/user/src/com/google/gwt/user/client/ui/Anchor.java
@@ -183,6 +183,7 @@
     return getAnchorElement().getName();
   }
 
+  @Override
   public int getTabIndex() {
     return getAnchorElement().getTabIndex();
   }
@@ -205,6 +206,7 @@
     return !getElement().getStyle().getProperty("whiteSpace").equals("nowrap");
   }
 
+  @Override
   public void setAccessKey(char key) {
     getAnchorElement().setAccessKey(Character.toString(key));
   }
@@ -213,6 +215,7 @@
     BidiUtils.setDirectionOnElement(getElement(), direction);
   }
 
+  @Override
   public void setFocus(boolean focused) {
     if (focused) {
       getAnchorElement().focus();
@@ -243,6 +246,7 @@
     getAnchorElement().setName(name);
   }
 
+  @Override
   public void setTabIndex(int index) {
     getAnchorElement().setTabIndex(index);
   }
diff --git a/user/src/com/google/gwt/user/client/ui/Button.java b/user/src/com/google/gwt/user/client/ui/Button.java
index bce6eac..c7738c8 100644
--- a/user/src/com/google/gwt/user/client/ui/Button.java
+++ b/user/src/com/google/gwt/user/client/ui/Button.java
@@ -18,6 +18,7 @@
 import com.google.gwt.dom.client.ButtonElement;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickHandler;
 
 /**
  * A standard push-button widget.
@@ -99,19 +100,31 @@
    * @param html the HTML caption
    * @param listener the click listener
    */
+  @Deprecated
   public Button(String html, ClickListener listener) {
     this(html);
     addClickListener(listener);
   }
 
   /**
+   * Creates a button with the given HTML caption and click listener.
+   * 
+   * @param html the HTML caption
+   * @param handler the click handler
+   */
+  public Button(String html, ClickHandler handler) {
+    this(html);
+    addClickHandler(handler);
+  }
+
+  /**
    * This constructor may be used by subclasses to explicitly use an existing
    * element. This element must be a &lt;button&gt; element.
    * 
    * @param element the element to be used
    */
   protected Button(com.google.gwt.dom.client.Element element) {
-    super(element.<Element>cast());
+    super(element.<Element> cast());
     ButtonElement.as(element);
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/ChangeListener.java b/user/src/com/google/gwt/user/client/ui/ChangeListener.java
index d8152f3..29e1bc4 100644
--- a/user/src/com/google/gwt/user/client/ui/ChangeListener.java
+++ b/user/src/com/google/gwt/user/client/ui/ChangeListener.java
@@ -20,13 +20,15 @@
 /**
  * Event listener interface for 'change' events.
  */
+@Deprecated
 public interface ChangeListener extends EventListener {
 
   /**
    * Fired when a widget changes, where 'change' is defined by the widget
    * sending the event.
    * 
-   * @param sender the widget that has changed.
+   * @param sender the widget that has changed
    */
+  @Deprecated
   void onChange(Widget sender);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/ChangeListenerCollection.java b/user/src/com/google/gwt/user/client/ui/ChangeListenerCollection.java
index e9874ef..12ce182 100644
--- a/user/src/com/google/gwt/user/client/ui/ChangeListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/ChangeListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.ChangeListener}.
  */
+@Deprecated
 public class ChangeListenerCollection extends ArrayList<ChangeListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/CheckBox.java b/user/src/com/google/gwt/user/client/ui/CheckBox.java
index 5d09e5d..1b1a8f3 100644
--- a/user/src/com/google/gwt/user/client/ui/CheckBox.java
+++ b/user/src/com/google/gwt/user/client/ui/CheckBox.java
@@ -15,6 +15,11 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 
@@ -39,7 +44,7 @@
  * {@example com.google.gwt.examples.CheckBoxExample}
  * </p>
  */
-public class CheckBox extends ButtonBase implements HasName {
+public class CheckBox extends ButtonBase implements HasName, HasValue<Boolean> {
   private Element inputElem, labelElem;
 
   /**
@@ -91,10 +96,26 @@
     // appears in tab sequence. FocusWidget's setElement method already
     // calls setTabIndex, which is overridden below. However, at the time
     // that this call is made, inputElem has not been created. So, we have
-    // to call setTabIndex again, once inputElem has been created. 
+    // to call setTabIndex again, once inputElem has been created.
     setTabIndex(0);
   }
 
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<Boolean> handler) {
+    // Is this the first value change handler? If so, time to listen to clicks
+    // on the checkbox
+    if (!isEventHandled(ValueChangeEvent.getType())) {
+      this.addClickHandler(new ClickHandler() {
+        public void onClick(ClickEvent event) {
+          // No need to compare old value and new value--click handler 
+          // only fires on real click, and value always toggles
+          ValueChangeEvent.fire(CheckBox.this, isChecked());
+        }
+      });
+    }
+    return addHandler(handler, ValueChangeEvent.getType());
+  }
+
   @Override
   public String getHTML() {
     return DOM.getInnerHTML(labelElem);
@@ -114,6 +135,10 @@
     return DOM.getInnerText(labelElem);
   }
 
+  public Boolean getValue() {
+    return isChecked();
+  }
+
   /**
    * Determines whether this check box is currently checked.
    * 
@@ -135,7 +160,8 @@
   }
 
   /**
-   * Checks or unchecks this check box.
+   * Checks or unchecks this check box. Does not fire {@link ValueChangeEvent}.
+   * (If you want the event to fire, use {@link #setValue(boolean, boolean)})
    * 
    * @param checked <code>true</code> to check the check box
    */
@@ -174,10 +200,10 @@
 
   @Override
   public void setTabIndex(int index) {
-    // Need to guard against call to setTabIndex before inputElem is initialized.
-    // This happens because FocusWidget's (a superclass of CheckBox) setElement method
-    // calls setTabIndex before inputElem is initialized. See CheckBox's protected
-    // constructor for more information.
+    // Need to guard against call to setTabIndex before inputElem is
+    // initialized. This happens because FocusWidget's (a superclass of
+    // CheckBox) setElement method calls setTabIndex before inputElem is
+    // initialized. See CheckBox's protected constructor for more information.
     if (inputElem != null) {
       getFocusImpl().setTabIndex(inputElem, index);
     }
@@ -188,11 +214,29 @@
     DOM.setInnerText(labelElem, text);
   }
 
+  public void setValue(Boolean value) {
+    setValue(value, false);
+  }
+
+  public void setValue(Boolean value, boolean fireEvents) {
+    if (isChecked() == value) {
+      return;
+    }
+    setChecked(value);
+    if (fireEvents) {
+      ValueChangeEvent.fire(this, value);
+    }
+  }
+
   // Unlike other widgets the CheckBox sinks on its input element, not its
   // wrapper element.
   @Override
   public void sinkEvents(int eventBitsToAdd) {
-    DOM.sinkEvents(inputElem, eventBitsToAdd | DOM.getEventsSunk(inputElem));
+    if (isOrWasAttached()) {
+      DOM.sinkEvents(inputElem, eventBitsToAdd | DOM.getEventsSunk(inputElem));
+    } else {
+      super.sinkEvents(eventBitsToAdd);
+    }
   }
 
   /**
@@ -253,7 +297,7 @@
     // Clear out the old input element
     DOM.setEventListener(inputElem, null);
     DOM.setEventListener(inputElem, null);
-   
+
     DOM.removeChild(getElement(), inputElem);
     DOM.insertChild(getElement(), elem, 0);
 
diff --git a/user/src/com/google/gwt/user/client/ui/ClickListener.java b/user/src/com/google/gwt/user/client/ui/ClickListener.java
index 269425a..4c34bb6 100644
--- a/user/src/com/google/gwt/user/client/ui/ClickListener.java
+++ b/user/src/com/google/gwt/user/client/ui/ClickListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for click events.
  */
+@Deprecated
 public interface ClickListener extends EventListener {
 
   /**
@@ -27,5 +28,6 @@
    * 
    * @param sender the widget sending the event.
    */
+  @Deprecated
   void onClick(Widget sender);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/ClickListenerCollection.java b/user/src/com/google/gwt/user/client/ui/ClickListenerCollection.java
index 287e317..3f150ff 100644
--- a/user/src/com/google/gwt/user/client/ui/ClickListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/ClickListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.ClickListener}.
  */
+@Deprecated
 public class ClickListenerCollection extends ArrayList<ClickListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/Composite.java b/user/src/com/google/gwt/user/client/ui/Composite.java
index 9b943ae..1bb5a3e 100644
--- a/user/src/com/google/gwt/user/client/ui/Composite.java
+++ b/user/src/com/google/gwt/user/client/ui/Composite.java
@@ -50,7 +50,7 @@
     // Delegate events to the widget.
     widget.onBrowserEvent(event);
   }
-
+ 
   /**
    * Provides subclasses access to the topmost widget that defines this
    * composite.
@@ -91,7 +91,11 @@
 
   @Override
   protected void onAttach() {
-    // Call the widget's onAttach() first.
+    if (!isOrWasAttached()) {
+      widget.sinkEvents(eventsToSink);
+      eventsToSink = -1;
+    }
+
     widget.onAttach();
 
     // Clobber the widget's call to setEventListener(), causing all events to
diff --git a/user/src/com/google/gwt/user/client/ui/CustomButton.java b/user/src/com/google/gwt/user/client/ui/CustomButton.java
index 0ad746d..35b4817 100644
--- a/user/src/com/google/gwt/user/client/ui/CustomButton.java
+++ b/user/src/com/google/gwt/user/client/ui/CustomButton.java
@@ -16,6 +16,8 @@
 
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
@@ -53,42 +55,42 @@
  * 
  * <tr>
  * <td>up</td>
- * <td> {@link #getUpFace()} </td>
+ * <td> {@link #getUpFace()}</td>
  * <td>face shown when button is up</td>
- * <td> none</td>
+ * <td>none</td>
  * </tr>
  * 
  * <tr>
  * <td>down</td>
- * <td> {@link #getDownFace()} </td>
+ * <td> {@link #getDownFace()}</td>
  * <td>face shown when button is down</td>
- * <td> up </td>
+ * <td>up</td>
  * </tr>
  * 
  * <tr>
  * <td>up-hovering</td>
- * <td> {@link #getUpHoveringFace()} </td>
+ * <td> {@link #getUpHoveringFace()}</td>
  * <td>face shown when button is up and hovering</td>
- * <td> up </td>
+ * <td>up</td>
  * </tr>
  * 
  * <tr>
  * <td>up-disabled</td>
- * <td> {@link #getUpDisabledFace()} </td>
+ * <td> {@link #getUpDisabledFace()}</td>
  * <td>face shown when button is up and disabled</td>
- * <td> up</td>
+ * <td>up</td>
  * </tr>
  * 
  * <tr>
  * <td>down-hovering</td>
- * <td> {@link #getDownHoveringFace()} </td>
+ * <td> {@link #getDownHoveringFace()}</td>
  * <td>face shown when button is down and hovering</td>
- * <td> down</td>
+ * <td>down</td>
  * </tr>
  * 
  * <tr>
  * <td>down-disabled</td>
- * <td> {@link #getDownDisabledFace()} </td>
+ * <td> {@link #getDownDisabledFace()}</td>
  * <td>face shown when button is down and disabled</td>
  * <td>down</td>
  * </tr>
@@ -107,8 +109,8 @@
     private Element face;
 
     /**
-     * Constructor for <code>Face</code>. Creates a new face that delegates
-     * to the supplied face.
+     * Constructor for <code>Face</code>. Creates a new face that delegates to
+     * the supplied face.
      * 
      * @param delegateTo default content provider
      */
@@ -185,8 +187,8 @@
     /**
      * Get the name of the face. This property is also used as a modifier on the
      * <code>CustomButton</code> style. <p/> For instance, if the
-     * <code>CustomButton</code> style is "gwt-PushButton" and the face name
-     * is "up", then the CSS class name will be "gwt-PushButton-up".
+     * <code>CustomButton</code> style is "gwt-PushButton" and the face name is
+     * "up", then the CSS class name will be "gwt-PushButton-up".
      * 
      * @return the face's name
      */
@@ -327,6 +329,29 @@
    * Constructor for <code>CustomButton</code>.
    * 
    * @param upImage image for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public CustomButton(Image upImage, ClickHandler handler) {
+    this(upImage);
+    addClickHandler(handler);
+  }
+
+  /**
+   * Constructor for <code>CustomButton</code>.
+   * 
+   * @param upImage image for the default (up) face of the button
+   * @param listener the click listener
+   */
+  @Deprecated
+  public CustomButton(Image upImage, ClickListener listener) {
+    this(upImage);
+    addClickListener(listener);
+  }
+
+  /**
+   * Constructor for <code>CustomButton</code>.
+   * 
+   * @param upImage image for the default (up) face of the button
    * @param downImage image for the down face of the button
    */
   public CustomButton(Image upImage, Image downImage) {
@@ -339,8 +364,21 @@
    * 
    * @param upImage image for the default (up) face of the button
    * @param downImage image for the down face of the button
+   * @param handler clickListener
+   */
+  public CustomButton(Image upImage, Image downImage, ClickHandler handler) {
+    this(upImage, handler);
+    getDownFace().setImage(downImage);
+  }
+
+  /**
+   * Constructor for <code>CustomButton</code>.
+   * 
+   * @param upImage image for the default (up) face of the button
+   * @param downImage image for the down face of the button
    * @param listener clickListener
    */
+  @Deprecated
   public CustomButton(Image upImage, Image downImage, ClickListener listener) {
     this(upImage, listener);
     getDownFace().setImage(downImage);
@@ -349,18 +387,7 @@
   /**
    * Constructor for <code>CustomButton</code>.
    * 
-   * @param upImage image for the default (up) face of the button
-   * @param listener the click listener
-   */
-  public CustomButton(Image upImage, ClickListener listener) {
-    this(upImage);
-    addClickListener(listener);
-  }
-
-  /**
-   * Constructor for <code>CustomButton</code>.
-   * 
-   * @param upText the text for the default (up) face of the button.
+   * @param upText the text for the default (up) face of the button
    */
   public CustomButton(String upText) {
     this();
@@ -371,8 +398,20 @@
    * Constructor for <code>CustomButton</code>.
    * 
    * @param upText the text for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public CustomButton(String upText, ClickHandler handler) {
+    this(upText);
+    addClickHandler(handler);
+  }
+
+  /**
+   * Constructor for <code>CustomButton</code>.
+   * 
+   * @param upText the text for the default (up) face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public CustomButton(String upText, ClickListener listener) {
     this(upText);
     addClickListener(listener);
@@ -394,8 +433,21 @@
    * 
    * @param upText the text for the default (up) face of the button
    * @param downText the text for the down face of the button
+   * @param handler the click handler
+   */
+  public CustomButton(String upText, String downText, ClickHandler handler) {
+    this(upText, downText);
+    addClickHandler(handler);
+  }
+
+  /**
+   * Constructor for <code>CustomButton</code>.
+   * 
+   * @param upText the text for the default (up) face of the button
+   * @param downText the text for the down face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public CustomButton(String upText, String downText, ClickListener listener) {
     this(upText, downText);
     addClickListener(listener);
@@ -408,7 +460,8 @@
     // Use FocusPanel.impl rather than FocusWidget because only FocusPanel.impl
     // works across browsers to create a focusable element.
     super(FocusPanel.impl.createFocusable());
-    sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS | Event.KEYEVENTS);
+    sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.FOCUSEVENTS
+        | Event.KEYEVENTS);
     setUpFace(createFace(null, "up", UP));
     setStyleName(STYLENAME_DEFAULT);
 
@@ -549,8 +602,8 @@
         break;
       case Event.ONMOUSEOUT:
         Element to = DOM.eventGetToElement(event);
-        if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event)) &&
-            (to == null || !DOM.isOrHasChild(getElement(), to))) {
+        if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))
+            && (to == null || !DOM.isOrHasChild(getElement(), to))) {
           if (isCapturing) {
             onClickCancel();
           }
@@ -619,7 +672,7 @@
    * Sets whether this button is enabled.
    * 
    * @param enabled <code>true</code> to enable the button, <code>false</code>
-   *          to disable it
+   * to disable it
    */
   @Override
   public final void setEnabled(boolean enabled) {
@@ -692,7 +745,7 @@
    * widget display.
    */
   protected void onClick() {
-    fireClickListeners();
+    fireClickListeners(null);
   }
 
   /**
@@ -710,8 +763,8 @@
    * subclasses should also override {@link #onClick()} and
    * {@link #onClickCancel()} to restore normal visual state. Each
    * <code>onClickStart</code> will eventually be followed by either
-   * <code>onClick</code> or <code>onClickCancel</code>, depending on
-   * whether the click is completed.
+   * <code>onClick</code> or <code>onClickCancel</code>, depending on whether
+   * the click is completed.
    */
   protected void onClickStart() {
   }
@@ -726,7 +779,7 @@
    * Sets whether this button is down.
    * 
    * @param down <code>true</code> to press the button, <code>false</code>
-   *          otherwise
+   * otherwise
    */
   protected void setDown(boolean down) {
     if (down != isDown()) {
@@ -743,6 +796,12 @@
     }
   }
 
+  void fireClickListeners(Event nativeEvent) {
+    // TODO(ecc) Once event triggering is committed, should fire a native click event instead.
+    fireEvent(new ClickEvent() {
+    });
+  }
+
   /**
    * Gets the current face of the button.
    * 
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
index e486ef6..e283f85 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingChangeListenerCollection.java
@@ -39,6 +39,7 @@
  *  }
  *</pre>
  */
+@Deprecated
 public class DelegatingChangeListenerCollection extends
     ChangeListenerCollection implements ChangeListener {
 
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
index afe3f37..0e66518 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingClickListenerCollection.java
@@ -39,6 +39,7 @@
  *  }
  *</pre>
  */
+@Deprecated
 public class DelegatingClickListenerCollection extends ClickListenerCollection
     implements ClickListener {
 
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
index 438add4..7c937e0 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingFocusListenerCollection.java
@@ -39,6 +39,7 @@
  *  }
  *</pre>
  */
+@Deprecated
 public class DelegatingFocusListenerCollection extends FocusListenerCollection
     implements FocusListener {
 
diff --git a/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java b/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
index 1992254..6994c25 100644
--- a/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/DelegatingKeyboardListenerCollection.java
@@ -40,6 +40,7 @@
  *  }
  *</pre>
  */
+@Deprecated
 public class DelegatingKeyboardListenerCollection extends
     KeyboardListenerCollection implements KeyboardListener {
 
diff --git a/user/src/com/google/gwt/user/client/ui/DialogBox.java b/user/src/com/google/gwt/user/client/ui/DialogBox.java
index d52a649..3522241 100644
--- a/user/src/com/google/gwt/user/client/ui/DialogBox.java
+++ b/user/src/com/google/gwt/user/client/ui/DialogBox.java
@@ -16,11 +16,24 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.logical.shared.ResizeEvent;
+import com.google.gwt.event.logical.shared.ResizeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.WindowResizeListener;
 
 /**
  * A form of popup that has a caption area at the top and can be dragged by the
@@ -55,28 +68,64 @@
  * <li>.gwt-DialogBox .dialogBottomCenterInner { the inner element of the cell }</li>
  * <li>.gwt-DialogBox .dialogBottomRight { the bottom right cell }</li>
  * <li>.gwt-DialogBox .dialogBottomRightInner { the inner element of the cell }</li>
- * </ul>
  * <p>
  * <h3>Example</h3>
  * {@example com.google.gwt.examples.DialogBoxExample}
  * </p>
  */
+@SuppressWarnings("deprecation")
 public class DialogBox extends DecoratedPopupPanel implements HasHTML, HasText,
     MouseListener {
   /**
+   * Set of characteristic interfaces supported by the {@link DialogBox} caption
+   *
+   * Note that this set might expand over time, so implement this interface at
+   * your own risk.
+   */
+  public interface Caption extends HasAllMouseHandlers {
+  }
+
+  private class CaptionImpl extends HTML implements Caption {
+  }
+
+  private class MouseHandler implements MouseDownHandler, MouseUpHandler,
+      MouseOutHandler, MouseOverHandler, MouseMoveHandler {
+
+    public void onMouseDown(MouseDownEvent event) {
+      beginDragging(event);
+    }
+
+    public void onMouseMove(MouseMoveEvent event) {
+      continueDragging(event);
+    }
+
+    public void onMouseOut(MouseOutEvent event) {
+      DialogBox.this.onMouseLeave(caption);
+    }
+
+    public void onMouseOver(MouseOverEvent event) {
+      DialogBox.this.onMouseEnter(caption);
+    }
+
+    public void onMouseUp(MouseUpEvent event) {
+      endDragging(event);
+    }
+  }
+
+  /**
    * The default style name.
    */
   private static final String DEFAULT_STYLENAME = "gwt-DialogBox";
 
-  private HTML caption = new HTML();
+  private CaptionImpl caption = new CaptionImpl();
   private boolean dragging;
   private int dragStartX, dragStartY;
-  private MouseListenerCollection mouseListeners = new MouseListenerCollection();
-  private WindowResizeListener resizeListener;
   private int windowWidth;
   private int clientLeft;
   private int clientTop;
 
+  private HandlerRegistration resizeHandlerRegistration;
+
   /**
    * Creates an empty dialog box. It should not be shown until its child widget
    * has been added using {@link #add(Widget)}.
@@ -91,7 +140,7 @@
    * {@link #add(Widget)}.
    * 
    * @param autoHide <code>true</code> if the dialog should be automatically
-   *          hidden when the user clicks outside of it
+   * hidden when the user clicks outside of it
    */
   public DialogBox(boolean autoHide) {
     this(autoHide, true);
@@ -103,9 +152,9 @@
    * {@link #add(Widget)}.
    * 
    * @param autoHide <code>true</code> if the dialog should be automatically
-   *          hidden when the user clicks outside of it
-   * @param modal <code>true</code> if keyboard and mouse events for widgets
-   *          not contained by the dialog should be ignored
+   * hidden when the user clicks outside of it
+   * @param modal <code>true</code> if keyboard and mouse events for widgets not
+   * contained by the dialog should be ignored
    */
   public DialogBox(boolean autoHide, boolean modal) {
     super(autoHide, modal, "dialog");
@@ -116,15 +165,33 @@
     DOM.appendChild(td, caption.getElement());
     adopt(caption);
     caption.setStyleName("Caption");
-    mouseListeners.add(this);
 
     // Set the style name
     setStyleName(DEFAULT_STYLENAME);
-    sinkEvents(Event.MOUSEEVENTS);
 
     windowWidth = Window.getClientWidth();
     clientLeft = Document.get().getBodyOffsetLeft();
     clientTop = Document.get().getBodyOffsetTop();
+
+    MouseHandler mouseHandler = new MouseHandler();
+    addDomHandler(mouseHandler, MouseDownEvent.getType());
+    addDomHandler(mouseHandler, MouseUpEvent.getType());
+    addDomHandler(mouseHandler, MouseMoveEvent.getType());
+    addDomHandler(mouseHandler, MouseOverEvent.getType());
+    addDomHandler(mouseHandler, MouseOutEvent.getType());
+  }
+
+  /**
+   * Provides access to the dialog's caption.
+   *
+   * This method is final because the Caption interface will expand. Therefore
+   * it is highly likely that subclasses which implemented this method would end up
+   * breaking.
+   * 
+   * @return the logical caption for this dialog box
+   */
+  public final Caption getCaption() {
+    return caption;
   }
 
   public String getHTML() {
@@ -137,31 +204,27 @@
 
   @Override
   public void hide() {
-    Window.removeWindowResizeListener(resizeListener);
+    resizeHandlerRegistration.removeHandler();
+    resizeHandlerRegistration = null;
     super.hide();
   }
 
   @Override
   public void onBrowserEvent(Event event) {
-    super.onBrowserEvent(event);
-
-    // Only trigger mouse events if the event occurs in the caption wrapper
-    if (!dragging
-        && !getCellElement(0, 1).getParentElement().isOrHasChild(
-            event.getTarget())) {
-      return;
-    }
-
-    // Trigger a mouse event as if it originated in the caption
+    // If we're not yet dragging, only trigger mouse events if the event occurs
+    // in the caption wrapper
     switch (event.getTypeInt()) {
       case Event.ONMOUSEDOWN:
       case Event.ONMOUSEUP:
       case Event.ONMOUSEMOVE:
       case Event.ONMOUSEOVER:
       case Event.ONMOUSEOUT:
-        mouseListeners.fireMouseEvent(caption, event);
-        break;
+        if (!dragging && !isCaptionEvent(event)) {
+          return;
+        }
     }
+
+    super.onBrowserEvent(event);
   }
 
   @Override
@@ -169,15 +232,18 @@
     // We need to preventDefault() on mouseDown events (outside of the
     // DialogBox content) to keep text from being selected when it
     // is dragged.
-    if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
-      if (DOM.isOrHasChild(caption.getElement(), DOM.eventGetTarget(event))) {
-        DOM.eventPreventDefault(event);
-      }
+    if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && isCaptionEvent(event)) {
+      DOM.eventPreventDefault(event);
     }
 
     return super.onEventPreview(event);
   }
 
+  /**
+   * @deprecated Use {@link #beginDragging} instead and {@link #getCaption}
+   * instead
+   */
+  @Deprecated
   public void onMouseDown(Widget sender, int x, int y) {
     dragging = true;
     DOM.setCapture(getElement());
@@ -185,12 +251,18 @@
     dragStartY = y;
   }
 
+  @Deprecated
   public void onMouseEnter(Widget sender) {
   }
 
+  @Deprecated
   public void onMouseLeave(Widget sender) {
   }
 
+  /**
+   * @deprecated Use {@link #continueDragging} and {@link #getCaption} instead
+   */
+  @Deprecated
   public void onMouseMove(Widget sender, int x, int y) {
     if (dragging) {
       int absX = x + getAbsoluteLeft();
@@ -207,6 +279,10 @@
     }
   }
 
+  /**
+   * @deprecated Use {@link #endDragging} and {@link #getCaption} instead
+   */
+  @Deprecated
   public void onMouseUp(Widget sender, int x, int y) {
     dragging = false;
     DOM.releaseCapture(getElement());
@@ -238,17 +314,42 @@
 
   @Override
   public void show() {
-    if (resizeListener == null) {
-      resizeListener = new WindowResizeListener() {
-        public void onWindowResized(int width, int height) {
-          windowWidth = width;
+    if (resizeHandlerRegistration == null) {
+      resizeHandlerRegistration = Window.addResizeHandler(new ResizeHandler() {
+        public void onResize(ResizeEvent event) {
+          windowWidth = event.getWidth();
         }
-      };
+      });
     }
-    Window.addWindowResizeListener(resizeListener);
     super.show();
   }
 
+  /**
+   * Called on mouse down in the caption area, begins the dragging loop by
+   * turning on event capture.
+   * 
+   * @see DOM#setCapture
+   * @see #continueDragging
+   * @param event the mouse down event that triggered dragging
+   */
+  protected void beginDragging(MouseDownEvent event) {
+    onMouseDown(caption, event.getRelativeX(getElement()),
+        event.getRelativeY(getElement()));
+  }
+
+  /**
+   * Called on mouse move in the caption area, continues dragging if it was
+   * started by {@link #beginDragging}.
+   * 
+   * @see #beginDragging
+   * @see #endDragging
+   * @param event the mouse move event that continues dragging
+   */
+  protected void continueDragging(MouseMoveEvent event) {
+    onMouseMove(caption, event.getRelativeX(getElement()),
+        event.getRelativeY(getElement()));
+  }
+
   @Override
   protected void doAttachChildren() {
     super.doAttachChildren();
@@ -269,6 +370,20 @@
   }
 
   /**
+   * Called on mouse up in the caption area, ends dragging by ending event
+   * capture.
+   * @param event  the mouse up event that ended dragging
+   * 
+   * @see DOM#releaseCapture
+   * @see #beginDragging
+   * @see #endDragging
+   */
+  protected void endDragging(MouseUpEvent event) {
+    onMouseUp(caption, event.getRelativeX(getElement()),
+        event.getRelativeY(getElement()));
+  }
+
+  /**
    * <b>Affected Elements:</b>
    * <ul>
    * <li>-caption = text at the top of the {@link DialogBox}.</li>
@@ -283,4 +398,9 @@
     caption.ensureDebugId(baseID + "-caption");
     ensureDebugId(getCellElement(1, 1), baseID, "content");
   }
+
+  private boolean isCaptionEvent(Event event) {
+    return getCellElement(0, 1).getParentElement().isOrHasChild(
+        event.getTarget());
+  }
 }
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosureEvent.java b/user/src/com/google/gwt/user/client/ui/DisclosureEvent.java
index a1a8ae8..f5405d0 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosureEvent.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosureEvent.java
@@ -20,6 +20,7 @@
 /**
  * Event object containing information about {@link DisclosurePanel} changes.
  */
+@Deprecated
 public class DisclosureEvent extends EventObject {
   /**
    * Creates a new instance of the event object.
@@ -28,6 +29,7 @@
    * 
    * @see DisclosureHandler
    */
+  @Deprecated
   public DisclosureEvent(DisclosurePanel sender) {
     super(sender);
   }
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosureHandler.java b/user/src/com/google/gwt/user/client/ui/DisclosureHandler.java
index 6e0edf6..5d09bd0 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosureHandler.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosureHandler.java
@@ -15,17 +15,21 @@
  */
 package com.google.gwt.user.client.ui;
 
+import java.util.EventListener;
+
 /**
  * Event handler interface for {@link DisclosureEvent}.
  * 
  * @see DisclosurePanel
  */
-public interface DisclosureHandler {
+@Deprecated
+public interface DisclosureHandler extends EventListener {
   /**
    * Fired when the panel is closed.
    * 
    * @param event event representing this action.
    */
+  @Deprecated
   void onClose(DisclosureEvent event);
 
   /**
@@ -33,5 +37,6 @@
    * 
    * @param event event representing this action.
    */
+  @Deprecated
   void onOpen(DisclosureEvent event);
 }
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
index 6e7b243..12ee898 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosurePanel.java
@@ -17,12 +17,18 @@
 
 import com.google.gwt.animation.client.Animation;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.HasCloseHandlers;
+import com.google.gwt.event.logical.shared.HasOpenHandlers;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 
-import java.util.ArrayList;
 import java.util.Iterator;
 
 /**
@@ -34,9 +40,6 @@
  * <li>.gwt-DisclosurePanel { the panel's primary style }</li>
  * <li>.gwt-DisclosurePanel-open { dependent style set when panel is open }</li>
  * <li>.gwt-DisclosurePanel-closed { dependent style set when panel is closed }</li>
- * <li>.header { the header section }</li>
- * <li>.content { the content section }</li>
- * </ul>
  * 
  * <p>
  * <img class='gallery' src='DisclosurePanel.png'/>
@@ -48,9 +51,10 @@
  * </p>
  */
 public final class DisclosurePanel extends Composite implements
-    FiresDisclosureEvents, HasWidgets, HasAnimation {
+    FiresDisclosureEvents, HasWidgets, HasAnimation,
+    HasOpenHandlers<DisclosurePanel>, HasCloseHandlers<DisclosurePanel> {
   /**
-   * The duration of the animation. 
+   * The duration of the animation.
    */
   private static final int ANIMATION_DURATION = 350;
 
@@ -156,7 +160,7 @@
    * The default header widget used within a {@link DisclosurePanel}.
    */
   private class DefaultHeader extends Widget implements HasText,
-      DisclosureHandler {
+      OpenHandler<DisclosurePanel>, CloseHandler<DisclosurePanel> {
 
     /**
      * imageTD holds the image for the icon, not null. labelTD holds the text
@@ -196,7 +200,8 @@
 
       setText(text);
 
-      addEventHandler(this);
+      addOpenHandler(this);
+      addCloseHandler(this);
       setStyle();
     }
 
@@ -204,11 +209,11 @@
       return DOM.getInnerText(labelTD);
     }
 
-    public final void onClose(DisclosureEvent event) {
+    public final void onClose(CloseEvent<DisclosurePanel> event) {
       setStyle();
     }
 
-    public final void onOpen(DisclosureEvent event) {
+    public final void onOpen(OpenEvent<DisclosurePanel> event) {
       setStyle();
     }
 
@@ -275,12 +280,6 @@
   private boolean isOpen = false;
 
   /**
-   * null until #{@link #addEventHandler(DisclosureHandler)} is called (lazily
-   * initialized).
-   */
-  private ArrayList<DisclosureHandler> handlers;
-
-  /**
    * Creates an empty DisclosurePanel that is initially closed.
    */
   public DisclosurePanel() {
@@ -306,7 +305,7 @@
    * Creates a DisclosurePanel that will be initially closed using the specified
    * text in the header.
    * 
-   * @param headerText the text to be displayed in the header.
+   * @param headerText the text to be displayed in the header
    */
   public DisclosurePanel(String headerText) {
     this(createDefaultImages(), headerText, false);
@@ -354,17 +353,26 @@
     }
   }
 
+  public HandlerRegistration addCloseHandler(
+      CloseHandler<DisclosurePanel> handler) {
+    return addHandler(handler, CloseEvent.getType());
+  }
+
   /**
    * Attaches an event handler to the panel to receive {@link DisclosureEvent}
    * notification.
    * 
    * @param handler the handler to be added (should not be null)
+   * @deprecated use {@link DisclosurePanel#addOpenHandler(OpenHandler)} and
+   * {@link DisclosurePanel#addCloseHandler(CloseHandler)} instead
    */
-  public void addEventHandler(DisclosureHandler handler) {
-    if (handlers == null) {
-      handlers = new ArrayList<DisclosureHandler>();
-    }
-    handlers.add(handler);
+  @Deprecated
+  public void addEventHandler(final DisclosureHandler handler) {
+    ListenerWrapper.Disclosure.add(this, handler);
+  }
+
+  public HandlerRegistration addOpenHandler(OpenHandler<DisclosurePanel> handler) {
+    return addHandler(handler, OpenEvent.getType());
   }
 
   public void clear() {
@@ -394,7 +402,7 @@
    * the header widget does provide such access.
    * 
    * @return a reference to the header widget if it implements {@link HasText},
-   *         <code>null</code> otherwise
+   * <code>null</code> otherwise
    */
   public HasText getHeaderTextAccessor() {
     Widget widget = header.getWidget();
@@ -432,11 +440,9 @@
    * 
    * @param handler the handler to be removed
    */
+  @Deprecated
   public void removeEventHandler(DisclosureHandler handler) {
-    if (handlers == null) {
-      return;
-    }
-    handlers.remove(handler);
+    ListenerWrapper.Disclosure.remove(this, handler);
   }
 
   public void setAnimationEnabled(boolean enable) {
@@ -479,8 +485,8 @@
   /**
    * Changes the visible state of this <code>DisclosurePanel</code>.
    * 
-   * @param isOpen <code>true</code> to open the panel, <code>false</code>
-   *          to close
+   * @param isOpen <code>true</code> to open the panel, <code>false</code> to
+   * close
    */
   public void setOpen(boolean isOpen) {
     if (this.isOpen != isOpen) {
@@ -505,17 +511,10 @@
   }
 
   private void fireEvent() {
-    if (handlers == null) {
-      return;
-    }
-
-    DisclosureEvent event = new DisclosureEvent(this);
-    for (DisclosureHandler handler : handlers) {
-      if (isOpen) {
-        handler.onOpen(event);
-      } else {
-        handler.onClose(event);
-      }
+    if (isOpen) {
+      OpenEvent.fire(this, this);
+    } else {
+      CloseEvent.fire(this, this);
     }
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java b/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
index ac84430..ae8792f 100644
--- a/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
+++ b/user/src/com/google/gwt/user/client/ui/DisclosurePanelImages.java
@@ -35,7 +35,6 @@
   AbstractImagePrototype disclosurePanelClosed();
 }
 
-
 /**
  * A bundle containing the RTL versions of the images for DisclosurePanel. Right now, we
  * only need to override the disclosurePanelClosed() method, as the image that we provide
diff --git a/user/src/com/google/gwt/user/client/ui/FiresDisclosureEvents.java b/user/src/com/google/gwt/user/client/ui/FiresDisclosureEvents.java
index f4383ba..6ea43b2 100644
--- a/user/src/com/google/gwt/user/client/ui/FiresDisclosureEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/FiresDisclosureEvents.java
@@ -25,13 +25,16 @@
    * Adds a handler interface to receive open events.
    * 
    * @param handler the handler to add
+   * @deprecated add an open or close handler to the event source instead
    */
+  @Deprecated
   void addEventHandler(DisclosureHandler handler);
   
   /**
    * Removes a previously added handler interface.
    * 
-   * @param handler the handler to remove.
+   * @param handler the handler to remove
    */
+  @Deprecated
   void removeEventHandler(DisclosureHandler handler);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FiresFormEvents.java b/user/src/com/google/gwt/user/client/ui/FiresFormEvents.java
index 78560df..a4a6541 100644
--- a/user/src/com/google/gwt/user/client/ui/FiresFormEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/FiresFormEvents.java
@@ -19,13 +19,17 @@
  * A widget that implements this interface fires the events defined by the
  * {@link com.google.gwt.user.client.ui.FormHandler} interface.
  */
+
 public interface FiresFormEvents {
 
   /**
    * Adds a handler interface to receive click events.
    * 
+   * @deprecated use {@link FormPanel#addSubmitCompleteHandler} and
+   * {@link FormPanel#addSubmitHandler} instead
    * @param handler the handler interface to add
    */
+  @Deprecated
   void addFormHandler(FormHandler handler);
 
   /**
@@ -33,5 +37,6 @@
    * 
    * @param handler the handler interface to remove
    */
+  @Deprecated
   void removeFormHandler(FormHandler handler);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FiresSuggestionEvents.java b/user/src/com/google/gwt/user/client/ui/FiresSuggestionEvents.java
index ec9db30..1e24d57 100644
--- a/user/src/com/google/gwt/user/client/ui/FiresSuggestionEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/FiresSuggestionEvents.java
@@ -24,14 +24,17 @@
   /**
    * Adds a handler interface to receive suggestion events.
    * 
+   * @deprecated add a selection handler instead
    * @param handler the handler to add
    */
+  @Deprecated
   void addEventHandler(SuggestionHandler handler);
 
   /**
    * Removes a previously added handler interface.
    * 
-   * @param handler the handler to remove.
+   * @param handler the handler to remove
    */
+  @Deprecated
   void removeEventHandler(SuggestionHandler handler);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FocusListener.java b/user/src/com/google/gwt/user/client/ui/FocusListener.java
index ff69ecf..e89ceed 100644
--- a/user/src/com/google/gwt/user/client/ui/FocusListener.java
+++ b/user/src/com/google/gwt/user/client/ui/FocusListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener for focus events.
  */
+@Deprecated
 public interface FocusListener extends EventListener {
 
   /**
@@ -27,6 +28,7 @@
    * 
    * @param sender the widget receiving focus.
    */
+  @Deprecated
   void onFocus(Widget sender);
 
   /**
@@ -34,5 +36,6 @@
    * 
    * @param sender the widget losing focus.
    */
+  @Deprecated
   void onLostFocus(Widget sender);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FocusListenerAdapter.java b/user/src/com/google/gwt/user/client/ui/FocusListenerAdapter.java
index 2ac3c3f..121269c 100644
--- a/user/src/com/google/gwt/user/client/ui/FocusListenerAdapter.java
+++ b/user/src/com/google/gwt/user/client/ui/FocusListenerAdapter.java
@@ -19,6 +19,7 @@
  * An adapter to simplify focus event listeners that do not need all events
  * defined on the FocusListener interface.
  */
+@Deprecated
 public abstract class FocusListenerAdapter implements FocusListener {
 
   public void onFocus(Widget sender) {
diff --git a/user/src/com/google/gwt/user/client/ui/FocusListenerCollection.java b/user/src/com/google/gwt/user/client/ui/FocusListenerCollection.java
index 26b4b31..cfa0409 100644
--- a/user/src/com/google/gwt/user/client/ui/FocusListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/FocusListenerCollection.java
@@ -26,6 +26,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.FocusListener}.
  */
+@Deprecated
 public class FocusListenerCollection extends ArrayList<FocusListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/FocusPanel.java b/user/src/com/google/gwt/user/client/ui/FocusPanel.java
index 64d90a0..a8feb75 100644
--- a/user/src/com/google/gwt/user/client/ui/FocusPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/FocusPanel.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2007 Google Inc.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * 
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,8 +15,35 @@
  */
 package com.google.gwt.user.client.ui;
 
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasAllFocusHandlers;
+import com.google.gwt.event.dom.client.HasAllKeyHandlers;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelEvent;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.ui.impl.FocusImpl;
 
 /**
@@ -24,20 +51,14 @@
  * catch mouse and keyboard events.
  */
 public class FocusPanel extends SimplePanel implements HasFocus,
-    SourcesClickEvents, SourcesMouseEvents, SourcesMouseWheelEvents {
+    SourcesClickEvents, SourcesMouseEvents, SourcesMouseWheelEvents,
+    HasAllMouseHandlers, HasClickHandlers, HasAllKeyHandlers,
+    HasAllFocusHandlers {
 
   static final FocusImpl impl = FocusImpl.getFocusImplForPanel();
 
-  private ClickListenerCollection clickListeners;
-  private FocusListenerCollection focusListeners;
-  private KeyboardListenerCollection keyboardListeners;
-  private MouseListenerCollection mouseListeners;
-  private MouseWheelListenerCollection mouseWheelListeners;
-
   public FocusPanel() {
     super(impl.createFocusable());
-    sinkEvents(Event.FOCUSEVENTS | Event.KEYEVENTS | Event.ONCLICK
-      | Event.MOUSEEVENTS | Event.ONMOUSEWHEEL);
   }
 
   public FocusPanel(Widget child) {
@@ -45,115 +66,106 @@
     setWidget(child);
   }
 
+  public HandlerRegistration addBlurHandler(BlurHandler handler) {
+    return addDomHandler(handler, BlurEvent.getType());
+  }
+
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addDomHandler(handler, ClickEvent.getType());
+  }
+
+  @Deprecated
   public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new ClickListenerCollection();
-    }
-    clickListeners.add(listener);
+    ListenerWrapper.Click.add(this, listener);
   }
 
+  public HandlerRegistration addFocusHandler(FocusHandler handler) {
+    return addDomHandler(handler, FocusEvent.getType());
+  }
+
+  @Deprecated
   public void addFocusListener(FocusListener listener) {
-    if (focusListeners == null) {
-      focusListeners = new FocusListenerCollection();
-    }
-    focusListeners.add(listener);
+    ListenerWrapper.Focus.add(this, listener);
   }
 
+  @Deprecated
   public void addKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners == null) {
-      keyboardListeners = new KeyboardListenerCollection();
-    }
-    keyboardListeners.add(listener);
+    ListenerWrapper.Keyboard.add(this, listener);
   }
 
+  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+    return addDomHandler(handler, KeyDownEvent.getType());
+  }
+
+  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+    return addDomHandler(handler, KeyPressEvent.getType());
+  }
+
+  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+    return addDomHandler(handler, KeyUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+    return addDomHandler(handler, MouseDownEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseListener(MouseListener listener) {
-    if (mouseListeners == null) {
-      mouseListeners = new MouseListenerCollection();
-    }
-    mouseListeners.add(listener);
+    ListenerWrapper.Mouse.add(this, listener);
   }
 
+  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+    return addDomHandler(handler, MouseMoveEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+    return addDomHandler(handler, MouseOutEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+    return addDomHandler(handler, MouseOverEvent.getType());
+  }
+
+  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+    return addDomHandler(handler, MouseUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+    return addDomHandler(handler, MouseWheelEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners == null) {
-      mouseWheelListeners = new MouseWheelListenerCollection();
-    }
-    mouseWheelListeners.add(listener);
+    ListenerWrapper.MouseWheel.add(this, listener);
   }
 
   public int getTabIndex() {
     return impl.getTabIndex(getElement());
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    switch (DOM.eventGetType(event)) {
-      case Event.ONCLICK:
-        if (clickListeners != null) {
-          clickListeners.fireClick(this);
-        }
-        break;
-
-      case Event.ONMOUSEDOWN:
-      case Event.ONMOUSEUP:
-      case Event.ONMOUSEMOVE:
-      case Event.ONMOUSEOVER:
-      case Event.ONMOUSEOUT:
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-
-      case Event.ONMOUSEWHEEL:
-        if (mouseWheelListeners != null) {
-          mouseWheelListeners.fireMouseWheelEvent(this, event);
-        }
-        break;
-
-      case Event.ONBLUR:
-      case Event.ONFOCUS:
-        if (focusListeners != null) {
-          focusListeners.fireFocusEvent(this, event);
-        }
-        break;
-
-      case Event.ONKEYDOWN:
-      case Event.ONKEYUP:
-      case Event.ONKEYPRESS:
-        if (keyboardListeners != null) {
-          keyboardListeners.fireKeyboardEvent(this, event);
-        }
-        break;
-    }
-  }
-
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(this, listener);
   }
 
+  @Deprecated
   public void removeFocusListener(FocusListener listener) {
-    if (focusListeners != null) {
-      focusListeners.remove(listener);
-    }
+    ListenerWrapper.Focus.remove(this, listener);
   }
 
+  @Deprecated
   public void removeKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners != null) {
-      keyboardListeners.remove(listener);
-    }
+    ListenerWrapper.Keyboard.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseListener(MouseListener listener) {
-    if (mouseListeners != null) {
-      mouseListeners.remove(listener);
-    }
+    ListenerWrapper.Mouse.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners != null) {
-      mouseWheelListeners.remove(listener);
-    }
+    ListenerWrapper.MouseWheel.remove(this, listener);
   }
 
   public void setAccessKey(char key) {
diff --git a/user/src/com/google/gwt/user/client/ui/FocusWidget.java b/user/src/com/google/gwt/user/client/ui/FocusWidget.java
index cb09062..2c0757a 100644
--- a/user/src/com/google/gwt/user/client/ui/FocusWidget.java
+++ b/user/src/com/google/gwt/user/client/ui/FocusWidget.java
@@ -16,15 +16,44 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasAllFocusHandlers;
+import com.google.gwt.event.dom.client.HasAllKeyHandlers;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelEvent;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.ui.impl.FocusImpl;
 
 /**
  * Abstract base class for most widgets that can receive keyboard focus.
  */
 public abstract class FocusWidget extends Widget implements SourcesClickEvents,
-    SourcesFocusEvents, HasFocus, SourcesKeyboardEvents {
+    HasClickHandlers, HasFocus, HasAllFocusHandlers, HasAllKeyHandlers,
+    HasAllMouseHandlers, SourcesMouseEvents {
 
   private static final FocusImpl impl = FocusImpl.getFocusImplForWidget();
 
@@ -37,10 +66,6 @@
     return impl;
   }
 
-  private ClickListenerCollection clickListeners;
-  private FocusListenerCollection focusListeners;
-  private KeyboardListenerCollection keyboardListeners;
-
   /**
    * Creates a new focus widget with no element. {@link #setElement(Element)}
    * must be called before any other methods.
@@ -57,30 +82,84 @@
     setElement(elem);
   }
 
+  public HandlerRegistration addBlurHandler(BlurHandler handler) {
+    return addDomHandler(handler, BlurEvent.getType());
+  }
+
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addDomHandler(handler, ClickEvent.getType());
+  }
+
+  @Deprecated
   public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new ClickListenerCollection();
-      sinkEvents(Event.ONCLICK);
-    }
-    clickListeners.add(listener);
+    ListenerWrapper.Click.add(this, listener);
   }
 
+  public HandlerRegistration addFocusHandler(FocusHandler handler) {
+    return addDomHandler(handler, FocusEvent.getType());
+  }
+
+  @Deprecated
   public void addFocusListener(FocusListener listener) {
-    if (focusListeners == null) {
-      focusListeners = new FocusListenerCollection();
-      sinkEvents(Event.FOCUSEVENTS);
-    }
-    focusListeners.add(listener);
+    ListenerWrapper.Focus.add(this, listener);
   }
 
+  @Deprecated
   public void addKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners == null) {
-      keyboardListeners = new KeyboardListenerCollection();
-      sinkEvents(Event.KEYEVENTS);
-    }
-    keyboardListeners.add(listener);
+    ListenerWrapper.Keyboard.add(this, listener);
   }
 
+  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+    return addDomHandler(handler, KeyDownEvent.getType());
+  }
+
+  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+    return addDomHandler(handler, KeyPressEvent.getType());
+  }
+
+  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+    return addDomHandler(handler, KeyUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+    return addDomHandler(handler, MouseDownEvent.getType());
+  }
+
+  @Deprecated
+  public void addMouseListener(MouseListener listener) {
+    ListenerWrapper.Mouse.add(this, listener);
+  }
+
+  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+    return addDomHandler(handler, MouseMoveEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+    return addDomHandler(handler, MouseOutEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+    return addDomHandler(handler, MouseOverEvent.getType());
+  }
+
+  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+    return addDomHandler(handler, MouseUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+    return addDomHandler(handler, MouseWheelEvent.getType());
+  }
+
+  @Deprecated
+  public void addMouseWheelListener(MouseWheelListener listener) {
+    ListenerWrapper.MouseWheel.add(this, listener);
+  }
+
+  /**
+   * Gets the tab index.
+   * 
+   * @return the tab index
+   */
   public int getTabIndex() {
     return impl.getTabIndex(getElement());
   }
@@ -94,48 +173,29 @@
     return !DOM.getElementPropertyBoolean(getElement(), "disabled");
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    switch (DOM.eventGetType(event)) {
-      case Event.ONCLICK:
-        if (clickListeners != null) {
-          clickListeners.fireClick(this);
-        }
-        break;
-
-      case Event.ONBLUR:
-      case Event.ONFOCUS:
-        if (focusListeners != null) {
-          focusListeners.fireFocusEvent(this, event);
-        }
-        break;
-
-      case Event.ONKEYDOWN:
-      case Event.ONKEYUP:
-      case Event.ONKEYPRESS:
-        if (keyboardListeners != null) {
-          keyboardListeners.fireKeyboardEvent(this, event);
-        }
-        break;
-    }
-  }
-
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(this, listener);
   }
 
+  @Deprecated
   public void removeFocusListener(FocusListener listener) {
-    if (focusListeners != null) {
-      focusListeners.remove(listener);
-    }
+    ListenerWrapper.Focus.remove(this, listener);
   }
 
+  @Deprecated
   public void removeKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners != null) {
-      keyboardListeners.remove(listener);
-    }
+    ListenerWrapper.Keyboard.remove(this, listener);
+  }
+
+  @Deprecated
+  public void removeMouseListener(MouseListener listener) {
+    ListenerWrapper.Mouse.remove(this, listener);
+  }
+
+  @Deprecated
+  public void removeMouseWheelListener(MouseWheelListener listener) {
+    ListenerWrapper.MouseWheel.remove(this, listener);
   }
 
   public void setAccessKey(char key) {
@@ -176,16 +236,4 @@
     setTabIndex(0);
   }
 
-  /**
-   * Fire all current {@link ClickListener}.
-   */
-  void fireClickListeners() {
-    /*
-     * Implementation note: PushButton needs to fire click listeners manually.
-     * Exposing this method so it can do so.
-     */
-    if (clickListeners != null) {
-      clickListeners.fireClick(this);
-    }
-  }
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FormHandler.java b/user/src/com/google/gwt/user/client/ui/FormHandler.java
index f59e2e3..4c5faec 100644
--- a/user/src/com/google/gwt/user/client/ui/FormHandler.java
+++ b/user/src/com/google/gwt/user/client/ui/FormHandler.java
@@ -20,6 +20,7 @@
 /**
  * Handler interface for form submit events.
  */
+@Deprecated
 public interface FormHandler extends EventListener {
 
   /**
@@ -34,6 +35,7 @@
    * @param event an event object containing information about the form
    *          submission
    */
+  @Deprecated
   void onSubmit(FormSubmitEvent event);
 
   /**
@@ -42,5 +44,6 @@
    * @param event an event object containing information about the form
    *          submission
    */
+  @Deprecated
   void onSubmitComplete(FormSubmitCompleteEvent event);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/FormHandlerCollection.java b/user/src/com/google/gwt/user/client/ui/FormHandlerCollection.java
index c99ac40..ecb31b8 100644
--- a/user/src/com/google/gwt/user/client/ui/FormHandlerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/FormHandlerCollection.java
@@ -23,6 +23,7 @@
  * subclass of ArrayList assumes that all items added to it will be of type
  * {@link com.google.gwt.user.client.ui.FormHandler}.
  */
+@Deprecated
 public class FormHandlerCollection extends ArrayList<FormHandler> {
 
   /**
@@ -32,6 +33,7 @@
    * @param sender the object sending the event
    * @param results the results of the form submission
    */
+  @Deprecated
   public void fireOnComplete(FormPanel sender, String results) {
     FormSubmitCompleteEvent event = new FormSubmitCompleteEvent(sender, results);
     for (FormHandler handler : this) {
@@ -46,6 +48,7 @@
    * @param sender the object sending the event
    * @return <code>true</code> if the event should be cancelled
    */
+  @Deprecated
   public boolean fireOnSubmit(FormPanel sender) {
     FormSubmitEvent event = new FormSubmitEvent(sender);
     for (FormHandler handler : this) {
diff --git a/user/src/com/google/gwt/user/client/ui/FormPanel.java b/user/src/com/google/gwt/user/client/ui/FormPanel.java
index 08cb5ba..8b489e3 100644
--- a/user/src/com/google/gwt/user/client/ui/FormPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/FormPanel.java
@@ -20,6 +20,9 @@
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.FormElement;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Event;
@@ -46,9 +49,9 @@
  * <li>{@link com.google.gwt.user.client.ui.FileUpload}</li>
  * <li>{@link com.google.gwt.user.client.ui.Hidden}</li>
  * </ul>
- * In particular, {@link com.google.gwt.user.client.ui.FileUpload} is <i>only</i>
- * useful when used within a FormPanel, because the browser will only upload
- * files using form submission.
+ * In particular, {@link com.google.gwt.user.client.ui.FileUpload} is
+ * <i>only</i> useful when used within a FormPanel, because the browser will
+ * only upload files using form submission.
  * </p>
  * 
  * <p>
@@ -58,6 +61,150 @@
  */
 public class FormPanel extends SimplePanel implements FiresFormEvents,
     FormPanelImplHost {
+  /**
+   * Fired when a form has been submitted successfully.
+   */
+  public static class SubmitCompleteEvent extends
+      GwtEvent<SubmitCompleteHandler> {
+    /**
+     * The event type.
+     */
+    private static Type<SubmitCompleteHandler> TYPE;
+
+    /**
+     * Handler hook.
+     * 
+     * @return the handler hook
+     */
+    static Type<SubmitCompleteHandler> getType() {
+      if (TYPE == null) {
+        TYPE = new Type<SubmitCompleteHandler>();
+      }
+      return TYPE;
+    }
+
+    private String resultHtml;
+
+    /**
+     * Create a submit complete event
+     * @param resultsHtml the results from submitting the form
+     */
+    protected SubmitCompleteEvent(String resultsHtml) {
+      this.resultHtml = resultsHtml;
+    }
+
+    /**
+     * Gets the result text of the form submission.
+     * 
+     * @return the result html, or <code>null</code> if there was an error
+     *         reading it
+     * @tip The result html can be <code>null</code> as a result of submitting a
+     *      form to a different domain.
+     */
+    public String getResults() {
+      return resultHtml;
+    }
+
+    @Override
+    protected void dispatch(SubmitCompleteHandler handler) {
+      handler.onSubmitComplete(this);
+    }
+
+    @Override
+    protected Type<SubmitCompleteHandler> getAssociatedType() {
+      return TYPE;
+    }
+  }
+
+  /**
+   * Handler for {@link FormPanel.SubmitCompleteEvent} events.
+   */
+  public interface SubmitCompleteHandler extends EventHandler {
+    /**
+     * Fired when a form has been submitted successfully.
+     * 
+     * @param event the event
+     */
+    void onSubmitComplete(FormPanel.SubmitCompleteEvent event);
+  }
+
+  /**
+   * Fired when the form is submitted.
+   */
+  public static class SubmitEvent extends GwtEvent<SubmitHandler> {
+    /**
+     * The event type.
+     */
+    private static Type<SubmitHandler> TYPE = new Type<SubmitHandler>();
+
+    /**
+     * Handler hook.
+     * 
+     * @return the handler hook
+     */
+    static Type<SubmitHandler> getType() {
+      if (TYPE == null) {
+        TYPE = new Type<SubmitHandler>();
+      }
+      return TYPE;
+    }
+
+    private boolean canceled = false;
+
+    /**
+     * Cancel the form submit. Firing this will prevent a subsequent
+     * {@link FormPanel.SubmitCompleteEvent} from being fired.
+     */
+    public void cancel() {
+      this.canceled = true;
+    }
+
+    /**
+     * Gets whether this form submit will be canceled.
+     * 
+     * @return <code>true</code> if the form submit will be canceled
+     */
+    public boolean isCanceled() {
+      return canceled;
+    }
+
+    @Override
+    protected void dispatch(FormPanel.SubmitHandler handler) {
+      handler.onSubmit(this);
+    }
+
+    @Override
+    protected Type<FormPanel.SubmitHandler> getAssociatedType() {
+      return TYPE;
+    }
+
+    /**
+     * This method is used for legacy support and should be removed when
+     * {@link FormHandler} is removed.
+     */
+    @Deprecated
+    void setCanceled(boolean canceled) {
+      this.canceled = canceled;
+    }
+  }
+
+  /**
+   * Handler for {@link FormPanel.SubmitEvent} events.
+   */
+  public interface SubmitHandler extends EventHandler {
+    /**
+     *Fired when the form is submitted.
+     * 
+     * <p>
+     * The FormPanel must <em>not</em> be detached (i.e. removed from its parent
+     * or otherwise disconnected from a {@link RootPanel}) until the submission
+     * is complete. Otherwise, notification of submission will fail.
+     * </p>
+     * 
+     * @param event the event
+     */
+    void onSubmit(FormPanel.SubmitEvent event);
+  }
 
   /**
    * Used with {@link #setEncoding(String)} to specify that the form will be
@@ -123,10 +270,10 @@
    * {@link RootPanel#detachNow(Widget)}.
    * 
    * <p>
-   * If the createIFrame parameter is set to <code>true</code>, then the
-   * wrapped form's target attribute will be set to a hidden iframe. If not, the
-   * form's target will be left alone, and the FormSubmitComplete event will not
-   * be fired.
+   * If the createIFrame parameter is set to <code>true</code>, then the wrapped
+   * form's target attribute will be set to a hidden iframe. If not, the form's
+   * target will be left alone, and the FormSubmitComplete event will not be
+   * fired.
    * </p>
    * 
    * @param element the element to be wrapped
@@ -146,22 +293,21 @@
     return formPanel;
   }
 
-  private FormHandlerCollection formHandlers;
   private String frameName;
   private Element synthesizedFrame;
 
   /**
    * Creates a new FormPanel. When created using this constructor, it will be
    * submitted to a hidden &lt;iframe&gt; element, and the results of the
-   * submission made available via {@link FormHandler}.
+   * submission made available via {@link SubmitCompleteHandler}.
    * 
    * <p>
    * The back-end server is expected to respond with a content-type of
    * 'text/html', meaning that the text returned will be treated as HTML. If any
    * other content-type is specified by the server, then the result html sent in
    * the onFormSubmit event will be unpredictable across browsers, and the
-   * {@link FormHandler#onSubmitComplete(FormSubmitCompleteEvent)} event may not
-   * fire at all.
+   * {@link SubmitCompleteHandler#onSubmitComplete(SubmitCompleteEvent)} event
+   * may not fire at all.
    * </p>
    * 
    * @tip The initial implementation of FormPanel specified that the server
@@ -200,8 +346,8 @@
    * </p>
    * 
    * @param target the name of the &lt;iframe&gt; to receive the results of the
-   *          submission, or <code>null</code> to specify that the current
-   *          page be replaced
+   *          submission, or <code>null</code> to specify that the current page
+   *          be replaced
    */
   public FormPanel(String target) {
     super(Document.get().createFormElement());
@@ -218,8 +364,6 @@
    * </p>
    * 
    * @param element the element to be used
-   * @param createIFrame <code>true</code> to create an &lt;iframe&gt; element
-   *          that will be targeted by this form
    */
   protected FormPanel(Element element) {
     this(element, false);
@@ -230,10 +374,10 @@
    * element. This element must be a &lt;form&gt; element.
    * 
    * <p>
-   * If the createIFrame parameter is set to <code>true</code>, then the
-   * wrapped form's target attribute will be set to a hidden iframe. If not, the
-   * form's target will be left alone, and the FormSubmitComplete event will not
-   * be fired.
+   * If the createIFrame parameter is set to <code>true</code>, then the wrapped
+   * form's target attribute will be set to a hidden iframe. If not, the form's
+   * target will be left alone, and the FormSubmitComplete event will not be
+   * fired.
    * </p>
    * 
    * @param element the element to be used
@@ -254,11 +398,30 @@
     }
   }
 
+  @Deprecated
   public void addFormHandler(FormHandler handler) {
-    if (formHandlers == null) {
-      formHandlers = new FormHandlerCollection();
-    }
-    formHandlers.add(handler);
+    ListenerWrapper.Form.add(this, handler);
+  }
+
+  /**
+   * Adds a {@link SubmitCompleteEvent} handler.
+   * 
+   * @param handler the handler
+   * @return the handler registration used to remove the handler
+   */
+  public HandlerRegistration addSubmitCompleteHandler(
+      SubmitCompleteHandler handler) {
+    return addHandler(handler, SubmitCompleteEvent.getType());
+  }
+
+  /**
+   * Adds a {@link SubmitEvent} handler.
+   * 
+   * @param handler the handler
+   * @return the handler registration used to remove the handler
+   */
+  public HandlerRegistration addSubmitHandler(SubmitHandler handler) {
+    return addHandler(handler, SubmitEvent.getType());
   }
 
   /**
@@ -302,6 +465,11 @@
     return getFormElement().getTarget();
   }
 
+  /**
+   * Fired when a form is submitted.
+   * 
+   * @return true if the form is submitted, false if canceled
+   */
   public boolean onFormSubmit() {
     UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
     if (handler != null) {
@@ -320,10 +488,9 @@
     }
   }
 
+  @Deprecated
   public void removeFormHandler(FormHandler handler) {
-    if (formHandlers != null) {
-      formHandlers.remove(handler);
-    }
+    ListenerWrapper.Form.remove(this, handler);
   }
 
   /**
@@ -368,17 +535,15 @@
    * 
    * <p>
    * The FormPanel must <em>not</em> be detached (i.e. removed from its parent
-   * or otherwise disconnected from a {@link RootPanel}) until the submission
-   * is complete. Otherwise, notification of submission will fail.
+   * or otherwise disconnected from a {@link RootPanel}) until the submission is
+   * complete. Otherwise, notification of submission will fail.
    * </p>
    */
   public void submit() {
     // Fire the onSubmit event, because javascript's form.submit() does not
     // fire the built-in onsubmit event.
-    if (formHandlers != null) {
-      if (formHandlers.fireOnSubmit(this)) {
-        return;
-      }
+    if (!fireSubmitEvent()) {
+      return;
     }
 
     impl.submit(getElement(), synthesizedFrame);
@@ -433,6 +598,17 @@
     synthesizedFrame = dummy.getFirstChildElement();
   }
 
+  /**
+   * Fire a {@link FormPanel.SubmitEvent}.
+   * 
+   * @return true to continue, false if canceled
+   */
+  private boolean fireSubmitEvent() {
+    FormPanel.SubmitEvent event = new FormPanel.SubmitEvent();
+    fireEvent(event);
+    return !event.isCanceled();
+  }
+
   private FormElement getFormElement() {
     return getElement().cast();
   }
@@ -446,13 +622,11 @@
     }
   }
 
+  /**
+   * @return true if the form is submitted, false if canceled
+   */
   private boolean onFormSubmitImpl() {
-    if (formHandlers != null) {
-      // fireOnSubmit() returns true if the submit should be cancelled
-      return !formHandlers.fireOnSubmit(this);
-    }
-
-    return true;
+    return fireSubmitEvent();
   }
 
   private void onFrameLoadAndCatch(UncaughtExceptionHandler handler) {
@@ -464,18 +638,15 @@
   }
 
   private void onFrameLoadImpl() {
-    if (formHandlers != null) {
-      // Fire onComplete events in a deferred command. This is necessary
-      // because clients that detach the form panel when submission is
-      // complete can cause some browsers (i.e. Mozilla) to go into an
-      // 'infinite loading' state. See issue 916.
-      DeferredCommand.addCommand(new Command() {
-        public void execute() {
-          formHandlers.fireOnComplete(FormPanel.this,
-              impl.getContents(synthesizedFrame));
-        }
-      });
-    }
+    // Fire onComplete events in a deferred command. This is necessary
+    // because clients that detach the form panel when submission is
+    // complete can cause some browsers (i.e. Mozilla) to go into an
+    // 'infinite loading' state. See issue 916.
+    DeferredCommand.addCommand(new Command() {
+      public void execute() {
+        fireEvent(new SubmitCompleteEvent(impl.getContents(synthesizedFrame)));
+      }
+    });
   }
 
   private void setTarget(String target) {
diff --git a/user/src/com/google/gwt/user/client/ui/FormSubmitEvent.java b/user/src/com/google/gwt/user/client/ui/FormSubmitEvent.java
index 308795a..c8fbb40 100644
--- a/user/src/com/google/gwt/user/client/ui/FormSubmitEvent.java
+++ b/user/src/com/google/gwt/user/client/ui/FormSubmitEvent.java
@@ -23,6 +23,7 @@
 public class FormSubmitEvent extends EventObject {
 
   private boolean cancel;
+  private boolean setCancelledCalled = false;
 
   /**
    * Creates a new event with information about the source.
@@ -49,5 +50,10 @@
    */
   public void setCancelled(boolean cancel) {
     this.cancel = cancel;
+    setCancelledCalled = true;
+  }
+
+  boolean isSetCancelledCalled() {
+    return setCancelledCalled;
   }
 }
diff --git a/user/src/com/google/gwt/user/client/ui/HTMLTable.java b/user/src/com/google/gwt/user/client/ui/HTMLTable.java
index 8fbad57..0899be8 100644
--- a/user/src/com/google/gwt/user/client/ui/HTMLTable.java
+++ b/user/src/com/google/gwt/user/client/ui/HTMLTable.java
@@ -15,6 +15,10 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
@@ -33,7 +37,49 @@
  * <img class='gallery' src='Table.png'/>
  * </p>
  */
-public abstract class HTMLTable extends Panel implements SourcesTableEvents {
+public abstract class HTMLTable extends Panel implements SourcesTableEvents,
+    HasClickHandlers {
+  
+  /**
+   * Return value for {@link HTMLTable#getCellForEvent}.
+   */
+  public class Cell {
+    private final int rowIndex;
+    private final int cellIndex;
+    
+    /**
+     * Creates a cell.
+     * @param rowIndex the cell's row
+     * @param cellIndex the cell's index
+     */
+    protected Cell(int rowIndex, int cellIndex) {
+      this.cellIndex = cellIndex;
+      this.rowIndex = rowIndex;
+    }
+     
+    /**
+     * Gets the cell index.
+     * @return the cell index
+     */
+    public int getCellIndex() {
+      return cellIndex;
+    }
+    /**
+     * Gets the cell's element.
+     * @return the cell's element.
+     */
+    public Element getElement() {
+      return getCellFormatter().getElement(cellIndex, rowIndex);
+    }
+    
+    /**
+     * Get row index.
+     * @return the row index
+     */
+    public int getRowIndex() {
+      return rowIndex;
+    }
+  }
   /**
    * This class contains methods used to format a table's cells.
    */
@@ -123,7 +169,7 @@
      * contents.
      * 
      * @param row the row of the cell whose alignment is to be set
-     * @param column the cell whose alignment is to be set
+     * @param column the column of the cell whose alignment is to be set
      * @param hAlign the cell's new horizontal alignment as specified in
      *          {@link HasHorizontalAlignment}
      * @param vAlign the cell's new vertical alignment as specified in
@@ -140,7 +186,7 @@
      * Sets the height of the specified cell.
      * 
      * @param row the row of the cell whose height is to be set
-     * @param column the cell whose height is to be set
+     * @param column the column of the cell whose height is to be set
      * @param height the cell's new height, in CSS units
      * @throws IndexOutOfBoundsException
      */
@@ -154,7 +200,7 @@
      * Sets the horizontal alignment of the specified cell.
      * 
      * @param row the row of the cell whose alignment is to be set
-     * @param column the cell whose alignment is to be set
+     * @param column the column of the cell whose alignment is to be set
      * @param align the cell's new horizontal alignment as specified in
      *          {@link HasHorizontalAlignment}.
      * @throws IndexOutOfBoundsException
@@ -198,7 +244,7 @@
      * Sets the vertical alignment of the specified cell.
      * 
      * @param row the row of the cell whose alignment is to be set
-     * @param column the cell whose alignment is to be set
+     * @param column the column of the cell whose alignment is to be set
      * @param align the cell's new vertical alignment as specified in
      *          {@link HasVerticalAlignment}.
      * @throws IndexOutOfBoundsException
@@ -217,8 +263,8 @@
      * 
      * @param row the row of the cell whose visibility is to be set
      * @param column the column of the cell whose visibility is to be set
-     * @param visible <code>true</code> to show the cell, <code>false</code>
-     *          to hide it
+     * @param visible <code>true</code> to show the cell, <code>false</code> to
+     *          hide it
      */
     public void setVisible(int row, int column, boolean visible) {
       Element e = ensureElement(row, column);
@@ -229,7 +275,7 @@
      * Sets the width of the specified cell.
      * 
      * @param row the row of the cell whose width is to be set
-     * @param column the cell whose width is to be set
+     * @param column the column of the cell whose width is to be set
      * @param width the cell's new width, in CSS units
      * @throws IndexOutOfBoundsException
      */
@@ -244,7 +290,7 @@
      * Sets whether the specified cell will allow word wrapping of its contents.
      * 
      * @param row the row of the cell whose word-wrap is to be set
-     * @param column the cell whose word-wrap is to be set
+     * @param column the column of the cell whose word-wrap is to be set
      * @param wrap <code>false </code> to disable word wrapping in this cell
      * @throws IndexOutOfBoundsException
      */
@@ -310,11 +356,12 @@
 
     /**
      * Gets the TD element representing the specified cell unsafely (meaning
-     * that it doesn't ensure that the row and column are valid).
+     * that it doesn't ensure that <code>row</code> and <code>column</code>
+     * are valid).
      * 
      * @param row the row of the cell to be retrieved
      * @param column the column of the cell to be retrieved
-     * @return the column's TD element
+     * @return the cell's TD element
      */
     private Element getRawElement(int row, int column) {
       return getCellElement(bodyElem, row, column);
@@ -426,12 +473,12 @@
       }
       return DOM.getChild(columnGroup, col);
     }
-    
+
     /**
-     * Prepare the colgroup tag for the first time, guarenteeing that it
-     * exists and has at least one col tag in it.  This method corrects
-     * a Mozilla issue where the col tag will affect the wrong column if
-     * a col tag doesn't exist when the element is attached to the page.
+     * Prepare the colgroup tag for the first time, guaranteeing that it exists
+     * and has at least one col tag in it. This method corrects a Mozilla issue
+     * where the col tag will affect the wrong column if a col tag doesn't exist
+     * when the element is attached to the page.
      */
     private void prepareColumnGroup() {
       if (columnGroup == null) {
@@ -560,8 +607,8 @@
      * Sets whether this row is visible.
      * 
      * @param row the row whose visibility is to be set
-     * @param visible <code>true</code> to show the row, <code>false</code>
-     *          to hide it
+     * @param visible <code>true</code> to show the row, <code>false</code> to
+     *          hide it
      */
     public void setVisible(int row, boolean visible) {
       Element e = ensureElement(row);
@@ -582,8 +629,8 @@
     }
 
     protected native Element getRow(Element elem, int row)/*-{
-     return elem.rows[row];
-     }-*/;
+      return elem.rows[row];
+    }-*/;
 
     /**
      * Convenience methods to set an attribute on a row.
@@ -753,11 +800,6 @@
    */
   private final Element tableElem;
 
-  /**
-   * Current table listener.
-   */
-  private TableListenerCollection tableListeners;
-
   private WidgetMapper widgetMap = new WidgetMapper();
 
   /**
@@ -770,17 +812,18 @@
     setElement(tableElem);
   }
 
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addDomHandler(handler, ClickEvent.getType());
+  }
+
   /**
    * Adds a listener to the current table.
    * 
    * @param listener listener to add
+   * @deprecated add a click handler instead and use {@link HTMLTable#getCellForEvent(ClickEvent)} to get the cell information
    */
   public void addTableListener(TableListener listener) {
-    if (tableListeners == null) {
-      tableListeners = new TableListenerCollection();
-      sinkEvents(Event.ONCLICK);
-    }
-    tableListeners.add(listener);
+    ListenerWrapper.Table.add(this, listener);
   }
 
   /**
@@ -800,10 +843,11 @@
   }
 
   /**
-   * Clears the given row and column. If it contains a Widget, it will be
-   * removed from the table. If not, its contents will simply be cleared.
+   * Clears the cell at the given row and column. If it contains a Widget, it
+   * will be removed from the table. If not, its contents will simply be
+   * cleared.
    * 
-   * @param row the widget's column
+   * @param row the widget's row
    * @param column the widget's column
    * @return true if a widget was removed
    * @throws IndexOutOfBoundsException
@@ -822,6 +866,26 @@
   public abstract int getCellCount(int row);
 
   /**
+   * Given a click event, return the Cell that was clicked, or null if 
+   * the event did not hit this table.
+   * @param event A click event of indeterminate origin
+   * @return The appropriate cell, or null
+   */
+  public Cell getCellForEvent(ClickEvent event) {
+    Element td = getEventTargetCell(event.getNativeEvent());
+    if (td == null) {
+      return null;
+    }
+
+    Element tr = DOM.getParent(td);
+    Element body = DOM.getParent(tr);
+    int row = DOM.getChildIndex(body, tr);
+    int column = DOM.getChildIndex(tr, td);
+
+    return new Cell(row, column);
+  }
+
+  /**
    * Gets the {@link CellFormatter} associated with this table. Use casting to
    * get subclass-specific functionality
    * 
@@ -942,36 +1006,6 @@
   }
 
   /**
-   * Method to process events generated from the browser.
-   * 
-   * @param event the generated event
-   */
-  @Override
-  public void onBrowserEvent(Event event) {
-    switch (DOM.eventGetType(event)) {
-      case Event.ONCLICK: {
-        if (tableListeners != null) {
-          // Find out which cell was actually clicked.
-          Element td = getEventTargetCell(event);
-          if (td == null) {
-            return;
-          }
-          Element tr = DOM.getParent(td);
-          Element body = DOM.getParent(tr);
-          int row = DOM.getChildIndex(body, tr);
-          int column = DOM.getChildIndex(tr, td);
-          // Fire the event.
-          tableListeners.fireCellClicked(this, row, column);
-        }
-        break;
-      }
-      default: {
-        // Do nothing
-      }
-    }
-  }
-
-  /**
    * Remove the specified widget from the table.
    * 
    * @param widget widget to remove
@@ -1001,10 +1035,9 @@
    * 
    * @param listener listener to remove
    */
+  @Deprecated
   public void removeTableListener(TableListener listener) {
-    if (tableListeners != null) {
-      tableListeners.remove(listener);
-    }
+    ListenerWrapper.Table.remove(this, listener);
   }
 
   /**
@@ -1164,8 +1197,8 @@
    * @return number of columns in the row
    */
   protected native int getDOMCellCount(Element tableBody, int row) /*-{
-   return tableBody.rows[row].cells.length;
-   }-*/;
+    return tableBody.rows[row].cells.length;
+  }-*/;
 
   /**
    * Directly ask the underlying DOM what the cell count on the given row is.
@@ -1187,8 +1220,8 @@
   }
 
   protected native int getDOMRowCount(Element elem) /*-{
-   return elem.rows.length;
-   }-*/;
+    return elem.rows.length;
+  }-*/;
 
   /**
    * Determines the TD associated with the specified event.
@@ -1303,7 +1336,7 @@
   @Override
   protected void onEnsureDebugId(String baseID) {
     super.onEnsureDebugId(baseID);
-    
+
     int rowCount = getRowCount();
     for (int row = 0; row < rowCount; row++) {
       int cellCount = getCellCount(row);
diff --git a/user/src/com/google/gwt/user/client/ui/HasKeyPreview.java b/user/src/com/google/gwt/user/client/ui/HasKeyPreview.java
index 866213f..36849c0 100644
--- a/user/src/com/google/gwt/user/client/ui/HasKeyPreview.java
+++ b/user/src/com/google/gwt/user/client/ui/HasKeyPreview.java
@@ -19,8 +19,10 @@
  * A class that implements this interface receives a preview of keyboard events
  * before they are passed to the focused widget.
  * 
- * @see com.google.gwt.user.client.ui.KeyboardListener
+ * @see com.google.gwt.event.dom.client.KeyCodeEvent
+ * @deprecated This interface hasn't worked in at least two years. Oops.
  */
+@Deprecated
 public interface HasKeyPreview {
 
   /**
@@ -30,9 +32,10 @@
    *          are defined in this interface with the KEYCODE prefix.
    * @param modifiers the modifier keys pressed at when the event occurred. This
    *          value is a combination of the bits defined by
-   *          {@link KeyboardListener#MODIFIER_SHIFT},
-   *          {@link KeyboardListener#MODIFIER_CTRL}, and
-   *          {@link KeyboardListener#MODIFIER_ALT}.
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_SHIFT},
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_CTRL},
+   *          and
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_ALT}.
    */
   boolean onKeyDownPreview(char key, int modifiers);
 
@@ -42,9 +45,10 @@
    * @param key the Unicode character that was generated by the keyboard action.
    * @param modifiers the modifier keys pressed at when the event occurred. This
    *          value is a combination of the bits defined by
-   *          {@link KeyboardListener#MODIFIER_SHIFT},
-   *          {@link KeyboardListener#MODIFIER_CTRL}, and
-   *          {@link KeyboardListener#MODIFIER_ALT}.
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_SHIFT},
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_CTRL},
+   *          and
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_ALT}.
    */
   boolean onKeyPressPreview(char key, int modifiers);
 
@@ -55,9 +59,10 @@
    *          defined in this interface with the KEYCODE prefix.
    * @param modifiers the modifier keys pressed at when the event occurred. This
    *          value is a combination of the bits defined by
-   *          {@link KeyboardListener#MODIFIER_SHIFT},
-   *          {@link KeyboardListener#MODIFIER_CTRL}, and
-   *          {@link KeyboardListener#MODIFIER_ALT}.
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_SHIFT},
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_CTRL},
+   *          and
+   *          {@link com.google.gwt.user.client.ui.KeyboardListener#MODIFIER_ALT}.
    */
   boolean onKeyUpPreview(char key, int modifiers);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/HasValue.java b/user/src/com/google/gwt/user/client/ui/HasValue.java
new file mode 100644
index 0000000..f3240e9
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/HasValue.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+
+/**
+ * An object that implements this interface should be a user input widget, where
+ * the user and programmer can both set and get the object's value.
+ * 
+ * @param <T> the type of value.
+ */
+public interface HasValue<T> extends HasValueChangeHandlers<T> {
+
+  /**
+   * Gets this object's value.
+   * 
+   * @return the object's value
+   */
+  T getValue();
+
+  /**
+   * Sets this object's value without firing any events. Should call setValue(T
+   * value, false).
+   * 
+   * @param value the object's new value
+   */
+  void setValue(T value);
+
+  /**
+   * Sets this object's value. Fires
+   * {@link com.google.gwt.event.logical.shared.ValueChangeEvent} when
+   * fireEvents is true and the new value does not equal the existing value.
+   * 
+   * @param value the object's new value
+   * @param fireEvents fire events if true and value is new
+   */
+  void setValue(T value, boolean fireEvents);
+}
diff --git a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
index 2bc9dfc..3917cd9 100644
--- a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
@@ -225,6 +225,7 @@
       splitPosition = px;
     }
 
+    @Override
     public void setSplitPositionUsingPixels(int px) {
       if (LocaleInfo.getCurrentLocale().isRTL()) {
         final Element splitElem = panel.getSplitElement();
@@ -488,7 +489,7 @@
    *             "1em")
    */
   @Override
-  public final void setSplitPosition(String pos) {
+  public void setSplitPosition(String pos) {
     lastSplitPosition = pos;
     impl.setSplitPosition(pos);
   }
diff --git a/user/src/com/google/gwt/user/client/ui/Hyperlink.java b/user/src/com/google/gwt/user/client/ui/Hyperlink.java
index 297e2de..981ed9e 100644
--- a/user/src/com/google/gwt/user/client/ui/Hyperlink.java
+++ b/user/src/com/google/gwt/user/client/ui/Hyperlink.java
@@ -15,6 +15,10 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
@@ -45,10 +49,10 @@
  * <h3>Example</h3> {@example com.google.gwt.examples.HistoryExample}
  * </p>
  */
-public class Hyperlink extends Widget implements HasHTML, SourcesClickEvents {
+public class Hyperlink extends Widget implements HasHTML, SourcesClickEvents,
+    HasClickHandlers {
 
   private Element anchorElem;
-  private ClickListenerCollection clickListeners;
   private String targetHistoryToken;
 
   /**
@@ -91,11 +95,13 @@
     setTargetHistoryToken(targetHistoryToken);
   }
 
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addHandler(handler, ClickEvent.getType());
+  }
+
+  @Deprecated
   public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new ClickListenerCollection();
-    }
-    clickListeners.add(listener);
+    ListenerWrapper.Click.add(this, listener);
   }
 
   public String getHTML() {
@@ -119,18 +125,15 @@
   @Override
   public void onBrowserEvent(Event event) {
     if (DOM.eventGetType(event) == Event.ONCLICK) {
-      if (clickListeners != null) {
-        clickListeners.fireClick(this);
-      }
+      super.onBrowserEvent(event);
       History.newItem(targetHistoryToken);
       DOM.eventPreventDefault(event);
     }
   }
 
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(this, listener);
   }
 
   public void setHTML(String html) {
diff --git a/user/src/com/google/gwt/user/client/ui/Image.java b/user/src/com/google/gwt/user/client/ui/Image.java
index 8d0e256..09d968c 100644
--- a/user/src/com/google/gwt/user/client/ui/Image.java
+++ b/user/src/com/google/gwt/user/client/ui/Image.java
@@ -19,6 +19,29 @@
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.ImageElement;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.ErrorEvent;
+import com.google.gwt.event.dom.client.ErrorHandler;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.dom.client.HasErrorHandlers;
+import com.google.gwt.event.dom.client.HasLoadHandlers;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelEvent;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Event;
@@ -62,8 +85,9 @@
  * {@example com.google.gwt.examples.ImageExample}
  * </p>
  */
-public class Image extends Widget implements SourcesClickEvents,
-    SourcesLoadEvents, SourcesMouseEvents, SourcesMouseWheelEvents {
+public class Image extends Widget implements SourcesLoadEvents,
+    HasLoadHandlers, HasErrorHandlers, SourcesClickEvents, HasClickHandlers,
+    HasAllMouseHandlers, SourcesMouseEvents {
 
   /**
    * Implementation of behaviors associated with the clipped state of an image.
@@ -86,6 +110,8 @@
       this.height = height;
       this.url = url;
       image.replaceElement(impl.createStructure(url, left, top, width, height));
+      // Todo(ecc) This is wrong, we should not be sinking these here on such a
+      // common widget.After the branch is stable, this should be fixed.
       image.sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.ONMOUSEWHEEL);
       fireSyntheticLoadEvent(image);
     }
@@ -180,9 +206,10 @@
        */
       DeferredCommand.addCommand(new Command() {
         public void execute() {
-          if (image.loadListeners != null) {
-            image.loadListeners.fireLoad(image);
-          }
+          // TODO(ecc) once event triggering is committed, this call should
+          // fire a native load event instead.
+          image.fireEvent(new LoadEvent() {
+          });
         }
       });
     }
@@ -223,12 +250,16 @@
   private static class UnclippedState extends State {
 
     UnclippedState(Element element) {
+      // Todo(ecc) This is wrong, we should not be sinking these here on such a
+      // common widget.After the branch is stable, this should be fixed.
       Event.sinkEvents(element, Event.ONCLICK | Event.MOUSEEVENTS
           | Event.ONLOAD | Event.ONERROR | Event.ONMOUSEWHEEL);
     }
 
     UnclippedState(Image image) {
       image.replaceElement(Document.get().createImageElement());
+      // Todo(ecc) This is wrong, we should not be sinking these here on such a
+      // common widget.After the branch is stable, this should be fixed.
       image.sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS | Event.ONLOAD
           | Event.ONERROR | Event.ONMOUSEWHEEL);
     }
@@ -329,11 +360,6 @@
     return image;
   }
 
-  private ClickListenerCollection clickListeners;
-  private LoadListenerCollection loadListeners;
-  private MouseListenerCollection mouseListeners;
-  private MouseWheelListenerCollection mouseWheelListeners;
-
   private State state;
 
   /**
@@ -389,32 +415,60 @@
     setElement(element);
   }
 
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addHandler(handler, ClickEvent.getType());
+  }
+
+  @Deprecated
   public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new ClickListenerCollection();
-    }
-    clickListeners.add(listener);
+    ListenerWrapper.Click.add(this, listener);
   }
 
+  public HandlerRegistration addErrorHandler(ErrorHandler handler) {
+    return super.addHandler(handler, ErrorEvent.getType());
+  }
+
+  public HandlerRegistration addLoadHandler(LoadHandler handler) {
+    return super.addHandler(handler, LoadEvent.getType());
+  }
+
+  @Deprecated
   public void addLoadListener(LoadListener listener) {
-    if (loadListeners == null) {
-      loadListeners = new LoadListenerCollection();
-    }
-    loadListeners.add(listener);
+    ListenerWrapper.Load.add(this, listener);
   }
 
+  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+    return addDomHandler(handler, MouseDownEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseListener(MouseListener listener) {
-    if (mouseListeners == null) {
-      mouseListeners = new MouseListenerCollection();
-    }
-    mouseListeners.add(listener);
+    ListenerWrapper.Mouse.add(this, listener);
   }
 
+  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+    return addDomHandler(handler, MouseMoveEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+    return addDomHandler(handler, MouseOutEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+    return addDomHandler(handler, MouseOverEvent.getType());
+  }
+
+  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+    return addDomHandler(handler, MouseUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+    return addDomHandler(handler, MouseWheelEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners == null) {
-      mouseWheelListeners = new MouseWheelListenerCollection();
-    }
-    mouseWheelListeners.add(listener);
+    ListenerWrapper.MouseWheel.add(this, listener);
   }
 
   /**
@@ -476,67 +530,24 @@
     return state.getWidth(this);
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    switch (event.getTypeInt()) {
-      case Event.ONCLICK: {
-        if (clickListeners != null) {
-          clickListeners.fireClick(this);
-        }
-        break;
-      }
-      case Event.ONMOUSEDOWN:
-      case Event.ONMOUSEUP:
-      case Event.ONMOUSEMOVE:
-      case Event.ONMOUSEOVER:
-      case Event.ONMOUSEOUT: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-      }
-      case Event.ONMOUSEWHEEL:
-        if (mouseWheelListeners != null) {
-          mouseWheelListeners.fireMouseWheelEvent(this, event);
-        }
-        break;
-      case Event.ONLOAD: {
-        if (loadListeners != null) {
-          loadListeners.fireLoad(this);
-        }
-        break;
-      }
-      case Event.ONERROR: {
-        if (loadListeners != null) {
-          loadListeners.fireError(this);
-        }
-        break;
-      }
-    }
-  }
-
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(this, listener);
   }
 
+  @Deprecated
   public void removeLoadListener(LoadListener listener) {
-    if (loadListeners != null) {
-      loadListeners.remove(listener);
-    }
+    ListenerWrapper.Load.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseListener(MouseListener listener) {
-    if (mouseListeners != null) {
-      mouseListeners.remove(listener);
-    }
+    ListenerWrapper.Mouse.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners != null) {
-      mouseWheelListeners.remove(listener);
-    }
+    ListenerWrapper.MouseWheel.remove(this, listener);
   }
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/KeyboardListener.java b/user/src/com/google/gwt/user/client/ui/KeyboardListener.java
index 33a3b6b..2680f96 100644
--- a/user/src/com/google/gwt/user/client/ui/KeyboardListener.java
+++ b/user/src/com/google/gwt/user/client/ui/KeyboardListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for keyboard events.
  */
+@Deprecated
 public interface KeyboardListener extends EventListener {
 
   int KEY_ALT = 18;
diff --git a/user/src/com/google/gwt/user/client/ui/KeyboardListenerAdapter.java b/user/src/com/google/gwt/user/client/ui/KeyboardListenerAdapter.java
index 4557b3d..1a2d6b1 100644
--- a/user/src/com/google/gwt/user/client/ui/KeyboardListenerAdapter.java
+++ b/user/src/com/google/gwt/user/client/ui/KeyboardListenerAdapter.java
@@ -19,6 +19,7 @@
  * An adapter to simplify keyboard event listeners that do not need all events
  * defined on the KeyboardListener interface.
  */
+@Deprecated
 public class KeyboardListenerAdapter implements KeyboardListener {
 
   public void onKeyDown(Widget sender, char keyCode, int modifiers) {
diff --git a/user/src/com/google/gwt/user/client/ui/KeyboardListenerCollection.java b/user/src/com/google/gwt/user/client/ui/KeyboardListenerCollection.java
index b5edaef..74a1945 100644
--- a/user/src/com/google/gwt/user/client/ui/KeyboardListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/KeyboardListenerCollection.java
@@ -25,6 +25,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.KeyboardListener}.
  */
+@Deprecated
 public class KeyboardListenerCollection extends ArrayList<KeyboardListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/Label.java b/user/src/com/google/gwt/user/client/ui/Label.java
index a58d854..b470fd8 100644
--- a/user/src/com/google/gwt/user/client/ui/Label.java
+++ b/user/src/com/google/gwt/user/client/ui/Label.java
@@ -17,9 +17,25 @@
 
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelEvent;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.BidiUtils;
 import com.google.gwt.i18n.client.HasDirection;
-import com.google.gwt.user.client.Event;
 
 /**
  * A widget that contains arbitrary text, <i>not</i> interpreted as HTML.
@@ -37,9 +53,9 @@
  * {@example com.google.gwt.examples.HTMLExample}
  * </p>
  */
-public class Label extends Widget implements SourcesClickEvents,
-    SourcesMouseEvents, SourcesMouseWheelEvents, HasHorizontalAlignment,
-    HasText, HasWordWrap, HasDirection {
+public class Label extends Widget implements HasHorizontalAlignment, HasText,
+    HasWordWrap, HasDirection, HasClickHandlers, SourcesClickEvents,
+    SourcesMouseEvents, HasAllMouseHandlers {
 
   /**
    * Creates a Label widget that wraps an existing &lt;div&gt; or &lt;span&gt;
@@ -64,10 +80,7 @@
     return label;
   }
 
-  private ClickListenerCollection clickListeners;
   private HorizontalAlignmentConstant horzAlign;
-  private MouseListenerCollection mouseListeners;
-  private MouseWheelListenerCollection mouseWheelListeners;
 
   /**
    * Creates an empty label.
@@ -110,28 +123,47 @@
         || element.getTagName().equalsIgnoreCase("span");
   }
 
+  public HandlerRegistration addClickHandler(ClickHandler handler) {
+    return addDomHandler(handler, ClickEvent.getType());
+  }
+
+  @Deprecated
   public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new ClickListenerCollection();
-      sinkEvents(Event.ONCLICK);
-    }
-    clickListeners.add(listener);
+    ListenerWrapper.Click.add(this, listener);
   }
 
+  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+    return addDomHandler(handler, MouseDownEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseListener(MouseListener listener) {
-    if (mouseListeners == null) {
-      mouseListeners = new MouseListenerCollection();
-      sinkEvents(Event.MOUSEEVENTS);
-    }
-    mouseListeners.add(listener);
+    ListenerWrapper.Mouse.add(this, listener);
   }
 
+  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+    return addDomHandler(handler, MouseMoveEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+    return addDomHandler(handler, MouseOutEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+    return addDomHandler(handler, MouseOverEvent.getType());
+  }
+
+  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+    return addDomHandler(handler, MouseUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+    return addDomHandler(handler, MouseWheelEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners == null) {
-      mouseWheelListeners = new MouseWheelListenerCollection();
-      sinkEvents(Event.ONMOUSEWHEEL);
-    }
-    mouseWheelListeners.add(listener);
+    ListenerWrapper.MouseWheel.add(this, listener);
   }
 
   public Direction getDirection() {
@@ -150,49 +182,19 @@
     return !getElement().getStyle().getProperty("whiteSpace").equals("nowrap");
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    switch (event.getTypeInt()) {
-      case Event.ONCLICK:
-        if (clickListeners != null) {
-          clickListeners.fireClick(this);
-        }
-        break;
-
-      case Event.ONMOUSEDOWN:
-      case Event.ONMOUSEUP:
-      case Event.ONMOUSEMOVE:
-      case Event.ONMOUSEOVER:
-      case Event.ONMOUSEOUT:
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-
-      case Event.ONMOUSEWHEEL:
-        if (mouseWheelListeners != null) {
-          mouseWheelListeners.fireMouseWheelEvent(this, event);
-        }
-        break;
-    }
-  }
-
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseListener(MouseListener listener) {
-    if (mouseListeners != null) {
-      mouseListeners.remove(listener);
-    }
+    ListenerWrapper.Mouse.remove(this, listener);
   }
 
+  @Deprecated
   public void removeMouseWheelListener(MouseWheelListener listener) {
-    if (mouseWheelListeners != null) {
-      mouseWheelListeners.remove(listener);
-    }
+    ListenerWrapper.MouseWheel.remove(this, listener);
   }
 
   public void setDirection(Direction direction) {
diff --git a/user/src/com/google/gwt/user/client/ui/ListBox.java b/user/src/com/google/gwt/user/client/ui/ListBox.java
index ed82a9b..9a10f59 100644
--- a/user/src/com/google/gwt/user/client/ui/ListBox.java
+++ b/user/src/com/google/gwt/user/client/ui/ListBox.java
@@ -19,7 +19,10 @@
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.OptionElement;
 import com.google.gwt.dom.client.SelectElement;
-import com.google.gwt.user.client.Event;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
 
 /**
  * A widget that presents a list of choices to the user, either as a list box or
@@ -40,7 +43,7 @@
  * </p>
  */
 public class ListBox extends FocusWidget implements SourcesChangeEvents,
-    HasName {
+    HasChangeHandlers, HasName {
 
   private static final int INSERT_AT_END = -1;
 
@@ -52,6 +55,7 @@
    * {@link RootPanel#detachNow(Widget)}.
    * 
    * @param element the element to be wrapped
+   * @return list box
    */
   public static ListBox wrap(Element element) {
     // Assert that the element is attached.
@@ -66,8 +70,6 @@
     return listBox;
   }
 
-  private ChangeListenerCollection changeListeners;
-
   /**
    * Creates an empty list box in single selection mode.
    */
@@ -97,12 +99,13 @@
     SelectElement.as(element);
   }
 
+  public HandlerRegistration addChangeHandler(ChangeHandler handler) {
+    return addDomHandler(handler, ChangeEvent.getType());
+  }
+
+  @Deprecated
   public void addChangeListener(ChangeListener listener) {
-    if (changeListeners == null) {
-      changeListeners = new ChangeListenerCollection();
-      sinkEvents(Event.ONCHANGE);
-    }
-    changeListeners.add(listener);
+    addChangeHandler(new ListenerWrapper.Change(listener));
   }
 
   /**
@@ -210,9 +213,8 @@
 
   /**
    * Inserts an item into the list box, specifying an initial value for the
-   * item. If the index is less than zero, or greater than or equal to
-   * the length of the list, then the item will be appended to the end of
-   * the list.
+   * item. If the index is less than zero, or greater than or equal to the
+   * length of the list, then the item will be appended to the end of the list.
    * 
    * @param item the text of the item to be inserted
    * @param value the item's value, to be submitted if it is part of a
@@ -254,21 +256,9 @@
     return getSelectElement().isMultiple();
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    if (event.getTypeInt() == Event.ONCHANGE) {
-      if (changeListeners != null) {
-        changeListeners.fireChange(this);
-      }
-    } else {
-      super.onBrowserEvent(event);
-    }
-  }
-
+  @Deprecated
   public void removeChangeListener(ChangeListener listener) {
-    if (changeListeners != null) {
-      changeListeners.remove(listener);
-    }
+    ListenerWrapper.Change.remove(this, listener);
   }
 
   /**
@@ -287,7 +277,7 @@
    * 
    * <p>
    * Note that setting the selection programmatically does <em>not</em> cause
-   * the {@link ChangeListener#onChange(Widget)} event to be fired.
+   * the {@link ChangeHandler#onChange(ChangeEvent)} event to be fired.
    * </p>
    * 
    * @param index the index of the item to be selected or unselected
@@ -334,13 +324,13 @@
   /**
    * Sets the currently selected index.
    * 
-   * After calling this method, only the specified item in the list will
-   * remain selected.  For a ListBox with multiple selection enabled, see
+   * After calling this method, only the specified item in the list will remain
+   * selected. For a ListBox with multiple selection enabled, see
    * {@link #setItemSelected(int, boolean)} to select multiple items at a time.
    * 
    * <p>
    * Note that setting the selected index programmatically does <em>not</em>
-   * cause the {@link ChangeListener#onChange(Widget)} event to be fired.
+   * cause the {@link ChangeHandler#onChange(ChangeEvent)} event to be fired.
    * </p>
    * 
    * @param index the index of the item to be selected
@@ -359,7 +349,7 @@
    * @throws IndexOutOfBoundsException if the index is out of range
    */
   public void setValue(int index, String value) {
-    checkIndex(index);   
+    checkIndex(index);
     getSelectElement().getOptions().getItem(index).setValue(value);
   }
 
@@ -388,7 +378,8 @@
     // Set the id of each option
     int numItems = getItemCount();
     for (int i = 0; i < numItems; i++) {
-      ensureDebugId(getSelectElement().getOptions().getItem(i), baseID, "item" + i);
+      ensureDebugId(getSelectElement().getOptions().getItem(i), baseID, "item"
+          + i);
     }
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
new file mode 100644
index 0000000..1ea7741
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/ListenerWrapper.java
@@ -0,0 +1,548 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.user.client.ui;

+

+import com.google.gwt.dom.client.Element;

+import com.google.gwt.event.dom.client.BlurEvent;

+import com.google.gwt.event.dom.client.BlurHandler;

+import com.google.gwt.event.dom.client.ChangeEvent;

+import com.google.gwt.event.dom.client.ChangeHandler;

+import com.google.gwt.event.dom.client.ClickEvent;

+import com.google.gwt.event.dom.client.ClickHandler;

+import com.google.gwt.event.dom.client.ErrorEvent;

+import com.google.gwt.event.dom.client.ErrorHandler;

+import com.google.gwt.event.dom.client.FocusEvent;

+import com.google.gwt.event.dom.client.FocusHandler;

+import com.google.gwt.event.dom.client.HandlesAllFocusEvents;

+import com.google.gwt.event.dom.client.HandlesAllKeyEvents;

+import com.google.gwt.event.dom.client.HasAllFocusHandlers;

+import com.google.gwt.event.dom.client.HasAllKeyHandlers;

+import com.google.gwt.event.dom.client.HasChangeHandlers;

+import com.google.gwt.event.dom.client.HasClickHandlers;

+import com.google.gwt.event.dom.client.HasLoadHandlers;

+import com.google.gwt.event.dom.client.HasMouseDownHandlers;

+import com.google.gwt.event.dom.client.HasMouseMoveHandlers;

+import com.google.gwt.event.dom.client.HasMouseOutHandlers;

+import com.google.gwt.event.dom.client.HasMouseOverHandlers;

+import com.google.gwt.event.dom.client.HasMouseUpHandlers;

+import com.google.gwt.event.dom.client.HasMouseWheelHandlers;

+import com.google.gwt.event.dom.client.HasScrollHandlers;

+import com.google.gwt.event.dom.client.KeyDownEvent;

+import com.google.gwt.event.dom.client.KeyDownHandler;

+import com.google.gwt.event.dom.client.KeyPressEvent;

+import com.google.gwt.event.dom.client.KeyPressHandler;

+import com.google.gwt.event.dom.client.KeyUpEvent;

+import com.google.gwt.event.dom.client.KeyUpHandler;

+import com.google.gwt.event.dom.client.LoadEvent;

+import com.google.gwt.event.dom.client.LoadHandler;

+import com.google.gwt.event.dom.client.MouseDownEvent;

+import com.google.gwt.event.dom.client.MouseDownHandler;

+import com.google.gwt.event.dom.client.MouseMoveEvent;

+import com.google.gwt.event.dom.client.MouseMoveHandler;

+import com.google.gwt.event.dom.client.MouseOutEvent;

+import com.google.gwt.event.dom.client.MouseOutHandler;

+import com.google.gwt.event.dom.client.MouseOverEvent;

+import com.google.gwt.event.dom.client.MouseOverHandler;

+import com.google.gwt.event.dom.client.MouseUpEvent;

+import com.google.gwt.event.dom.client.MouseUpHandler;

+import com.google.gwt.event.dom.client.MouseWheelEvent;

+import com.google.gwt.event.dom.client.MouseWheelHandler;

+import com.google.gwt.event.dom.client.ScrollEvent;

+import com.google.gwt.event.dom.client.ScrollHandler;

+import com.google.gwt.event.logical.shared.BeforeSelectionEvent;

+import com.google.gwt.event.logical.shared.BeforeSelectionHandler;

+import com.google.gwt.event.logical.shared.CloseEvent;

+import com.google.gwt.event.logical.shared.CloseHandler;

+import com.google.gwt.event.logical.shared.HasCloseHandlers;

+import com.google.gwt.event.logical.shared.OpenEvent;

+import com.google.gwt.event.logical.shared.OpenHandler;

+import com.google.gwt.event.logical.shared.SelectionEvent;

+import com.google.gwt.event.logical.shared.SelectionHandler;

+import com.google.gwt.event.logical.shared.ValueChangeEvent;

+import com.google.gwt.event.shared.EventHandler;

+import com.google.gwt.event.shared.GwtEvent;

+import com.google.gwt.event.shared.HandlerManager;

+import com.google.gwt.event.shared.GwtEvent.Type;

+

+import java.util.EventListener;

+

+/**

+ * Legacy listener support hierarchy for

+ * <code>com.google.gwt.user.client.ui</code>. Gathers the bulk of the legacy

+ * glue code in one place, for easy deletion when Listener methods are deleted.

+ * 

+ * @see com.google.gwt.user.client.L

+ * @param <T> listener type

+ */

+@Deprecated

+abstract class ListenerWrapper<T> implements EventHandler {

+

+  public static class Change extends ListenerWrapper<ChangeListener> implements ChangeHandler {

+    @Deprecated

+    public static void add(HasChangeHandlers source, ChangeListener listener) {

+      source.addChangeHandler(new Change(listener));

+    }

+

+    public static void remove(Widget eventSource, ChangeListener listener) {

+      baseRemove(eventSource, listener, ChangeEvent.getType());

+    }

+

+    protected Change(ChangeListener listener) {

+      super(listener);

+    }

+

+    public void onChange(ChangeEvent event) {

+      listener.onChange(source(event));

+    }

+  }

+

+  public static class Click extends ListenerWrapper<ClickListener> implements ClickHandler {

+    @Deprecated

+    public static Click add(HasClickHandlers source, ClickListener listener) {

+      Click rtn = new Click(listener);

+      source.addClickHandler(rtn);

+      return rtn;

+    }

+

+    public static void remove(Widget eventSource, ClickListener listener) {

+      baseRemove(eventSource, listener, ClickEvent.getType());

+    }

+

+    private Click(ClickListener listener) {

+      super(listener);

+    }

+

+    public void onClick(ClickEvent event) {

+      listener.onClick(source(event));

+    }

+  }

+

+  public static class Disclosure extends ListenerWrapper<DisclosureHandler> implements

+      CloseHandler<DisclosurePanel>, OpenHandler<DisclosurePanel> {

+

+    public static void add(DisclosurePanel source, DisclosureHandler listener) {

+      Disclosure handlers = new Disclosure(listener);

+      source.addOpenHandler(handlers);

+      source.addCloseHandler(handlers);

+    }

+

+    public static void remove(Widget eventSource, DisclosureHandler listener) {

+      baseRemove(eventSource, listener, CloseEvent.getType(),

+          OpenEvent.getType());

+    }

+

+    private Disclosure(DisclosureHandler listener) {

+      super(listener);

+    }

+

+    public void onClose(CloseEvent<DisclosurePanel> event) {

+      listener.onClose(new DisclosureEvent((DisclosurePanel) event.getSource()));

+    }

+

+    public void onOpen(OpenEvent<DisclosurePanel> event) {

+      listener.onOpen(new DisclosureEvent((DisclosurePanel) event.getSource()));

+    }

+  }

+

+  /*

+   * Handler wrapper for {@link FocusListener}.

+   */

+  public static class Focus extends ListenerWrapper<FocusListener> implements FocusHandler,

+      BlurHandler {

+

+    public static <EventSourceType extends Widget & HasAllFocusHandlers> Focus add(

+        EventSourceType source, FocusListener listener) {

+      Focus rtn = new Focus(listener);

+      HandlesAllFocusEvents.handle(source, rtn);

+      return rtn;

+    }

+

+    public static void remove(Widget eventSource, FocusListener listener) {

+      baseRemove(eventSource, listener, LoadEvent.getType(),

+          ErrorEvent.getType());

+    }

+

+    private Focus(FocusListener listener) {

+      super(listener);

+    }

+

+    public void onBlur(BlurEvent event) {

+      listener.onLostFocus(source(event));

+    }

+

+    public void onFocus(FocusEvent event) {

+      listener.onFocus(source(event));

+    }

+  }

+

+  public static class Form extends ListenerWrapper<FormHandler> implements

+      FormPanel.SubmitHandler, FormPanel.SubmitCompleteHandler {

+

+    public static void add(FormPanel source, FormHandler listener) {

+      Form handlers = new Form(listener);

+      source.addSubmitHandler(handlers);

+      source.addSubmitCompleteHandler(handlers);

+    }

+

+    public static void remove(Widget eventSource, FormHandler listener) {

+      baseRemove(eventSource, listener, FormPanel.SubmitEvent.getType(),

+          FormPanel.SubmitCompleteEvent.getType());

+    }

+

+    private Form(FormHandler listener) {

+      super(listener);

+    }

+

+    public void onSubmit(FormPanel.SubmitEvent event) {

+      FormSubmitEvent fse = new FormSubmitEvent((FormPanel) event.getSource());

+      listener.onSubmit(fse);

+      if (fse.isSetCancelledCalled()) {

+        event.setCanceled(fse.isCancelled());

+      }

+    }

+

+    public void onSubmitComplete(FormPanel.SubmitCompleteEvent event) {

+      listener.onSubmitComplete(new FormSubmitCompleteEvent(

+          (FormPanel) event.getSource(), event.getResults()));

+    }

+  }

+

+  public static class Load extends ListenerWrapper<LoadListener> implements LoadHandler,

+      ErrorHandler {

+

+    public static void add(HasLoadHandlers source, LoadListener listener) {

+      source.addLoadHandler(new Load(listener));

+    }

+

+    public static void remove(Widget eventSource, LoadListener listener) {

+      baseRemove(eventSource, listener, LoadEvent.getType(),

+          ErrorEvent.getType());

+    }

+

+    private Load(LoadListener listener) {

+      super(listener);

+    }

+

+    public void onError(ErrorEvent event) {

+      listener.onError(source(event));

+    }

+

+    public void onLoad(LoadEvent event) {

+      listener.onLoad(source(event));

+    }

+  }

+

+  public static class Mouse extends ListenerWrapper<MouseListener> implements

+      MouseDownHandler, MouseUpHandler, MouseOutHandler, MouseOverHandler,

+      MouseMoveHandler {

+

+    public static <EventSourceType extends Widget & HasMouseDownHandlers & HasMouseUpHandlers & HasMouseOutHandlers & HasMouseOverHandlers & HasMouseMoveHandlers> void add(

+        EventSourceType source, MouseListener listener) {

+      Mouse handlers = new Mouse(listener);

+      source.addMouseDownHandler(handlers);

+      source.addMouseUpHandler(handlers);

+      source.addMouseOutHandler(handlers);

+      source.addMouseOverHandler(handlers);

+      source.addMouseMoveHandler(handlers);

+    }

+

+    public static void remove(Widget eventSource, MouseListener listener) {

+      baseRemove(eventSource, listener, MouseDownEvent.getType(),

+          MouseUpEvent.getType(), MouseOverEvent.getType(),

+          MouseOutEvent.getType());

+    }

+

+    private Mouse(MouseListener listener) {

+      super(listener);

+    }

+

+    public void onMouseDown(MouseDownEvent event) {

+      listener.onMouseDown(source(event), event.getClientX(),

+          event.getClientY());

+    }

+

+    public void onMouseMove(MouseMoveEvent event) {

+      listener.onMouseMove(source(event), event.getClientX(),

+          event.getClientY());

+    }

+

+    public void onMouseOut(MouseOutEvent event) {

+      listener.onMouseLeave(source(event));

+    }

+

+    public void onMouseOver(MouseOverEvent event) {

+      listener.onMouseEnter(source(event));

+    }

+

+    public void onMouseUp(MouseUpEvent event) {

+      listener.onMouseUp(source(event), event.getClientX(), event.getClientY());

+    }

+  }

+  public static class MouseWheel extends ListenerWrapper<MouseWheelListener> implements

+      MouseWheelHandler {

+    public static void add(HasMouseWheelHandlers source, MouseWheelListener listener) {

+      source.addMouseWheelHandler(new MouseWheel(listener));

+    }

+

+    public static void remove(Widget eventSource, MouseWheelListener listener) {

+      baseRemove(eventSource, listener, MouseWheelEvent.getType());

+    }

+

+    private MouseWheel(MouseWheelListener listener) {

+      super(listener);

+    }

+

+    public void onMouseWheel(MouseWheelEvent event) {

+      listener.onMouseWheel(source(event), new MouseWheelVelocity(

+          event.getNativeEvent()));

+    }

+  }

+

+  public static class Popup extends ListenerWrapper<PopupListener> implements

+      CloseHandler<PopupPanel> {

+

+    public static void add(HasCloseHandlers<PopupPanel> source, PopupListener listener) {

+      source.addCloseHandler(new Popup(listener));

+    }

+

+    public static void remove(Widget eventSource, PopupListener listener) {

+      baseRemove(eventSource, listener, CloseEvent.getType());

+    }

+

+    private Popup(PopupListener listener) {

+      super(listener);

+    }

+

+    public void onClose(CloseEvent<PopupPanel> event) {

+      listener.onPopupClosed((PopupPanel) event.getSource(),

+          event.isAutoClosed());

+    }

+  }

+

+  public static class Scroll extends ListenerWrapper<ScrollListener> implements ScrollHandler {

+

+    public static void add(HasScrollHandlers source, ScrollListener listener) {

+      source.addScrollHandler(new Scroll(listener));

+    }

+

+    public static void remove(Widget eventSource, ScrollListener listener) {

+      baseRemove(eventSource, listener, ScrollEvent.getType(),

+          ErrorEvent.getType());

+    }

+

+    private Scroll(ScrollListener listener) {

+      super(listener);

+    }

+

+    public void onScroll(ScrollEvent event) {

+      Widget source = source(event);

+      Element elem = source.getElement();

+      listener.onScroll(source(event), elem.getScrollLeft(),

+          elem.getScrollTop());

+    }

+  }

+

+  public static class Suggestion extends ListenerWrapper<SuggestionHandler> implements

+      SelectionHandler<SuggestOracle.Suggestion> {

+    @Deprecated

+    public static void add(SuggestBox source, SuggestionHandler listener) {

+      source.addSelectionHandler(new Suggestion(listener));

+    }

+

+    public static void remove(Widget eventSource, SuggestionHandler listener) {

+      baseRemove(eventSource, listener, SelectionEvent.getType());

+    }

+

+    private Suggestion(SuggestionHandler listener) {

+      super(listener);

+    }

+

+    public void onSelection(SelectionEvent<SuggestOracle.Suggestion> event) {

+      listener.onSuggestionSelected(new SuggestionEvent(

+          (SuggestBox) event.getSource(), event.getSelectedItem()));

+    }

+  }

+

+  public static class Tab extends ListenerWrapper<TabListener> implements

+      SelectionHandler<Integer>, BeforeSelectionHandler<Integer> {

+    @Deprecated

+    public static void add(TabBar source, TabListener listener) {

+      Tab t = new Tab(listener);

+      source.addBeforeSelectionHandler(t);

+      source.addSelectionHandler(t);

+    }

+

+    public static void add(TabPanel source, TabListener listener) {

+      Tab t = new Tab(listener);

+      source.addBeforeSelectionHandler(t);

+      source.addSelectionHandler(t);

+    }

+

+    public static void remove(Widget eventSource, TabListener listener) {

+      baseRemove(eventSource, listener, SelectionEvent.getType(),

+          BeforeSelectionEvent.getType());

+    }

+

+    private Tab(TabListener listener) {

+      super(listener);

+    }

+

+    public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {

+      if (!listener.onBeforeTabSelected((SourcesTabEvents) event.getSource(),

+          event.getItem().intValue())) {

+        event.cancel();

+      }

+    }

+

+    public void onSelection(SelectionEvent<Integer> event) {

+      listener.onTabSelected((SourcesTabEvents) event.getSource(),

+          event.getSelectedItem().intValue());

+    }

+  }

+

+  public static class Table extends ListenerWrapper<TableListener> implements

+      ClickHandler {

+    @Deprecated

+    public static void add(HasClickHandlers source, TableListener listener) {

+      source.addClickHandler(new Table(listener));

+    }

+

+    public static void remove(Widget eventSource, TableListener listener) {

+      baseRemove(eventSource, listener, ClickEvent.getType());

+    }

+

+    private Table(TableListener listener) {

+      super(listener);

+    }

+

+    public void onClick(ClickEvent event) {

+      HTMLTable table = (HTMLTable) event.getSource();

+      HTMLTable.Cell cell = table.getCellForEvent(event);

+      listener.onCellClicked(table, cell.getRowIndex(), cell.getCellIndex());

+    }

+  }

+

+  public static class Tree extends ListenerWrapper<TreeListener> implements

+      SelectionHandler<TreeItem>, CloseHandler<TreeItem>, OpenHandler<TreeItem> {

+    @Deprecated

+    public static void add(com.google.gwt.user.client.ui.Tree tree,

+        TreeListener listener) {

+      Tree t = new Tree(listener);

+      tree.addSelectionHandler(t);

+      tree.addCloseHandler(t);

+      tree.addOpenHandler(t);

+    }

+

+    public static void remove(Widget eventSource, TreeListener listener) {

+      baseRemove(eventSource, listener, ValueChangeEvent.getType());

+    }

+

+    private Tree(TreeListener listener) {

+      super(listener);

+    }

+

+    public void onClose(CloseEvent<TreeItem> event) {

+      listener.onTreeItemStateChanged(event.getTarget());

+    }

+

+    public void onOpen(OpenEvent<TreeItem> event) {

+      listener.onTreeItemSelected(event.getTarget());

+    }

+

+    public void onSelection(SelectionEvent<TreeItem> event) {

+      listener.onTreeItemSelected(event.getSelectedItem());

+    }

+  }

+

+  static class Keyboard extends ListenerWrapper<KeyboardListener> implements KeyDownHandler,

+      KeyUpHandler, KeyPressHandler {

+

+    public static <EventSourceType extends Widget & HasAllKeyHandlers> void add(

+        EventSourceType source, KeyboardListener listener) {

+      HandlesAllKeyEvents.addHandlers(source, new Keyboard(listener));

+    }

+

+    public static void remove(Widget eventSource, KeyboardListener listener) {

+      ListenerWrapper.baseRemove(eventSource, listener, KeyDownEvent.getType(),

+          KeyUpEvent.getType(), KeyPressEvent.getType());

+    }

+

+    private Keyboard(KeyboardListener listener) {

+      super(listener);

+    }

+

+    public void onKeyDown(KeyDownEvent event) {

+      listener.onKeyDown(source(event), (char) event.getNativeKeyCode(),

+          KeyboardListenerCollection.getKeyboardModifiers(event.getNativeEvent()));

+    }

+

+    public void onKeyPress(KeyPressEvent event) {

+      listener.onKeyPress(source(event), 

+          (char) event.getNativeEvent().getKeyCode(), 

+          KeyboardListenerCollection.getKeyboardModifiers(event.getNativeEvent()));

+    }

+

+    public void onKeyUp(KeyUpEvent event) {

+      source(event);

+      listener.onKeyUp(source(event), (char) event.getNativeKeyCode(), 

+          KeyboardListenerCollection.getKeyboardModifiers(event.getNativeEvent()));

+    }

+  }

+

+  // This is an internal helper method with the current formulation, we have

+  // lost the info needed to make it safe by this point.

+  @SuppressWarnings("unchecked")

+  static <H extends EventHandler> void baseRemove(Widget eventSource,

+      EventListener listener, Type... keys) {

+    HandlerManager manager = eventSource.getHandlers();

+    if (manager != null) {

+      for (Type<H> key : keys) {

+        int handlerCount = manager.getHandlerCount(key);

+        // We are removing things as we traverse, have to go backward

+        for (int i = handlerCount - 1; i >= 0; i--) {

+          H handler = manager.getHandler(key, i);

+          if (handler instanceof ListenerWrapper && ((ListenerWrapper) handler).listener.equals(listener)) {

+            manager.removeHandler(key, handler);

+          }

+        }

+      }

+    }

+  }

+

+  /**

+   * Listener being wrapped.

+   */

+  protected final T listener;

+

+  private Widget source;

+

+  protected ListenerWrapper(T listener) {

+    this.listener = listener;

+  }

+

+  public void setSource(Widget source) {

+    this.source = source;

+  }

+

+  Widget source(GwtEvent<?> event) {

+    if (source == null) {

+      return (Widget) event.getSource();

+    } else {

+      return source;

+    }

+  }

+}

diff --git a/user/src/com/google/gwt/user/client/ui/LoadListener.java b/user/src/com/google/gwt/user/client/ui/LoadListener.java
index 95f4587..149259c 100644
--- a/user/src/com/google/gwt/user/client/ui/LoadListener.java
+++ b/user/src/com/google/gwt/user/client/ui/LoadListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for 'load' events.
  */
+@Deprecated
 public interface LoadListener extends EventListener {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/LoadListenerCollection.java b/user/src/com/google/gwt/user/client/ui/LoadListenerCollection.java
index 43ef4bd..ffebb8c 100644
--- a/user/src/com/google/gwt/user/client/ui/LoadListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/LoadListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.LoadListener}.
  */
+@Deprecated
 public class LoadListenerCollection extends ArrayList<LoadListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/MenuBar.java b/user/src/com/google/gwt/user/client/ui/MenuBar.java
index bcc74ff..04dc6b3 100644
--- a/user/src/com/google/gwt/user/client/ui/MenuBar.java
+++ b/user/src/com/google/gwt/user/client/ui/MenuBar.java
@@ -16,12 +16,17 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.HasCloseHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.ui.PopupPanel.AnimationType;
 
 import java.util.ArrayList;
@@ -36,44 +41,32 @@
  * <img class='gallery' src='MenuBar.png'/>
  * </p>
  * 
- * <h3>CSS Style Rules</h3>
- * <ul class='css'>
+ * <h3>CSS Style Rules</h3> <ul class='css'>
  * <li>.gwt-MenuBar { the menu bar itself }</li>
- * <li>.gwt-MenuBar-horizontal { dependent style applied to horizontal menu
- * bars }</li>
+ * <li>.gwt-MenuBar-horizontal { dependent style applied to horizontal menu bars }</li>
  * <li>.gwt-MenuBar-vertical { dependent style applied to vertical menu bars }</li>
  * <li>.gwt-MenuBar .gwt-MenuItem { menu items }</li>
  * <li>.gwt-MenuBar .gwt-MenuItem-selected { selected menu items }</li>
- * <li>.gwt-MenuBar .gwt-MenuItemSeparator { section breaks between menu items }
- * </li>
- * <li>.gwt-MenuBar .gwt-MenuItemSeparator .menuSeparatorInner { inner component of
- * section separators } </li>
+ * <li>.gwt-MenuBar .gwt-MenuItemSeparator { section breaks between menu items } </li>
+ * <li>.gwt-MenuBar .gwt-MenuItemSeparator .menuSeparatorInner { inner component of section separators }</li>
  * <li>.gwt-MenuBarPopup .menuPopupTopLeft { the top left cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupTopLeftInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupTopCenter { the top center cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupTopCenterInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupTopCenterInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupTopRight { the top right cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupTopRightInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupTopRightInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupMiddleLeft { the middle left cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupMiddleLeftInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupMiddleLeftInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupMiddleCenter { the middle center cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupMiddleCenterInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupMiddleCenterInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupMiddleRight { the middle right cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupMiddleRightInner { the inner element of the
- * cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupBottomLeft { the bottom left cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupBottomLeftInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupMiddleRightInner { the inner element of the cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupBottomLeft { the bottom left cell }</li> 
+ * <li>.gwt-MenuBarPopup .menuPopupBottomLeftInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupBottomCenter { the bottom center cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupBottomCenterInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupBottomCenterInner { the inner element of the cell }</li>
  * <li>.gwt-MenuBarPopup .menuPopupBottomRight { the bottom right cell }</li>
- * <li>.gwt-MenuBarPopup .menuPopupBottomRightInner { the inner element of the
- * cell }</li>
+ * <li>.gwt-MenuBarPopup .menuPopupBottomRightInner { the inner element of the cell }</li>
  * </ul>
  * 
  * <p>
@@ -81,9 +74,11 @@
  * {@example com.google.gwt.examples.MenuBarExample}
  * </p>
  */
-public class MenuBar extends Widget implements PopupListener, HasAnimation {
-  private static final String STYLENAME_DEFAULT = "gwt-MenuBar";
-
+// Nothing we can do about MenuBar implementing PopupListener until next
+// release.
+@SuppressWarnings("deprecation")
+public class MenuBar extends Widget implements PopupListener, HasAnimation,
+    HasCloseHandlers<PopupPanel> {
   /**
    * An {@link ImageBundle} that provides images for {@link MenuBar}.
    */
@@ -107,15 +102,17 @@
    */
   interface MenuBarImagesRTL extends MenuBarImages {
     /**
-     * An image indicating a {@link MenuItem} has an associated submenu for
-     * a RTL context.
+     * An image indicating a {@link MenuItem} has an associated submenu for a
+     * RTL context.
      * 
      * @return a prototype of this image
      */
     @Resource("menuBarSubMenuIcon_rtl.gif")
-    AbstractImagePrototype menuBarSubMenuIcon();    
+    AbstractImagePrototype menuBarSubMenuIcon();
   }
 
+  private static final String STYLENAME_DEFAULT = "gwt-MenuBar";
+
   /**
    * List of all {@link MenuItem}s and {@link MenuItemSeparator}s.
    */
@@ -145,24 +142,24 @@
 
   /**
    * Creates an empty menu bar.
-   *
+   * 
    * @param vertical <code>true</code> to orient the menu bar vertically
    */
   public MenuBar(boolean vertical) {
     super();
     if (LocaleInfo.getCurrentLocale().isRTL()) {
-      init(vertical, GWT.<MenuBarImagesRTL>create(MenuBarImagesRTL.class));
+      init(vertical, GWT.<MenuBarImagesRTL> create(MenuBarImagesRTL.class));
     } else {
-      init(vertical, GWT.<MenuBarImages>create(MenuBarImages.class));
+      init(vertical, GWT.<MenuBarImages> create(MenuBarImages.class));
     }
   }
 
   /**
-   * Creates an empty menu bar that uses the specified image bundle
-   * for menu images.
-   *
+   * Creates an empty menu bar that uses the specified image bundle for menu
+   * images.
+   * 
    * @param vertical <code>true</code> to orient the menu bar vertically
-   * @param images   a bundle that provides images for this menu
+   * @param images a bundle that provides images for this menu
    */
   public MenuBar(boolean vertical, MenuBarImages images) {
     init(vertical, images);
@@ -171,13 +168,17 @@
   /**
    * Creates an empty horizontal menu bar that uses the specified image bundle
    * for menu images.
-   *
+   * 
    * @param images a bundle that provides images for this menu
    */
   public MenuBar(MenuBarImages images) {
     this(false, images);
   }
 
+  public HandlerRegistration addCloseHandler(CloseHandler<PopupPanel> handler) {
+    return super.addHandler(handler, CloseEvent.getType());
+  }
+
   /**
    * Adds a menu item to the bar.
    * 
@@ -306,7 +307,7 @@
   }
 
   /**
-   * Get the index of a {@link MenuItemSerpator}.
+   * Get the index of a {@link MenuItemSeparator}.
    * 
    * @return the index of the separator, or -1 if it is not contained by this
    *         MenuBar
@@ -359,7 +360,7 @@
    *           range
    */
   public MenuItemSeparator insertSeparator(int beforeIndex) {
-    return insertSeparator(new MenuItemSeparator(), beforeIndex); 
+    return insertSeparator(new MenuItemSeparator(), beforeIndex);
   }
 
   /**
@@ -399,7 +400,7 @@
     MenuItem item = findItem(DOM.eventGetTarget(event));
     switch (DOM.eventGetType(event)) {
       case Event.ONCLICK: {
-        FocusPanel.impl.focus(getElement());  
+        FocusPanel.impl.focus(getElement());
         // Fire an item's command when the user clicks on it.
         if (item != null) {
           doItemAction(item, true);
@@ -429,7 +430,7 @@
       case Event.ONKEYDOWN: {
         int keyCode = DOM.eventGetKeyCode(event);
         switch (keyCode) {
-          case KeyboardListener.KEY_LEFT:
+          case  KeyCodes.KEY_LEFT:
             if (LocaleInfo.getCurrentLocale().isRTL()) {
               moveToNextItem();
             } else {
@@ -437,7 +438,7 @@
             }
             eatEvent(event);
             break;
-          case KeyboardListener.KEY_RIGHT:
+          case KeyCodes.KEY_RIGHT:
             if (LocaleInfo.getCurrentLocale().isRTL()) {
               moveToPrevItem();
             } else {
@@ -445,19 +446,19 @@
             }
             eatEvent(event);
             break;
-          case KeyboardListener.KEY_UP:
+          case KeyCodes.KEY_UP:
             moveUp();
             eatEvent(event);
             break;
-          case KeyboardListener.KEY_DOWN:
+          case KeyCodes.KEY_DOWN:
             moveDown();
             eatEvent(event);
             break;
-          case KeyboardListener.KEY_ESCAPE:
+          case KeyCodes.KEY_ESCAPE:
             closeAllParents();
             eatEvent(event);
             break;
-          case KeyboardListener.KEY_ENTER:
+          case KeyCodes.KEY_ENTER:
             if (!selectFirstItemIfNoneSelected()) {
               doItemAction(selectedItem, true);
               eatEvent(event);
@@ -470,6 +471,12 @@
     } // end switch (DOM.eventGetType(event))
   }
 
+  /**
+   * Closes the menu bar.
+   * 
+   * @deprecated use {@link #addCloseHandler(CloseHandler)} instead.
+   */
+  @Deprecated
   public void onPopupClosed(PopupPanel sender, boolean autoClosed) {
     // If the menu popup was auto-closed, close all of its parents as well.
     if (autoClosed) {
@@ -479,6 +486,7 @@
     // When the menu popup closes, remember that no item is
     // currently showing a popup menu.
     onHide();
+    CloseEvent.fire(MenuBar.this, sender);
     shownChildMenu = null;
     popup = null;
   }
@@ -531,17 +539,16 @@
    * bar. If there are no items in the menu bar, then an empty <code>List</code>
    * object will be returned.
    * 
-   * @return a list containing the <code>MenuItem</code> objects in the menu
-   *         bar
+   * @return a list containing the <code>MenuItem</code> objects in the menu bar
    */
   protected List<MenuItem> getItems() {
     return this.items;
   }
 
   /**
-   * Returns the <code>MenuItem</code> that is currently selected
-   * (highlighted) by the user. If none of the items in the menu are currently
-   * selected, then <code>null</code> will be returned.
+   * Returns the <code>MenuItem</code> that is currently selected (highlighted)
+   * by the user. If none of the items in the menu are currently selected, then
+   * <code>null</code> will be returned.
    * 
    * @return the <code>MenuItem</code> that is currently selected, or
    *         <code>null</code> if no items are currently selected
@@ -591,8 +598,9 @@
    * associated with it, and 'fireCommand' is true, then the command will be
    * fired. Popups associated with other items will be hidden.
    * 
-   * @param item the item whose popup is to be shown. @param fireCommand <code>true</code>
-   * if the item's command should be fired, <code>false</code> otherwise.
+   * @param item the item whose popup is to be shown. @param fireCommand
+   * <code>true</code> if the item's command should be fired, <code>false</code>
+   * otherwise.
    */
   void doItemAction(final MenuItem item, boolean fireCommand) {
     // Ensure that the item is selected.
@@ -603,11 +611,11 @@
       if (fireCommand && item.getCommand() != null) {
         // Close this menu and all of its parents.
         closeAllParents();
-  
+
         // Fire the item's command.
         Command cmd = item.getCommand();
         DeferredCommand.addCommand(cmd);
-        
+
         // hide any open submenus of this item
         if (shownChildMenu != null) {
           shownChildMenu.onHide();
@@ -694,8 +702,9 @@
         }
       }
 
-      Accessibility.setState(getElement(), Accessibility.STATE_ACTIVEDESCENDANT,
-          DOM.getElementAttribute(item.getElement(), "id"));
+      Accessibility.setState(getElement(),
+          Accessibility.STATE_ACTIVEDESCENDANT, DOM.getElementAttribute(
+              item.getElement(), "id"));
     }
 
     selectedItem = item;
@@ -804,10 +813,10 @@
       return DOM.getChild(body, 0);
     }
   }
-  
-  private void init(boolean vertical, MenuBarImages images) {    
+
+  private void init(boolean vertical, MenuBarImages images) {
     this.images = images;
-    
+
     Element table = DOM.createTable();
     body = DOM.createTBody();
     DOM.appendChild(table, body);
@@ -826,7 +835,7 @@
     Accessibility.setRole(getElement(), Accessibility.ROLE_MENUBAR);
 
     sinkEvents(Event.ONCLICK | Event.ONMOUSEOVER | Event.ONMOUSEOUT
-        | Event.ONFOCUS |  Event.ONKEYDOWN);
+        | Event.ONFOCUS | Event.ONKEYDOWN);
 
     setStyleName(STYLENAME_DEFAULT);
     if (vertical) {
@@ -839,9 +848,9 @@
     DOM.setStyleAttribute(getElement(), "outline", "0px");
 
     // Hide focus outline in IE 6/7
-    DOM.setElementAttribute(getElement(), "hideFocus", "true");   
+    DOM.setElementAttribute(getElement(), "hideFocus", "true");
   }
-  
+
   private void moveDown() {
     if (selectFirstItemIfNoneSelected()) {
       return;
@@ -850,7 +859,7 @@
     if (vertical) {
       selectNextItem();
     } else {
-      if (selectedItem.getSubMenu() != null 
+      if (selectedItem.getSubMenu() != null
           && !selectedItem.getSubMenu().getItems().isEmpty()
           && (shownChildMenu == null || shownChildMenu.getSelectedItem() == null)) {
         if (shownChildMenu == null) {
@@ -866,7 +875,7 @@
       }
     }
   }
-  
+
   private void moveToNextItem() {
     if (selectFirstItemIfNoneSelected()) {
       return;
@@ -875,7 +884,7 @@
     if (!vertical) {
       selectNextItem();
     } else {
-      if (selectedItem.getSubMenu() != null 
+      if (selectedItem.getSubMenu() != null
           && !selectedItem.getSubMenu().getItems().isEmpty()
           && (shownChildMenu == null || shownChildMenu.getSelectedItem() == null)) {
         if (shownChildMenu == null) {
@@ -907,7 +916,7 @@
       }
     }
   }
-  
+
   private void moveUp() {
     if (selectFirstItemIfNoneSelected()) {
       return;
@@ -942,6 +951,7 @@
     selectItem(null);
   }
 
+  @SuppressWarnings("deprecation")
   private void openPopup(final MenuItem item) {
     // Create a new popup for this item, and position it next to
     // the item (below if this is a horizontal menu bar, to the
@@ -951,7 +961,7 @@
         setWidget(item.getSubMenu());
         item.getSubMenu().onShow();
       }
-  
+
       @Override
       public boolean onEventPreview(Event event) {
         // Hook the popup panel's event preview. We use this to keep it from
@@ -982,33 +992,36 @@
       popup.addStyleName(primaryStyleName + "Popup");
     }
     popup.addPopupListener(this);
-  
+
     shownChildMenu = item.getSubMenu();
     item.getSubMenu().parentMenu = this;
-  
+
     // Show the popup, ensuring that the menubar's event preview remains on top
     // of the popup's.
     popup.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
-          
+
       public void setPosition(int offsetWidth, int offsetHeight) {
-        
+
         // depending on the bidi direction position a menu on the left or right
         // of its base item
-        if (LocaleInfo.getCurrentLocale().isRTL()) {                                   
+        if (LocaleInfo.getCurrentLocale().isRTL()) {
           if (vertical) {
-            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth + 1,
-                item.getAbsoluteTop());
+            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() - offsetWidth
+                + 1, item.getAbsoluteTop());
           } else {
-            popup.setPopupPosition(item.getAbsoluteLeft() + item.getOffsetWidth() - offsetWidth,
-                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight() - 1);
+            popup.setPopupPosition(item.getAbsoluteLeft()
+                + item.getOffsetWidth() - offsetWidth,
+                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
+                    - 1);
           }
         } else {
           if (vertical) {
-            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft() + MenuBar.this.getOffsetWidth() - 1,
-                item.getAbsoluteTop());
+            popup.setPopupPosition(MenuBar.this.getAbsoluteLeft()
+                + MenuBar.this.getOffsetWidth() - 1, item.getAbsoluteTop());
           } else {
-            popup.setPopupPosition(item.getAbsoluteLeft(), 
-                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight() - 1);
+            popup.setPopupPosition(item.getAbsoluteLeft(),
+                MenuBar.this.getAbsoluteTop() + MenuBar.this.getOffsetHeight()
+                    - 1);
           }
         }
       }
@@ -1035,11 +1048,11 @@
   }
 
   /**
-   * Selects the first item in the menu if no items are currently selected. This method
-   * assumes that the menu has at least 1 item.
-   *
-   * @return true if no item was previously selected and the first item in the list was selected,
-   *         false otherwise
+   * Selects the first item in the menu if no items are currently selected. This
+   * method assumes that the menu has at least 1 item.
+   * 
+   * @return true if no item was previously selected and the first item in the
+   *         list was selected, false otherwise
    */
   private boolean selectFirstItemIfNoneSelected() {
     if (selectedItem == null) {
@@ -1057,7 +1070,8 @@
     }
 
     int index = items.indexOf(selectedItem);
-    // We know that selectedItem is set to an item that is contained in the items collection.
+    // We know that selectedItem is set to an item that is contained in the
+    // items collection.
     // Therefore, we know that index can never be -1.
     assert (index != -1);
 
@@ -1081,7 +1095,8 @@
     }
 
     int index = items.indexOf(selectedItem);
-    // We know that selectedItem is set to an item that is contained in the items collection.
+    // We know that selectedItem is set to an item that is contained in the
+    // items collection.
     // Therefore, we know that index can never be -1.
     assert (index != -1);
 
@@ -1092,7 +1107,7 @@
     } else { // we're at the start, loop around to the end
       itemToBeSelected = items.get(items.size() - 1);
     }
-    
+
     selectItem(itemToBeSelected);
     if (shownChildMenu != null) {
       doItemAction(itemToBeSelected, false);
@@ -1101,7 +1116,7 @@
 
   /**
    * Set the colspan of a {@link MenuItem} or {@link MenuItemSeparator}.
-   *
+   * 
    * @param item the {@link MenuItem} or {@link MenuItemSeparator}
    * @param colspan the colspan
    */
diff --git a/user/src/com/google/gwt/user/client/ui/MouseListener.java b/user/src/com/google/gwt/user/client/ui/MouseListener.java
index 53ef9ba..9c250b2 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseListener.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for mouse events.
  */
+@Deprecated
 public interface MouseListener extends EventListener {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/MouseListenerAdapter.java b/user/src/com/google/gwt/user/client/ui/MouseListenerAdapter.java
index 7e686c6..bceee83 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseListenerAdapter.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseListenerAdapter.java
@@ -19,6 +19,7 @@
  * An adapter to simplify mouse event listeners that do not need all events
  * defined on the MouseListener interface.
  */
+@Deprecated
 public class MouseListenerAdapter implements MouseListener {
 
   public void onMouseDown(Widget sender, int x, int y) {
diff --git a/user/src/com/google/gwt/user/client/ui/MouseListenerCollection.java b/user/src/com/google/gwt/user/client/ui/MouseListenerCollection.java
index e979546..9d201b9 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseListenerCollection.java
@@ -27,6 +27,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.MouseListener}.
  */
+@Deprecated
 public class MouseListenerCollection extends ArrayList<MouseListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/MouseWheelListener.java b/user/src/com/google/gwt/user/client/ui/MouseWheelListener.java
index 5fec3e9..a74b3cc 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseWheelListener.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseWheelListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for mouse wheel events.
  */
+@Deprecated
 public interface MouseWheelListener extends EventListener {
 
   /**
@@ -28,5 +29,6 @@
    * @param sender the widget sending the event
    * @param velocity the velocity information for the wheel event
    */
+  @Deprecated
   void onMouseWheel(Widget sender, MouseWheelVelocity velocity);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/MouseWheelListenerCollection.java b/user/src/com/google/gwt/user/client/ui/MouseWheelListenerCollection.java
index fccd280..6bf8be5 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseWheelListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseWheelListenerCollection.java
@@ -25,11 +25,12 @@
  * This subclass of {@link ArrayList} assumes that all objects added to it will
  * be of type {@link com.google.gwt.user.client.ui.MouseWheelListener}.
  */
+@Deprecated
 public class MouseWheelListenerCollection extends ArrayList<MouseWheelListener> {
 
   /**
    * Fires a mouse wheel event to all listeners.
-   *
+   * 
    * @param sender the widget sending the event
    * @param velocity the velocity information for the event
    */
@@ -41,7 +42,7 @@
 
   /**
    * A helper for widgets that source mouse events.
-   *
+   * 
    * @param sender the widget sending the event
    * @param event the {@link Event} received by the widget
    */
diff --git a/user/src/com/google/gwt/user/client/ui/MouseWheelVelocity.java b/user/src/com/google/gwt/user/client/ui/MouseWheelVelocity.java
index 099ed35..bf66739 100644
--- a/user/src/com/google/gwt/user/client/ui/MouseWheelVelocity.java
+++ b/user/src/com/google/gwt/user/client/ui/MouseWheelVelocity.java
@@ -26,6 +26,8 @@
  * @see com.google.gwt.user.client.DOM#eventGetMouseWheelVelocityY An
  *      explanation of the units used for mouse wheel velocity.
  */
+
+@Deprecated
 public class MouseWheelVelocity {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/PopupListener.java b/user/src/com/google/gwt/user/client/ui/PopupListener.java
index bfa7c53..bcae3c1 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupListener.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for popup events.
  */
+@Deprecated
 public interface PopupListener extends EventListener {
 
   /**
@@ -29,5 +30,6 @@
    * @param autoClosed <code>true</code> if the popup was automatically
    *          closed; <code>false</code> if it was closed programmatically.
    */
+  @Deprecated
   void onPopupClosed(PopupPanel sender, boolean autoClosed);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/PopupListenerCollection.java b/user/src/com/google/gwt/user/client/ui/PopupListenerCollection.java
index e94ba51..b17e1b6 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.PopupListener}.
  */
+@Deprecated
 public class PopupListenerCollection extends ArrayList<PopupListener> {
 
   /**
@@ -31,6 +32,7 @@
    * @param autoClosed <code>true</code> if the popup was automatically
    *          closed; <code>false</code> if it was closed programmatically.
    */
+  @Deprecated
   public void firePopupClosed(PopupPanel sender, boolean autoClosed) {
     for (PopupListener listener : this) {
       listener.onPopupClosed(sender, autoClosed);
diff --git a/user/src/com/google/gwt/user/client/ui/PopupPanel.java b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
index 585672b..417134d 100644
--- a/user/src/com/google/gwt/user/client/ui/PopupPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/PopupPanel.java
@@ -18,6 +18,10 @@
 import com.google.gwt.animation.client.Animation;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.HasCloseHandlers;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
@@ -57,7 +61,7 @@
  * </ul>
  */
 public class PopupPanel extends SimplePanel implements SourcesPopupEvents,
-    EventPreview, HasAnimation {
+    EventPreview, HasAnimation, HasCloseHandlers<PopupPanel> {
 
   /**
    * A callback that is used to set the position of a {@link PopupPanel} right
@@ -83,8 +87,8 @@
    * 
    * <ul>
    * <li>CENTER - Expand from the center of the popup</li>
-   * <li>ONE_WAY_CORNER - Expand from the top left corner, do not animate
-   * hiding</li>
+   * <li>ONE_WAY_CORNER - Expand from the top left corner, do not animate hiding
+   * </li>
    * </ul>
    */
   static enum AnimationType {
@@ -280,8 +284,6 @@
   // The top style attribute in pixels
   private int topPosition = -1;
 
-  private PopupListenerCollection popupListeners;
-
   /**
    * Creates an empty popup panel. A child widget must be added to it before it
    * is shown.
@@ -323,11 +325,13 @@
     this.modal = modal;
   }
 
-  public void addPopupListener(PopupListener listener) {
-    if (popupListeners == null) {
-      popupListeners = new PopupListenerCollection();
-    }
-    popupListeners.add(listener);
+  public HandlerRegistration addCloseHandler(CloseHandler<PopupPanel> handler) {
+    return addHandler(handler, CloseEvent.getType());
+  }
+
+  @Deprecated
+  public void addPopupListener(final PopupListener listener) {
+    ListenerWrapper.Popup.add(this, listener);
   }
 
   /**
@@ -413,8 +417,7 @@
    * Hides the popup. This has no effect if it is not currently visible.
    * 
    * @param autoClosed the value that will be passed to
-   *          {@link PopupListener#onPopupClosed(PopupPanel, boolean)} when the
-   *          popup is closed
+   *          {@link CloseHandler#onClose(CloseEvent)} when the popup is closed
    */
   public void hide(boolean autoClosed) {
     if (!showing) {
@@ -424,11 +427,7 @@
 
     // Hide the popup
     resizeAnimation.setState(false);
-
-    // Fire the event listeners
-    if (popupListeners != null) {
-      popupListeners.firePopupClosed(this, autoClosed);
-    }
+    CloseEvent.fire(this, this, autoClosed);
   }
 
   public boolean isAnimationEnabled() {
@@ -480,6 +479,17 @@
       }
 
       case Event.ONMOUSEDOWN:
+        // Don't eat events if event capture is enabled, as this can interfere
+        // with dialog dragging, for example.
+        if (DOM.getCaptureElement() != null) {
+          return true;
+        }
+
+        if (!eventTargetsPopup && autoHide) {
+          hide(true);
+          return true;
+        }
+        break;
       case Event.ONMOUSEUP:
       case Event.ONMOUSEMOVE:
       case Event.ONCLICK:
@@ -518,7 +528,7 @@
    * 
    * @param key the key code of the depressed key
    * @param modifiers keyboard modifiers, as specified in
-   *          {@link KeyboardListener}.
+   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
    * @return <code>false</code> to suppress the event
    */
   public boolean onKeyDownPreview(char key, int modifiers) {
@@ -531,7 +541,7 @@
    * 
    * @param key the unicode character pressed
    * @param modifiers keyboard modifiers, as specified in
-   *          {@link KeyboardListener}.
+   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
    * @return <code>false</code> to suppress the event
    */
   public boolean onKeyPressPreview(char key, int modifiers) {
@@ -544,17 +554,16 @@
    * 
    * @param key the key code of the released key
    * @param modifiers keyboard modifiers, as specified in
-   *          {@link KeyboardListener}.
+   *          {@link com.google.gwt.event.dom.client.KeyCodes}.
    * @return <code>false</code> to suppress the event
    */
   public boolean onKeyUpPreview(char key, int modifiers) {
     return true;
   }
 
+  @Deprecated
   public void removePopupListener(PopupListener listener) {
-    if (popupListeners != null) {
-      popupListeners.remove(listener);
-    }
+    ListenerWrapper.Popup.remove(this, listener);
   }
 
   public void setAnimationEnabled(boolean enable) {
@@ -660,8 +669,8 @@
   /**
    * Sets whether this object is visible.
    * 
-   * @param visible <code>true</code> to show the object, <code>false</code>
-   *          to hide it
+   * @param visible <code>true</code> to show the object, <code>false</code> to
+   *          hide it
    */
   @Override
   public void setVisible(boolean visible) {
@@ -734,7 +743,7 @@
     DOM.removeEventPreview(this);
     super.onDetach();
   }
-  
+
   /**
    * We control size by setting our child widget's size. However, if we don't
    * currently have a child, we record the size the user wanted so that when we
@@ -760,7 +769,7 @@
       }
     }
   }
-  
+
   /**
    * Sets the animation used to animate this popup. Used by gwt-incubator to
    * allow DropDownPanel to override the default popup animation. Not protected
diff --git a/user/src/com/google/gwt/user/client/ui/PushButton.java b/user/src/com/google/gwt/user/client/ui/PushButton.java
index a5de73c..3872d11 100644
--- a/user/src/com/google/gwt/user/client/ui/PushButton.java
+++ b/user/src/com/google/gwt/user/client/ui/PushButton.java
@@ -16,6 +16,8 @@
 
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickHandler;
+
 /**
  * A normal push button with custom styling.
  * 
@@ -61,8 +63,20 @@
    * construct the default face of the button.
    * 
    * @param upImage image for the default (up) face of the button
+   * @param handler teh click handler
+   */
+  public PushButton(Image upImage, ClickHandler handler) {
+    super(upImage, handler);
+  }
+
+  /**
+   * Constructor for <code>PushButton</code>. The supplied image is used to
+   * construct the default face of the button.
+   * 
+   * @param upImage image for the default (up) face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public PushButton(Image upImage, ClickListener listener) {
     super(upImage, listener);
   }
@@ -84,6 +98,7 @@
    * @param downImage image for the down face of the button
    * @param listener clickListener
    */
+  @Deprecated
   public PushButton(Image upImage, Image downImage, ClickListener listener) {
     super(upImage, downImage, listener);
   }
@@ -103,8 +118,20 @@
    * construct the default face of the button.
    * 
    * @param upText the text for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public PushButton(String upText, ClickHandler handler) {
+    super(upText, handler);
+  }
+
+  /**
+   * Constructor for <code>PushButton</code>. The supplied text is used to
+   * construct the default face of the button.
+   * 
+   * @param upText the text for the default (up) face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public PushButton(String upText, ClickListener listener) {
     super(upText, listener);
   }
@@ -124,8 +151,20 @@
    * 
    * @param upText the text for the default (up) face of the button
    * @param downText the text for down face of the button
+   * @param handler the click handler
+   */
+  public PushButton(String upText, String downText, ClickHandler handler) {
+    super(upText, downText, handler);
+  }
+
+  /**
+   * Constructor for <code>PushButton</code>.
+   * 
+   * @param upText the text for the default (up) face of the button
+   * @param downText the text for down face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public PushButton(String upText, String downText, ClickListener listener) {
     super(upText, downText, listener);
   }
@@ -135,7 +174,7 @@
     setDown(false);
     super.onClick();
   }
-  
+
   @Override
   protected void onClickCancel() {
     setDown(false);
diff --git a/user/src/com/google/gwt/user/client/ui/RichTextArea.java b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
index e371ded..86faa94 100644
--- a/user/src/com/google/gwt/user/client/ui/RichTextArea.java
+++ b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
@@ -16,8 +16,7 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.Event;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
 import com.google.gwt.user.client.ui.impl.RichTextAreaImpl;
 
 /**
@@ -40,7 +39,7 @@
  * </ul>
  */
 public class RichTextArea extends FocusWidget implements HasHTML,
-    SourcesMouseEvents {
+    SourcesMouseEvents, HasAllMouseHandlers {
 
   /**
    * This interface is used to access basic formatting options, when available.
@@ -290,7 +289,7 @@
     public int getNumber() {
       return number;
     }
-    
+
     @Override
     public String toString() {
       return Integer.toString(number);
@@ -331,7 +330,6 @@
   }
 
   private RichTextAreaImpl impl = GWT.create(RichTextAreaImpl.class);
-  private MouseListenerCollection mouseListeners;
 
   /**
    * Creates a new, blank {@link RichTextArea} object with no stylesheet.
@@ -341,13 +339,6 @@
     setStyleName("gwt-RichTextArea");
   }
 
-  public void addMouseListener(MouseListener listener) {
-    if (mouseListeners == null) {
-      mouseListeners = new MouseListenerCollection();
-    }
-    mouseListeners.add(listener);
-  }
-
   /**
    * Gets the basic rich text formatting interface.
    * 
@@ -382,31 +373,6 @@
   }
 
   @Override
-  public void onBrowserEvent(Event event) {
-    switch (DOM.eventGetType(event)) {
-      case Event.ONMOUSEDOWN:
-      case Event.ONMOUSEUP:
-      case Event.ONMOUSEMOVE:
-      case Event.ONMOUSEOVER:
-      case Event.ONMOUSEOUT:
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-
-      default:
-        // ClickEvents, KeyboardEvents, and FocusEvents
-        super.onBrowserEvent(event);
-    }
-  }
-
-  public void removeMouseListener(MouseListener listener) {
-    if (mouseListeners != null) {
-      mouseListeners.remove(listener);
-    }
-  }
-
-  @Override
   public void setFocus(boolean focused) {
     // There are different problems on each browser when you try to focus an
     // unattached rich text iframe, so just cut it off early.
diff --git a/user/src/com/google/gwt/user/client/ui/RootPanel.java b/user/src/com/google/gwt/user/client/ui/RootPanel.java
index cabdc9c..3f70afb 100644
--- a/user/src/com/google/gwt/user/client/ui/RootPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/RootPanel.java
@@ -16,13 +16,14 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
 import com.google.gwt.i18n.client.BidiUtils;
 import com.google.gwt.i18n.client.HasDirection;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.WindowCloseListener;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -216,14 +217,10 @@
 
   private static void hookWindowClosing() {
     // Catch the window closing event.
-    Window.addWindowCloseListener(new WindowCloseListener() {
-      public void onWindowClosed() {
+    Window.addCloseHandler(new CloseHandler<Window>() {
+      public void onClose(CloseEvent<Window> closeEvent) {
         detachWidgets();
       }
-
-      public String onWindowClosing() {
-        return null;
-      }
     });
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/ScrollListener.java b/user/src/com/google/gwt/user/client/ui/ScrollListener.java
index c1a9d8f..d7e6130 100644
--- a/user/src/com/google/gwt/user/client/ui/ScrollListener.java
+++ b/user/src/com/google/gwt/user/client/ui/ScrollListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for scroll events.
  */
+@Deprecated
 public interface ScrollListener extends EventListener {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/ScrollListenerCollection.java b/user/src/com/google/gwt/user/client/ui/ScrollListenerCollection.java
index 10dafc2..5576063 100644
--- a/user/src/com/google/gwt/user/client/ui/ScrollListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/ScrollListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.ScrollListener}.
  */
+@Deprecated
 public class ScrollListenerCollection extends ArrayList<ScrollListener> {
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/ScrollPanel.java b/user/src/com/google/gwt/user/client/ui/ScrollPanel.java
index 3d23903..2145f78 100644
--- a/user/src/com/google/gwt/user/client/ui/ScrollPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/ScrollPanel.java
@@ -15,24 +15,24 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.HasScrollHandlers;
+import com.google.gwt.event.dom.client.ScrollEvent;
+import com.google.gwt.event.dom.client.ScrollHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.Event;
 
 /**
  * A simple panel that wraps its contents in a scrollable area.
  */
-public class ScrollPanel extends SimplePanel implements SourcesScrollEvents {
-
-  private ScrollListenerCollection scrollListeners;
+public class ScrollPanel extends SimplePanel implements SourcesScrollEvents,
+    HasScrollHandlers {
 
   /**
    * Creates an empty scroll panel.
    */
   public ScrollPanel() {
     setAlwaysShowScrollBars(false);
-    sinkEvents(Event.ONSCROLL);
-
     // Prevent IE standard mode bug when a AbsolutePanel is contained.
     DOM.setStyleAttribute(getElement(), "position", "relative");
   }
@@ -47,11 +47,13 @@
     setWidget(child);
   }
 
+  public HandlerRegistration addScrollHandler(ScrollHandler handler) {
+    return addDomHandler(handler, ScrollEvent.getType());
+  }
+
+  @Deprecated
   public void addScrollListener(ScrollListener listener) {
-    if (scrollListeners == null) {
-      scrollListeners = new ScrollListenerCollection();
-    }
-    scrollListeners.add(listener);
+    ListenerWrapper.Scroll.add(this, listener);
   }
 
   /**
@@ -84,20 +86,9 @@
     return DOM.getElementPropertyInt(getElement(), "scrollTop");
   }
 
-  @Override
-  public void onBrowserEvent(Event event) {
-    if (DOM.eventGetType(event) == Event.ONSCROLL) {
-      if (scrollListeners != null) {
-        scrollListeners.fireScroll(this, getHorizontalScrollPosition(),
-            getScrollPosition());
-      }
-    }
-  }
-
+  @Deprecated
   public void removeScrollListener(ScrollListener listener) {
-    if (scrollListeners != null) {
-      scrollListeners.remove(listener);
-    }
+    ListenerWrapper.Scroll.remove(this, listener);
   }
 
   /**
@@ -209,5 +200,4 @@
 
     scroll.scrollTop = realOffset - scroll.offsetHeight / 2;
   }-*/;
-
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SimpleCheckBox.java b/user/src/com/google/gwt/user/client/ui/SimpleCheckBox.java
index 602ffe5..4bc465c 100644
--- a/user/src/com/google/gwt/user/client/ui/SimpleCheckBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SimpleCheckBox.java
@@ -103,6 +103,7 @@
     getInputElement().setDefaultChecked(checked);
   }
 
+  @Override
   public void setEnabled(boolean enabled) {
     super.setEnabled(enabled);
     if (enabled) {
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesChangeEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesChangeEvents.java
index 28a49b3..57b71bc 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesChangeEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesChangeEvents.java
@@ -19,19 +19,23 @@
  * A widget that implements this interface sources the events defined by the
  * {@link com.google.gwt.user.client.ui.ChangeListener} interface.
  */
+
 public interface SourcesChangeEvents {
 
   /**
    * Adds a listener interface to receive change events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addChangeHandler</code> instead
    */
+  @Deprecated
   void addChangeListener(ChangeListener listener);
 
   /**
    * Removes a previously added listener interface.
    * 
-   * @param listener the listener interface to remove
+   * @param listener the listener interface to remove 
    */
+  @Deprecated
   void removeChangeListener(ChangeListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesClickEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesClickEvents.java
index e174bb1..3ee84cf 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesClickEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesClickEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive click events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addClickHandler</code> instead
    */
+  @Deprecated
   void addClickListener(ClickListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeClickListener(ClickListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesFocusEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesFocusEvents.java
index daa989c..44ea83d 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesFocusEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesFocusEvents.java
@@ -18,14 +18,18 @@
 /**
  * A widget that implements this interface sources the events defined by the
  * {@link com.google.gwt.user.client.ui.FocusListener} interface.
+ * 
  */
 public interface SourcesFocusEvents {
 
   /**
-   * Adds a listener interface to receive mouse events.
+   * Adds a listener interface to receive focus events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addFocusHandler</code> and <cod>addBlurHandler</code>
+   *             instead.
    */
+  @Deprecated
   void addFocusListener(FocusListener listener);
 
   /**
@@ -33,5 +37,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeFocusListener(FocusListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesKeyboardEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesKeyboardEvents.java
index 7a6e4b2..8e7d4f3 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesKeyboardEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesKeyboardEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive keyboard events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addKeyPressHandler/addKeyDownKeyDownHandler/addKeyUpHandler</code> instead
    */
+  @Deprecated
   void addKeyboardListener(KeyboardListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeKeyboardListener(KeyboardListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesLoadEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesLoadEvents.java
index 10bfeac..a8c9484 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesLoadEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesLoadEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive load events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addLoadHandler</code> instead
    */
+  @Deprecated
   void addLoadListener(LoadListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeLoadListener(LoadListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesMouseEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesMouseEvents.java
index f20b0d0..3c0539f 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesMouseEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesMouseEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive mouse events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use <code>addMouse(Down/Up/Over/Out/Move/Scroll)Handler</code> instead
    */
+  @Deprecated
   void addMouseListener(MouseListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeMouseListener(MouseListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesMouseWheelEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesMouseWheelEvents.java
index 0744fec..b8ff921 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesMouseWheelEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesMouseWheelEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive mouse events.
    *
    * @param listener the listener interface to add
+   * @deprecated use <code>addMouseWheelHandler</code>
    */
+  @Deprecated
   void addMouseWheelListener(MouseWheelListener listener);
 
   /**
@@ -33,5 +35,6 @@
    *
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeMouseWheelListener(MouseWheelListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesPopupEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesPopupEvents.java
index aa65b02..8276160 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesPopupEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesPopupEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive popup events.
    * 
    * @param listener the listener interface to add.
+   * @deprecated use <code>addCloseHandler<PopupPanel></code> instead
    */
+  @Deprecated
   void addPopupListener(PopupListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove.
    */
+  @Deprecated
   void removePopupListener(PopupListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesScrollEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesScrollEvents.java
index 6d39a60..178aeff 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesScrollEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesScrollEvents.java
@@ -24,14 +24,17 @@
   /**
    * Adds a listener interface to receive scroll events.
    * 
-   * @param listener the listener interface to add.
+   * @param listener the listener interface to add
+   * @deprecated use addScrollHandler instead
    */
+  @Deprecated
   void addScrollListener(ScrollListener listener);
 
   /**
    * Removes a previously added scroll listener.
    * 
-   * @param listener the listener interface to remove.
+   * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeScrollListener(ScrollListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesTabEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesTabEvents.java
index 5b750b1..1f3cf19 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesTabEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesTabEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive click events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use addBeforeSelectionHandler and addSelectionHandler instead
    */
+  @Deprecated
   void addTabListener(TabListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeTabListener(TabListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesTableEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesTableEvents.java
index add9f374..03e05a1 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesTableEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesTableEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive click events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use addClickHandler and getCell(DomEvent) instead
    */
+  @Deprecated
   void addTableListener(TableListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeTableListener(TableListener listener);
 }
\ No newline at end of file
diff --git a/user/src/com/google/gwt/user/client/ui/SourcesTreeEvents.java b/user/src/com/google/gwt/user/client/ui/SourcesTreeEvents.java
index 8cb1b54..519e148 100644
--- a/user/src/com/google/gwt/user/client/ui/SourcesTreeEvents.java
+++ b/user/src/com/google/gwt/user/client/ui/SourcesTreeEvents.java
@@ -25,7 +25,9 @@
    * Adds a listener interface to receive tree events.
    * 
    * @param listener the listener interface to add
+   * @deprecated use addSelectionHandler,addOpenHandler, and addCloseHandler instead
    */
+  @Deprecated
   void addTreeListener(TreeListener listener);
 
   /**
@@ -33,5 +35,6 @@
    * 
    * @param listener the listener interface to remove
    */
+  @Deprecated
   void removeTreeListener(TreeListener listener);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/StackPanel.java b/user/src/com/google/gwt/user/client/ui/StackPanel.java
index 5a00409..ae17c23 100644
--- a/user/src/com/google/gwt/user/client/ui/StackPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/StackPanel.java
@@ -223,8 +223,7 @@
     if ((index >= getWidgetCount()) || (index < 0) || (index == visibleStack)) {
       return;
     }
-
-    int oldIndex = visibleStack;
+ 
     if (visibleStack >= 0) {
       setStackVisible(visibleStack, false);
     }
@@ -343,7 +342,6 @@
     Element trNext = DOM.getChild(body, ((index + 1) * 2));
     if (trNext != null) {
       Element tdNext = DOM.getFirstChild(trNext);
-      Element divNext = DOM.getFirstChild(tdNext);
       setStyleName(tdNext, DEFAULT_ITEM_STYLENAME + "-below-selected", visible);
     }
   }
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestBox.java b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
index e4ba0ee..f9ec7da 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestBox.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestBox.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2008 Google Inc.
- *
+ * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * 
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,6 +15,25 @@
  */
 package com.google.gwt.user.client.ui;
 
+import static com.google.gwt.event.dom.client.KeyCodes.KEY_DOWN;
+import static com.google.gwt.event.dom.client.KeyCodes.KEY_ENTER;
+import static com.google.gwt.event.dom.client.KeyCodes.KEY_TAB;
+import static com.google.gwt.event.dom.client.KeyCodes.KEY_UP;
+
+import com.google.gwt.event.dom.client.HandlesAllKeyEvents;
+import com.google.gwt.event.dom.client.HasAllKeyHandlers;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
@@ -25,10 +44,8 @@
 import com.google.gwt.user.client.ui.SuggestOracle.Response;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-
 /**
  * A {@link SuggestBox} is a text box or text area which displays a
  * pre-configured set of selections that match the user's input.
@@ -57,7 +74,7 @@
  * oracle will configure the suggestions with the "Cat" and "Canary"
  * suggestions. Specifically, whenever the user types a key into the text
  * widget, the value is submitted to the <code>MultiWordSuggestOracle</code>.
- *
+ * 
  * <p>
  * Note that there is no method to retrieve the "currently selected suggestion"
  * in a SuggestBox, because there are points in time where the currently
@@ -65,70 +82,60 @@
  * text that does not match any of the SuggestBox's suggestions, then the
  * SuggestBox will not have a currently selected suggestion. It is more useful
  * to know when a suggestion has been chosen from the SuggestBox's list of
- * suggestions. A SuggestBox fires
- * {@link SuggestionEvent SuggestionEvents} whenever a suggestion is chosen, and
- * handlers for these events can be added using the 
- * {@link #addEventHandler(SuggestionHandler)} method.
+ * suggestions. A SuggestBox fires {@link SuggestionEvent SuggestionEvents}
+ * whenever a suggestion is chosen, and handlers for these events can be added
+ * using the {@link #addValueChangeHandler(ValueChangeHandler)} method.
  * </p>
- *
+ * 
  * <p>
  * <img class='gallery' src='SuggestBox.png'/>
  * </p>
  * 
- * <h3>CSS Style Rules</h3>
- * <ul class='css'>
- * <li>.gwt-SuggestBox { the suggest box itself }</li>
- * <li>.gwt-SuggestBoxPopup { the suggestion popup }</li>
- * <li>.gwt-SuggestBoxPopup .item { an unselected suggestion }</li>
- * <li>.gwt-SuggestBoxPopup .item-selected { a selected suggestion }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopLeft { the top left cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopLeftInner { the inner element of
- * the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopCenter { the top center cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopCenterInner { the inner element of
- * the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopRight { the top right cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupTopRightInner { the inner element of
- * the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleLeft { the middle left cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleLeftInner { the inner element of
- * the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleCenter { the middle center cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleCenterInner { the inner element
- * of the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleRight { the middle right cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleRightInner { the inner element
- * of the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomLeft { the bottom left cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomLeftInner { the inner element of
- * the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomCenter { the bottom center cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomCenterInner { the inner element
- * of the cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomRight { the bottom right cell }</li>
- * <li>.gwt-SuggestBoxPopup .suggestPopupBottomRightInner { the inner element
- * of the cell }</li>
- * </ul>
+ * <h3>CSS Style Rules</h3> 
+ * <ul class='css'> 
+ * <li>.gwt-SuggestBox { the suggest
+ * box itself }</li> 
+ * <li>.gwt-SuggestBoxPopup { the suggestion popup }</li> 
+ * <li>.gwt-SuggestBoxPopup .item { an unselected suggestion }</li> 
+ * <li>.gwt-SuggestBoxPopup .item-selected { a selected suggestion }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopLeft { the top left cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopLeftInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopCenter { the top center cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopCenterInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopRight { the top right cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupTopRightInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleLeft { the middle left cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleLeftInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleCenter { the middle center cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleCenterInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleRight { the middle right cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupMiddleRightInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomLeft { the bottom left cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomLeftInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomCenter { the bottom center cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomCenterInner { the inner element of the cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomRight { the bottom right cell }</li> 
+ * <li>.gwt-SuggestBoxPopup .suggestPopupBottomRightInner { the inner element of the cell }</li> </ul>
  * 
  * @see SuggestOracle
  * @see MultiWordSuggestOracle
  * @see TextBoxBase
  */
-public final class SuggestBox extends Composite implements HasText, HasFocus,
+public class SuggestBox extends Composite implements HasText, HasFocus,
     HasAnimation, SourcesClickEvents, SourcesFocusEvents, SourcesChangeEvents,
-    SourcesKeyboardEvents, FiresSuggestionEvents {
+    SourcesKeyboardEvents, FiresSuggestionEvents, HasAllKeyHandlers,
+    HasValue<String>, HasSelectionHandlers<Suggestion> {
 
   /**
    * The SuggestionMenu class is used for the display and selection of
-   * suggestions in the SuggestBox widget. SuggestionMenu differs from
-   * MenuBar in that it always has a vertical orientation, and it
-   * has no submenus. It also allows for programmatic selection of items in
-   * the menu, and programmatically performing the action associated with the
-   * selected item. In the MenuBar class, items cannot be selected
-   * programatically - they can only be selected when the user places the
-   * mouse over a particlar item. Additional methods in SuggestionMenu provide
-   * information about the number of items in the menu, and the index of the
-   * currently selected item.
+   * suggestions in the SuggestBox widget. SuggestionMenu differs from MenuBar
+   * in that it always has a vertical orientation, and it has no submenus. It
+   * also allows for programmatic selection of items in the menu, and
+   * programmatically performing the action associated with the selected item.
+   * In the MenuBar class, items cannot be selected programatically - they can
+   * only be selected when the user places the mouse over a particlar item.
+   * Additional methods in SuggestionMenu provide information about the number
+   * of items in the menu, and the index of the currently selected item.
    */
   private static class SuggestionMenu extends MenuBar {
 
@@ -154,6 +161,8 @@
 
     /**
      * Returns the index of the menu item that is currently selected.
+     * 
+     * @return returns the selected item
      */
     public int getSelectedItemIndex() {
       // The index of the currently selected item can only be
@@ -169,6 +178,8 @@
      * Selects the item at the specified index in the menu. Selecting the item
      * does not perform the item's associated action; it only changes the style
      * of the item and updates the value of SuggestionMenu.selectedItem.
+     * 
+     * @param index index
      */
     public void selectItem(int index) {
       List<MenuItem> items = getItems();
@@ -179,15 +190,13 @@
   }
 
   /**
-   * Class for menu items in a SuggestionMenu. A SuggestionMenuItem differs
-   * from a MenuItem in that each item is backed by a Suggestion object.
-   * The text of each menu item is derived from the display string of a
-   * Suggestion object, and each item stores a reference to its Suggestion
-   * object.
+   * Class for menu items in a SuggestionMenu. A SuggestionMenuItem differs from
+   * a MenuItem in that each item is backed by a Suggestion object. The text of
+   * each menu item is derived from the display string of a Suggestion object,
+   * and each item stores a reference to its Suggestion object.
    */
   private static class SuggestionMenuItem extends MenuItem {
 
-    @SuppressWarnings("hiding")
     private static final String STYLENAME_DEFAULT = "item";
 
     private Suggestion suggestion;
@@ -215,17 +224,15 @@
   /**
    * A PopupPanel with a SuggestionMenu as its widget. The SuggestionMenu is
    * placed in a PopupPanel so that it can be displayed at various positions
-   * around the SuggestBox's text field. Moreover, the SuggestionMenu
-   * needs to appear on top of any other widgets on the page, and the PopupPanel
-   * provides this behavior.
-   *
+   * around the SuggestBox's text field. Moreover, the SuggestionMenu needs to
+   * appear on top of any other widgets on the page, and the PopupPanel provides
+   * this behavior.
+   * 
    * A non-static member class is used because the popup uses the SuggestBox's
    * SuggestionMenu as its widget, and the position of the SuggestBox's TextBox
    * is needed in order to correctly position the popup.
    */
   private class SuggestionPopup extends DecoratedPopupPanel {
-
-    @SuppressWarnings("hiding")
     private static final String STYLENAME_DEFAULT = "gwt-SuggestBoxPopup";
 
     public SuggestionPopup() {
@@ -243,127 +250,136 @@
      * edge may be aligned with the right edge of the text box.
      */
     public void showAlignedPopup() {
-   
-    // Set the position of the popup right before it is shown.
-    setPopupPositionAndShow(new PositionCallback() {
-      public void setPosition(int offsetWidth, int offsetHeight) {
-        
-        // Calculate left position for the popup. The computation for
-        // the left position is bidi-sensitive.
-       
-        int textBoxOffsetWidth = box.getOffsetWidth();
-               
-        // Compute the difference between the popup's width and the
-        // textbox's width
-        int offsetWidthDiff = offsetWidth - textBoxOffsetWidth;
-        
-        int left;
-        
-        if (LocaleInfo.getCurrentLocale().isRTL()) {   // RTL case
-          
-          int textBoxAbsoluteLeft = box.getAbsoluteLeft();
-          
-          // Right-align the popup. Note that this computation is
-          // valid in the case where offsetWidthDiff is negative.
-          left = textBoxAbsoluteLeft - offsetWidthDiff;
 
-          // If the suggestion popup is not as wide as the text box, always align
-          // to the right edge of the text box. Otherwise, figure out whether to
-          // right-align or left-align the popup.
-          if (offsetWidthDiff > 0) {
-            
-            // Make sure scrolling is taken into account, since box.getAbsoluteLeft()
-            // takes scrolling into account.
-            int windowRight = Window.getClientWidth() + Window.getScrollLeft();
-            int windowLeft = Window.getScrollLeft();
+      // Set the position of the popup right before it is shown.
+      setPopupPositionAndShow(new PositionCallback() {
+        public void setPosition(int offsetWidth, int offsetHeight) {
 
-            // Compute the left value for the right edge of the textbox
-            int textBoxLeftValForRightEdge = textBoxAbsoluteLeft + textBoxOffsetWidth;
-                
-            // Distance from the right edge of the text box to the right edge of the
-            // window
-            int distanceToWindowRight = windowRight - textBoxLeftValForRightEdge;
+          // Calculate left position for the popup. The computation for
+          // the left position is bidi-sensitive.
 
-            // Distance from the right edge of the text box to the left edge of the
-            // window
-            int distanceFromWindowLeft = textBoxLeftValForRightEdge - windowLeft; 
+          int textBoxOffsetWidth = box.getOffsetWidth();
 
-            // If there is not enough space for the overflow of the popup's width to
-            // the right of the text box and there IS enough space for the overflow
-            // to the right of the text box, then left-align the popup. However, if
-            // there is not enough space on either side, stick with right-alignment.
-            if (distanceFromWindowLeft < offsetWidth &&
-                distanceToWindowRight >= offsetWidthDiff) {
-              // Align with the left edge of the text box.
-              left = textBoxAbsoluteLeft;
+          // Compute the difference between the popup's width and the
+          // textbox's width
+          int offsetWidthDiff = offsetWidth - textBoxOffsetWidth;
+
+          int left;
+
+          if (LocaleInfo.getCurrentLocale().isRTL()) { // RTL case
+
+            int textBoxAbsoluteLeft = box.getAbsoluteLeft();
+
+            // Right-align the popup. Note that this computation is
+            // valid in the case where offsetWidthDiff is negative.
+            left = textBoxAbsoluteLeft - offsetWidthDiff;
+
+            // If the suggestion popup is not as wide as the text box, always
+            // align to the right edge of the text box. Otherwise, figure out
+            // whether to right-align or left-align the popup.
+            if (offsetWidthDiff > 0) {
+
+              // Make sure scrolling is taken into account, since
+              // box.getAbsoluteLeft() takes scrolling into account.
+              int windowRight = Window.getClientWidth()
+                  + Window.getScrollLeft();
+              int windowLeft = Window.getScrollLeft();
+
+              // Compute the left value for the right edge of the textbox
+              int textBoxLeftValForRightEdge = textBoxAbsoluteLeft
+                  + textBoxOffsetWidth;
+
+              // Distance from the right edge of the text box to the right edge
+              // of the window
+              int distanceToWindowRight = windowRight
+                  - textBoxLeftValForRightEdge;
+
+              // Distance from the right edge of the text box to the left edge
+              // of the window
+              int distanceFromWindowLeft = textBoxLeftValForRightEdge
+                  - windowLeft;
+
+              // If there is not enough space for the overflow of the popup's
+              // width to the right of the text box and there IS enough space
+              // for the overflow to the right of the text box, then left-align
+              // the popup. However, if there is not enough space on either
+              // side, stick with right-alignment.
+              if (distanceFromWindowLeft < offsetWidth
+                  && distanceToWindowRight >= offsetWidthDiff) {
+                // Align with the left edge of the text box.
+                left = textBoxAbsoluteLeft;
+              }
+            }
+          } else { // LTR case
+
+            // Left-align the popup.
+            left = box.getAbsoluteLeft();
+
+            // If the suggestion popup is not as wide as the text box, always
+            // align to the left edge of the text box. Otherwise, figure out
+            // whether to left-align or right-align the popup.
+            if (offsetWidthDiff > 0) {
+              // Make sure scrolling is taken into account, since
+              // box.getAbsoluteLeft() takes scrolling into account.
+              int windowRight = Window.getClientWidth()
+                  + Window.getScrollLeft();
+              int windowLeft = Window.getScrollLeft();
+
+              // Distance from the left edge of the text box to the right edge
+              // of the window
+              int distanceToWindowRight = windowRight - left;
+
+              // Distance from the left edge of the text box to the left edge of
+              // the window
+              int distanceFromWindowLeft = left - windowLeft;
+
+              // If there is not enough space for the overflow of the popup's
+              // width to the right of hte text box, and there IS enough space
+              // for the overflow to the left of the text box, then right-align
+              // the popup. However, if there is not enough space on either
+              // side, then stick with left-alignment.
+              if (distanceToWindowRight < offsetWidth
+                  && distanceFromWindowLeft >= offsetWidthDiff) {
+                // Align with the right edge of the text box.
+                left -= offsetWidthDiff;
+              }
             }
           }
-        } else {  // LTR case
-          
-          // Left-align the popup.
-          left = box.getAbsoluteLeft();
 
-          // If the suggestion popup is not as wide as the text box, always align
-          // to the left edge of the text box. Otherwise, figure out whether to
-          // left-align or right-align the popup.
-          if (offsetWidthDiff > 0) {
-            // Make sure scrolling is taken into account, since box.getAbsoluteLeft()
-            // takes scrolling into account.
-            int windowRight = Window.getClientWidth() + Window.getScrollLeft();
-            int windowLeft = Window.getScrollLeft();
+          // Calculate top position for the popup
 
-            // Distance from the left edge of the text box to the right edge of the
-            // window
-            int distanceToWindowRight = windowRight - left;
+          int top = box.getAbsoluteTop();
 
-            // Distance from the left edge of the text box to the left edge of the
-            // window
-            int distanceFromWindowLeft = left - windowLeft;
+          // Make sure scrolling is taken into account, since
+          // box.getAbsoluteTop() takes scrolling into account.
+          int windowTop = Window.getScrollTop();
+          int windowBottom = Window.getScrollTop() + Window.getClientHeight();
 
-            // If there is not enough space for the overflow of the popup's width to 
-            // the right of hte text box, and there IS enough space for the overflow
-            // to the left of the text box, then right-align the popup. However, if
-            // there is not enough space on either side, then stick with left-alignment.
-            if (distanceToWindowRight < offsetWidth &&
-                distanceFromWindowLeft >= offsetWidthDiff) {
-              // Align with the right edge of the text box.
-              left -= offsetWidthDiff;
-            }
+          // Distance from the top edge of the window to the top edge of the
+          // text box
+          int distanceFromWindowTop = top - windowTop;
+
+          // Distance from the bottom edge of the window to the bottom edge of
+          // the text box
+          int distanceToWindowBottom = windowBottom
+              - (top + box.getOffsetHeight());
+
+          // If there is not enough space for the popup's height below the text
+          // box and there IS enough space for the popup's height above the text
+          // box, then then position the popup above the text box. However, if
+          // there is not enough space on either side, then stick with
+          // displaying the popup below the text box.
+          if (distanceToWindowBottom < offsetHeight
+              && distanceFromWindowTop >= offsetHeight) {
+            top -= offsetHeight;
+          } else {
+            // Position above the text box
+            top += box.getOffsetHeight();
           }
+
+          setPopupPosition(left, top);
         }
-
-        // Calculate top position for the popup
-
-        int top = box.getAbsoluteTop();
-
-        // Make sure scrolling is taken into account, since box.getAbsoluteTop()
-        // takes scrolling into account.
-        int windowTop = Window.getScrollTop();
-        int windowBottom = Window.getScrollTop() + Window.getClientHeight();
-
-        // Distance from the top edge of the window to the top edge of the text box
-        int distanceFromWindowTop = top - windowTop;
-
-        // Distance from the bottom edge of the window to the bottom edge of the
-        // text box
-        int distanceToWindowBottom = windowBottom - (top + box.getOffsetHeight());
-
-        // If there is not enough space for the popup's height below the text box
-        // and there IS enough space for the popup's height above the text box,
-        // then then position the popup above the text box. However, if there is
-        // not enough space on either side, then stick with displaying the popup
-        // below the text box.
-        if (distanceToWindowBottom < offsetHeight &&
-            distanceFromWindowTop >= offsetHeight) {
-          top -= offsetHeight;
-        } else {
-          // Position above the text box
-          top += box.getOffsetHeight();
-        }
-
-        setPopupPosition(left, top);
-      }
-    });
+      });
     }
   }
 
@@ -376,12 +392,6 @@
   private final SuggestionMenu suggestionMenu;
   private final SuggestionPopup suggestionPopup;
   private final TextBoxBase box;
-  private ArrayList<SuggestionHandler> suggestionHandlers = null;
-  private DelegatingClickListenerCollection clickListeners;
-  private DelegatingChangeListenerCollection changeListeners;
-  private DelegatingFocusListenerCollection focusListeners;
-  private DelegatingKeyboardListenerCollection keyboardListeners;
-
   private final Callback callBack = new Callback() {
     public void onSuggestionsReady(Request request, Response response) {
       showSuggestions(response.getSuggestions());
@@ -424,69 +434,88 @@
     suggestionMenu = new SuggestionMenu(true);
     suggestionPopup = new SuggestionPopup();
     suggestionPopup.setAnimationType(AnimationType.ONE_WAY_CORNER);
-    
-    addKeyboardSupport();
+
+    addEventsToTextBox();
+
     setOracle(oracle);
     setStyleName(STYLENAME_DEFAULT);
   }
 
   /**
-   * Adds a listener to recieve change events on the SuggestBox's text box.
-   * The source Widget for these events will be the SuggestBox.
-   *
+   * 
+   * Adds a listener to receive change events on the SuggestBox's text box. The
+   * source Widget for these events will be the SuggestBox.
+   * 
    * @param listener the listener interface to add
+   * @deprecated use getTextBox().addChangeHandler instead
    */
-  public void addChangeListener(ChangeListener listener) {
-    if (changeListeners == null) {
-      changeListeners = new DelegatingChangeListenerCollection(this, box);
-    }
-    changeListeners.add(listener);
+  @Deprecated
+  public void addChangeListener(final ChangeListener listener) {
+    ListenerWrapper.Change legacy = new ListenerWrapper.Change(listener);
+    legacy.setSource(this);
+    box.addChangeHandler(legacy);
   }
 
   /**
-   * Adds a listener to recieve click events on the SuggestBox's text box.
-   * The source Widget for these events will be the SuggestBox.
-   *
+   * Adds a listener to receive click events on the SuggestBox's text box. The
+   * source Widget for these events will be the SuggestBox.
+   * 
    * @param listener the listener interface to add
+   * @deprecated use getTextBox().addClickHandler instead
    */
-  public void addClickListener(ClickListener listener) {
-    if (clickListeners == null) {
-      clickListeners = new DelegatingClickListenerCollection(this, box);
-    }
-    clickListeners.add(listener);
-  }
-
-  public void addEventHandler(SuggestionHandler handler) {
-    if (suggestionHandlers == null) {
-      suggestionHandlers = new ArrayList<SuggestionHandler>();
-    }
-    suggestionHandlers.add(handler);
+  @Deprecated
+  public void addClickListener(final ClickListener listener) {
+    ListenerWrapper.Click legacy = ListenerWrapper.Click.add(box, listener);
+    legacy.setSource(this);
   }
 
   /**
-   * Adds a listener to recieve focus events on the SuggestBox's text box.
-   * The source Widget for these events will be the SuggestBox.
-   *
-   * @param listener the listener interface to add
+   * Adds an event to this handler.
+   * 
+   * @deprecated use addSelectionHandler instead.
    */
-  public void addFocusListener(FocusListener listener) {
-    if (focusListeners == null) {
-      focusListeners = new DelegatingFocusListenerCollection(this, box);
-    }
-    focusListeners.add(listener);
+  public void addEventHandler(final SuggestionHandler handler) {
+    ListenerWrapper.Suggestion.add(this, handler);
   }
 
   /**
-   * Adds a listener to recieve keyboard events on the SuggestBox's text box.
-   * The source Widget for these events will be the SuggestBox.
-   *
+   * Adds a listener to receive focus events on the SuggestBox's text box. The
+   * source Widget for these events will be the SuggestBox.
+   * 
    * @param listener the listener interface to add
+   * @deprecated use getTextBox().addFocusHandler/addBlurHandler() instead
    */
+  @Deprecated
+  public void addFocusListener(final FocusListener listener) {
+    ListenerWrapper.Focus focus = ListenerWrapper.Focus.add(box, listener);
+    focus.setSource(this);
+  }
+
+  @Deprecated
   public void addKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners == null) {
-      keyboardListeners = new DelegatingKeyboardListenerCollection(this, box);
-    }
-    keyboardListeners.add(listener);
+    ListenerWrapper.Keyboard.add(this, listener);
+  }
+
+  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+    return addDomHandler(handler, KeyDownEvent.getType());
+  }
+
+  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+    return addDomHandler(handler, KeyPressEvent.getType());
+  }
+
+  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+    return addDomHandler(handler, KeyUpEvent.getType());
+  }
+
+  public HandlerRegistration addSelectionHandler(
+      SelectionHandler<Suggestion> handler) {
+    return addHandler(handler, SelectionEvent.getType());
+  }
+
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<String> handler) {
+    return addHandler(handler, ValueChangeEvent.getType());
   }
 
   /**
@@ -527,39 +556,46 @@
     return box.getText();
   }
 
+  /**
+   * Get the text box associated with this suggest box.
+   * 
+   * @return this suggest box's text box
+   */
+  public TextBoxBase getTextBox() {
+    return box;
+  }
+
+  public String getValue() {
+    return box.getValue();
+  }
+
   public boolean isAnimationEnabled() {
     return suggestionPopup.isAnimationEnabled();
   }
 
+  @Deprecated
   public void removeChangeListener(ChangeListener listener) {
-    if (changeListeners != null) {
-      changeListeners.remove(listener);
-    }
+    ListenerWrapper.Change.remove(box, listener);
   }
 
+  @Deprecated
   public void removeClickListener(ClickListener listener) {
-    if (clickListeners != null) {
-      clickListeners.remove(listener);
-    }
+    ListenerWrapper.Click.remove(box, listener);
   }
 
+  @Deprecated
   public void removeEventHandler(SuggestionHandler handler) {
-    if (suggestionHandlers == null) {
-      return;
-    }
-    suggestionHandlers.remove(handler);
+    ListenerWrapper.Suggestion.remove(this, handler);
   }
 
+  @Deprecated
   public void removeFocusListener(FocusListener listener) {
-    if (focusListeners != null) {
-      focusListeners.remove(listener);
-    }
+    ListenerWrapper.Focus.remove(this, listener);
   }
 
+  @Deprecated
   public void removeKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners != null) {
-      keyboardListeners.remove(listener);
-    }
+    ListenerWrapper.Keyboard.remove(this, listener);
   }
 
   public void setAccessKey(char key) {
@@ -586,7 +622,7 @@
 
   /**
    * Sets the style name of the suggestion popup.
-   *
+   * 
    * @param style the new primary style name
    * @see UIObject#setStyleName(String)
    */
@@ -613,6 +649,14 @@
     box.setText(text);
   }
 
+  public void setValue(String newValue) {
+    box.setValue(newValue);
+  }
+
+  public void setValue(String value, boolean fireEvents) {
+    box.setValue(value, fireEvents);
+  }
+
   /**
    * <b>Affected Elements:</b>
    * <ul>
@@ -629,66 +673,23 @@
     suggestionMenu.setMenuItemDebugIds(baseID);
   }
 
-  /**
-   * Show the given collection of suggestions.
-   * 
-   * @param suggestions suggestions to show
-   */
-  private void showSuggestions(Collection<? extends Suggestion> suggestions) {
-    if (suggestions.size() > 0) {
+  private void addEventsToTextBox() {
+    class TextBoxEvents extends HandlesAllKeyEvents implements
+        ValueChangeHandler<String> {
 
-      // Hide the popup before we manipulate the menu within it. If we do not
-      // do this, some browsers will redraw the popup as items are removed
-      // and added to the menu.
-      boolean isAnimationEnabled = suggestionPopup.isAnimationEnabled();
-      if (suggestionPopup.isAttached()) {
-        suggestionPopup.setAnimationEnabled(false);
-        suggestionPopup.hide();
-      }
-      
-      suggestionMenu.clearItems();
-
-      for (Suggestion curSuggestion : suggestions) {
-        final SuggestionMenuItem menuItem =
-            new SuggestionMenuItem(curSuggestion, oracle.isDisplayStringHTML());
-        menuItem.setCommand(new Command() {
-          public void execute() {
-            SuggestBox.this.setNewSelection(menuItem);
-          }
-        });
-
-        suggestionMenu.addItem(menuItem);
-      }
-
-      if (selectsFirstItem) {
-        // Select the first item in the suggestion menu.
-        suggestionMenu.selectItem(0);
-      }
-
-      suggestionPopup.showAlignedPopup();
-      suggestionPopup.setAnimationEnabled(isAnimationEnabled);
-    } else {
-      suggestionPopup.hide();
-    }
-  }
-
-  private void addKeyboardSupport() {
-    box.addKeyboardListener(new KeyboardListenerAdapter() {
-
-      @Override
-      public void onKeyDown(Widget sender, char keyCode, int modifiers) {
+      public void onKeyDown(KeyDownEvent event) {
         // Make sure that the menu is actually showing. These keystrokes
         // are only relevant when choosing a suggestion.
         if (suggestionPopup.isAttached()) {
-          switch (keyCode) {
-            case KeyboardListener.KEY_DOWN:
+          switch (event.getNativeKeyCode()) {
+            case KEY_DOWN:
               suggestionMenu.selectItem(suggestionMenu.getSelectedItemIndex() + 1);
               break;
-            case KeyboardListener.KEY_UP:
+            case KEY_UP:
               suggestionMenu.selectItem(suggestionMenu.getSelectedItemIndex() - 1);
               break;
-            case KeyboardListener.KEY_ENTER:
-            case KeyboardListener.KEY_TAB:
+            case KEY_ENTER:
+            case KEY_TAB:
               if (suggestionMenu.getSelectedItemIndex() < 0) {
                 suggestionPopup.hide();
               } else {
@@ -697,12 +698,21 @@
               break;
           }
         }
+        fireEvent(event);
       }
 
-      @Override
-      public void onKeyUp(Widget sender, char keyCode, int modifiers) {
+      public void onKeyPress(KeyPressEvent event) {
+        fireEvent(event);
+      }
+
+      public void onKeyUp(KeyUpEvent event) {
         // After every user key input, refresh the popup's suggestions.
         refreshSuggestions();
+        fireEvent(event);
+      }
+
+      public void onValueChange(ValueChangeEvent<String> event) {
+         fireEvent(event);
       }
 
       private void refreshSuggestions() {
@@ -723,24 +733,23 @@
           showSuggestions(text);
         }
       }
-    });
+    }
+
+    TextBoxEvents events = new TextBoxEvents();
+    events.addKeyHandlersTo(box);
+    box.addValueChangeHandler(events);
   }
 
   private void fireSuggestionEvent(Suggestion selectedSuggestion) {
-    if (suggestionHandlers != null) {
-      SuggestionEvent event = new SuggestionEvent(this, selectedSuggestion);
-      for (SuggestionHandler handler : suggestionHandlers) {
-        handler.onSuggestionSelected(event);
-      }
-    }
+    SelectionEvent.fire(this, selectedSuggestion);
   }
 
   private void setNewSelection(SuggestionMenuItem menuItem) {
     Suggestion curSuggestion = menuItem.getSuggestion();
     currentText = curSuggestion.getReplacementString();
-    box.setText(currentText);
+    setText(currentText);
     suggestionPopup.hide();
-    fireSuggestionEvent(curSuggestion);    
+    fireSuggestionEvent(curSuggestion);
   }
 
   /**
@@ -752,6 +761,49 @@
     this.oracle = oracle;
   }
 
+  /**
+   * Show the given collection of suggestions.
+   * 
+   * @param suggestions suggestions to show
+   */
+  private void showSuggestions(Collection<? extends Suggestion> suggestions) {
+    if (suggestions.size() > 0) {
+
+      // Hide the popup before we manipulate the menu within it. If we do not
+      // do this, some browsers will redraw the popup as items are removed
+      // and added to the menu.
+      boolean isAnimationEnabled = suggestionPopup.isAnimationEnabled();
+      if (suggestionPopup.isAttached()) {
+        suggestionPopup.setAnimationEnabled(false);
+        suggestionPopup.hide();
+      }
+
+      suggestionMenu.clearItems();
+
+      for (Suggestion curSuggestion : suggestions) {
+        final SuggestionMenuItem menuItem = new SuggestionMenuItem(
+            curSuggestion, oracle.isDisplayStringHTML());
+        menuItem.setCommand(new Command() {
+          public void execute() {
+            SuggestBox.this.setNewSelection(menuItem);
+          }
+        });
+
+        suggestionMenu.addItem(menuItem);
+      }
+
+      if (selectsFirstItem) {
+        // Select the first item in the suggestion menu.
+        suggestionMenu.selectItem(0);
+      }
+
+      suggestionPopup.showAlignedPopup();
+      suggestionPopup.setAnimationEnabled(isAnimationEnabled);
+    } else {
+      suggestionPopup.hide();
+    }
+  }
+
   private void showSuggestions(String query) {
     oracle.requestSuggestions(new Request(query, limit), callBack);
   }
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
index c03adf9..6a90447 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestOracle.java
@@ -192,68 +192,68 @@
    * display string and a replacement string. The display string is what is
    * shown in the SuggestBox's list of suggestions. The interpretation of the
    * display string depends upon the value of its oracle's
-   * {@link SuggestOracle#isDisplayStringHTML()}. The replacement string is
-   * the string that is entered into the SuggestBox's text box when the
-   * suggestion is selected from the list.
-   *
+   * {@link SuggestOracle#isDisplayStringHTML()}. The replacement string is the
+   * string that is entered into the SuggestBox's text box when the suggestion
+   * is selected from the list.
+   * 
    * <p>
    * Replacement strings are useful when the display form of a suggestion
-   * differs from the input format for the data. For example,
-   * suppose that a company has a webpage with a form which requires the user to
-   * enter the e-mail address of an employee. Since users are likely to know
-   * the name of the employee, a SuggestBox is used to provide name suggestions
-   * as the user types. When the user types the letter <i>f</i>, a suggestion
-   * with the display string <i>foo bar</i> appears. When the user chooses this
-   * suggestion, the replacement string, <i>foobar@company.com</i>, is
-   * entered into the SuggestBox's text box.
+   * differs from the input format for the data. For example, suppose that a
+   * company has a webpage with a form which requires the user to enter the
+   * e-mail address of an employee. Since users are likely to know the name of
+   * the employee, a SuggestBox is used to provide name suggestions as the user
+   * types. When the user types the letter <i>f</i>, a suggestion with the
+   * display string <i>foo bar</i> appears. When the user chooses this
+   * suggestion, the replacement string, <i>foobar@company.com</i>, is entered
+   * into the SuggestBox's text box.
    * </p>
-   *
+   * 
    * <p>
-   * This is an example where the input data format for the suggestion is not
-   * as user-friendly as the display format. In the event that the display
-   * of a suggestion exactly matches the input data format, the
-   * <code>Suggestion</code> interface would be implemented in such a way
-   * that the display string and replacement string would be identical.
+   * This is an example where the input data format for the suggestion is not as
+   * user-friendly as the display format. In the event that the display of a
+   * suggestion exactly matches the input data format, the
+   * <code>Suggestion</code> interface would be implemented in such a way that
+   * the display string and replacement string would be identical.
    * </p>
-   *
+   * 
    * <h3>Associating Data Transfer Objects (DTOs) with Suggestion Objects</h3>
    * Some applications retrieve suggesstions from a server, and may want to send
    * back a DTO with each suggestion. In the previous example, a DTO returned
    * with the suggestion may provide additional contact information about the
    * selected employee, and this information could be used to fill out other
    * fields on the form. To send back a DTO with each suggestion, extend the
-   * <code>Suggestion</code> interface and define a getter method that has
-   * a return value of the DTO's type. Define a class that implements this
+   * <code>Suggestion</code> interface and define a getter method that has a
+   * return value of the DTO's type. Define a class that implements this
    * subinterface and use it to encapsulate each suggestion.
-   *
+   * 
    * <p>
    * To access a suggestion's DTO when the suggestion is selected, add a
-   * {@link SuggestionHandler} to the SuggestBox (see SuggestBox's documentation
-   * for more information). In the
+   * {@link com.google.gwt.event.dom.client.ChangeHandler} to the SuggestBox
+   * (see SuggestBox's documentation for more information). In the
    * <code>SuggestionHandler.onSuggestionSelected(SuggestionEvent event)</code>
    * method, obtain the selected <code>Suggestion</code> object from the
-   * {@link SuggestionEvent} object, and downcast the <code>Suggestion</code>
-   * object to the subinterface. Then, acces the DTO using the DTO getter method
-   * that was defined on the subinterface.
+   * {@link com.google.gwt.event.dom.client.ChangeHandler} object, and downcast
+   * the <code>Suggestion</code> object to the subinterface. Then, acces the DTO
+   * using the DTO getter method that was defined on the subinterface.
    * </p>
    */
   public interface Suggestion {
     /**
      * Gets the display string associated with this suggestion. The
-     * interpretation of the display string depends upon the value of
-     * its oracle's {@link SuggestOracle#isDisplayStringHTML()}.
+     * interpretation of the display string depends upon the value of its
+     * oracle's {@link SuggestOracle#isDisplayStringHTML()}.
      * 
      * @return the display string for this suggestion
      */
     String getDisplayString();
 
     /**
-     * Gets the replacement string associated with this suggestion. When
-     * this suggestion is selected, the replacement string will be entered
-     * into the SuggestBox's text box.
+     * Gets the replacement string associated with this suggestion. When this
+     * suggestion is selected, the replacement string will be entered into the
+     * SuggestBox's text box.
      * 
-     * @return the string to be entered into the SuggestBox's text box when
-     *         this suggestion is selected
+     * @return the string to be entered into the SuggestBox's text box when this
+     *         suggestion is selected
      */
     String getReplacementString();
   }
diff --git a/user/src/com/google/gwt/user/client/ui/SuggestionHandler.java b/user/src/com/google/gwt/user/client/ui/SuggestionHandler.java
index 5121720..112e069 100644
--- a/user/src/com/google/gwt/user/client/ui/SuggestionHandler.java
+++ b/user/src/com/google/gwt/user/client/ui/SuggestionHandler.java
@@ -22,6 +22,7 @@
  *
  * @see SuggestBox
  */
+@Deprecated
 public interface SuggestionHandler extends EventListener {
 
   /**
@@ -31,5 +32,6 @@
    *
    * @param event the object containing information about this event
    */
+  @Deprecated
   void onSuggestionSelected(SuggestionEvent event);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/TabBar.java b/user/src/com/google/gwt/user/client/ui/TabBar.java
index 33df6ab..482658b 100644
--- a/user/src/com/google/gwt/user/client/ui/TabBar.java
+++ b/user/src/com/google/gwt/user/client/ui/TabBar.java
@@ -15,9 +15,26 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.HasAllKeyHandlers;
+import com.google.gwt.event.dom.client.HasClickHandlers;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
+import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
+import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
-
 /**
  * A horizontal bar of folder-style tabs, most commonly used as part of a
  * {@link com.google.gwt.user.client.ui.TabPanel}.
@@ -36,41 +53,40 @@
  * <li>.gwt-TabBar .gwt-TabBarItem { unselected tabs }</li>
  * <li>.gwt-TabBar .gwt-TabBarItem-wrapper { table cell around tab }</li>
  * <li>.gwt-TabBar .gwt-TabBarItem-selected { additional style for selected
- * tabs } </li>
- * <li>.gwt-TabBar .gwt-TabBarItem-wrapper-selected { table cell around
- * selected tab }</li>
- * <li>.gwt-TabBar .gwt-TabBarItem-disabled { additional style for disabled
- * tabs } </li>
- * <li>.gwt-TabBar .gwt-TabBarItem-wrapper-disabled { table cell around
- * disabled tab }</li>
- * </ul>
  * <p>
  * <h3>Example</h3>
  * {@example com.google.gwt.examples.TabBarExample}
  * </p>
  */
+@SuppressWarnings("deprecation")
 public class TabBar extends Composite implements SourcesTabEvents,
+    HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer>,
     ClickListener, KeyboardListener {
+
+  /**
+   * Set of characteristic interfaces supported by {@link TabBar} tabs.
+   * 
+   * Note that this set might expand over time, so implement this interface at
+   * your own risk.
+   */
+  public interface Tab extends HasAllKeyHandlers, HasClickHandlers {
+  }
+
   /**
    * <code>ClickDelegatePanel</code> decorates any widget with the minimal
    * amount of machinery to receive clicks for delegation to the parent.
    * {@link SourcesClickEvents} is not implemented due to the fact that only a
    * single observer is needed.
    */
-  private class ClickDelegatePanel extends Composite {
+  private class ClickDelegatePanel extends Composite implements Tab {
     private SimplePanel focusablePanel;
-    private ClickListener clickDelegate;
-    private KeyboardListener keyDelegate;
     private boolean enabled = true;
 
-    ClickDelegatePanel(Widget child, ClickListener cDelegate,
-        KeyboardListener kDelegate) {
-      this.clickDelegate = cDelegate;
-      this.keyDelegate = kDelegate;
+    ClickDelegatePanel(Widget child) {
 
       focusablePanel = new SimplePanel(FocusPanel.impl.createFocusable());
       focusablePanel.setWidget(child);
-      SimplePanel wrapperWidget = createTabTextWrapper(); 
+      SimplePanel wrapperWidget = createTabTextWrapper();
       if (wrapperWidget == null) {
         initWidget(focusablePanel);
       } else {
@@ -81,6 +97,22 @@
       sinkEvents(Event.ONCLICK | Event.ONKEYDOWN);
     }
 
+    public HandlerRegistration addClickHandler(ClickHandler handler) {
+      return addHandler(handler, ClickEvent.getType());
+    }
+
+    public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+      return addHandler(handler, KeyDownEvent.getType());
+    }
+
+    public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+      return addDomHandler(handler, KeyPressEvent.getType());
+    }
+
+    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+      return addDomHandler(handler, KeyUpEvent.getType());
+    }
+
     public SimplePanel getFocusablePanel() {
       return focusablePanel;
     }
@@ -94,19 +126,23 @@
       if (!enabled) {
         return;
       }
-      
+
       // No need for call to super.
       switch (DOM.eventGetType(event)) {
-
         case Event.ONCLICK:
-          clickDelegate.onClick(this);
+          TabBar.this.selectTabByTabWidget(this);
+          TabBar.this.onClick(this);
           break;
 
         case Event.ONKEYDOWN:
-          keyDelegate.onKeyDown(this, ((char) DOM.eventGetKeyCode(event)),
+          if (((char) DOM.eventGetKeyCode(event)) == KeyCodes.KEY_ENTER) {
+            TabBar.this.selectTabByTabWidget(this);
+          }
+          TabBar.this.onKeyDown(this, (char) event.getKeyCode(),
               KeyboardListenerCollection.getKeyboardModifiers(event));
           break;
       }
+      super.onBrowserEvent(event);
     }
 
     public void setEnabled(boolean enabled) {
@@ -117,7 +153,6 @@
   private static final String STYLENAME_DEFAULT = "gwt-TabBarItem";
   private HorizontalPanel panel = new HorizontalPanel();
   private Widget selectedTab;
-  private TabListenerCollection tabListeners;
 
   /**
    * Creates an empty tab bar.
@@ -145,8 +180,17 @@
     panel.setCellWidth(rest, "100%");
     setStyleName(first.getElement().getParentElement(),
         "gwt-TabBarFirst-wrapper");
-    setStyleName(rest.getElement().getParentElement(),
-        "gwt-TabBarRest-wrapper");
+    setStyleName(rest.getElement().getParentElement(), "gwt-TabBarRest-wrapper");
+  }
+
+  public HandlerRegistration addBeforeSelectionHandler(
+      BeforeSelectionHandler<Integer> handler) {
+    return addHandler(handler, BeforeSelectionEvent.getType());
+  }
+
+  public HandlerRegistration addSelectionHandler(
+      SelectionHandler<Integer> handler) {
+    return addHandler(handler, SelectionEvent.getType());
   }
 
   /**
@@ -171,17 +215,15 @@
   /**
    * Adds a new tab with the specified widget.
    * 
-   * @param widget the new tab's widget.
+   * @param widget the new tab's widget
    */
   public void addTab(Widget widget) {
     insertTab(widget, getTabCount());
   }
 
+  @Deprecated
   public void addTabListener(TabListener listener) {
-    if (tabListeners == null) {
-      tabListeners = new TabListenerCollection();
-    }
-    tabListeners.add(listener);
+    ListenerWrapper.Tab.add(this, listener);
   }
 
   /**
@@ -197,6 +239,24 @@
   }
 
   /**
+   * Gets the given tab.
+   * 
+   * This method is final because the Tab interface will expand. Therefore
+   * it is highly likely that subclasses which implemented this method would end up
+   * breaking.
+   * 
+   * @param index the tab's index
+   * @return the tab wrapper
+   */
+  public final Tab getTab(int index) {
+    if (index >= getTabCount()) {
+      return null;
+    }
+    ClickDelegatePanel p = (ClickDelegatePanel) panel.getWidget(index + 1);
+    return p;
+  }
+
+  /**
    * Gets the number of tabs present.
    * 
    * @return the tab count
@@ -262,16 +322,16 @@
   /**
    * Inserts a new tab at the specified index.
    * 
-   * @param widget widget to be used in the new tab.
-   * @param beforeIndex the index before which this tab will be inserted.
+   * @param widget widget to be used in the new tab
+   * @param beforeIndex the index before which this tab will be inserted
    */
   public void insertTab(Widget widget, int beforeIndex) {
     insertTabWidget(widget, beforeIndex);
   }
 
   /**
-   * Check if a tab is enabled or disabled.  If disabled, the user cannot
-   * select the tab.
+   * Check if a tab is enabled or disabled. If disabled, the user cannot select
+   * the tab.
    * 
    * @param index the index of the tab
    * @return true if the tab is enabled, false if disabled
@@ -282,19 +342,34 @@
     return delPanel.isEnabled();
   }
 
+  /**
+   * @deprecated add a {@link BeforeSelectionHandler} instead. Alternatively, if
+   * you need to access to the individual tabs, add a click handler to each
+   * {@link Tab} element instead.
+   */
   public void onClick(Widget sender) {
-    selectTabByTabWidget(sender);
   }
 
+  /**
+   * @deprecated add a key down handler to the individual tab wrappers instead.
+   */
   public void onKeyDown(Widget sender, char keyCode, int modifiers) {
-    if (keyCode == KeyboardListener.KEY_ENTER) {
-      selectTabByTabWidget(sender);
-    }
   }
 
+  /**
+   * @deprecated this method has been doing nothing for the entire last release,
+   * if what you wanted to do was to listen to key press events on tabs, add the
+   * key press handler to the individual tab wrappers instead.
+   */
   public void onKeyPress(Widget sender, char keyCode, int modifiers) {
   }
 
+  /**
+   * @deprecated this method has been doing nothing for the entire last release,
+   * if what you wanted to do was to listen to key up events on tabs, add the
+   * key up handler to the individual tab wrappers instead.
+   * 
+   */
   public void onKeyUp(Widget sender, char keyCode, int modifiers) {
   }
 
@@ -314,27 +389,25 @@
     panel.remove(toRemove);
   }
 
+  @Deprecated
   public void removeTabListener(TabListener listener) {
-    if (tabListeners != null) {
-      tabListeners.remove(listener);
-    }
+    ListenerWrapper.Tab.remove(this, listener);
   }
 
   /**
    * Programmatically selects the specified tab. Use index -1 to specify that no
    * tab should be selected.
    * 
-   * @param index the index of the tab to be selected.
-   * @return <code>true</code> if successful, <code>false</code> if the
-   *         change is denied by the {@link TabListener}.
+   * @param index the index of the tab to be selected
+   * @return <code>true</code> if successful, <code>false</code> if the change
+   * is denied by the {@link BeforeSelectionHandler}.
    */
   public boolean selectTab(int index) {
     checkTabIndex(index);
+    BeforeSelectionEvent<?> event = BeforeSelectionEvent.fire(this, index);
 
-    if (tabListeners != null) {
-      if (!tabListeners.fireBeforeTabSelected(this, index)) {
-        return false;
-      }
+    if (event != null && event.isCanceled()) {
+      return false;
     }
 
     // Check for -1.
@@ -346,15 +419,12 @@
 
     selectedTab = panel.getWidget(index + 1);
     setSelectionStyle(selectedTab, true);
-
-    if (tabListeners != null) {
-      tabListeners.fireTabSelected(this, index);
-    }
+    SelectionEvent.fire(this, index);
     return true;
   }
 
   /**
-   * Enable or disable a tab.  When disabled, users cannot select the tab.
+   * Enable or disable a tab. When disabled, users cannot select the tab.
    * 
    * @param index the index of the tab to enable or disable
    * @param enabled true to enable, false to disable
@@ -401,7 +471,7 @@
     SimplePanel focusablePanel = delPanel.getFocusablePanel();
 
     // It is not safe to check if the current widget is an instanceof Label and
-    // reuse it here because HTML is an instanceof Label.  Leaving an HTML would
+    // reuse it here because HTML is an instanceof Label. Leaving an HTML would
     // throw off the results of getTabHTML(int).
     focusablePanel.setWidget(new Label(text));
   }
@@ -411,7 +481,7 @@
    * Subclasses can use this method to wrap tabs in decorator panels.
    * 
    * @return a {@link SimplePanel} to wrap the tab contents, or null to leave
-   *         tabs unwrapped
+   * tabs unwrapped
    */
   protected SimplePanel createTabTextWrapper() {
     return null;
@@ -420,13 +490,13 @@
   /**
    * Inserts a new tab at the specified index.
    * 
-   * @param widget widget to be used in the new tab.
-   * @param beforeIndex the index before which this tab will be inserted.
+   * @param widget widget to be used in the new tab
+   * @param beforeIndex the index before which this tab will be inserted
    */
   protected void insertTabWidget(Widget widget, int beforeIndex) {
     checkInsertBeforeTabIndex(beforeIndex);
 
-    ClickDelegatePanel delWidget = new ClickDelegatePanel(widget, this, this);
+    ClickDelegatePanel delWidget = new ClickDelegatePanel(widget);
     delWidget.setStyleName(STYLENAME_DEFAULT);
 
     // Add a11y role "tab"
@@ -481,7 +551,7 @@
    * 
    * @param tabWidget The widget for the tab to be selected
    * @return true if the tab corresponding to the widget for the tab could
-   *         located and selected, false otherwise
+   * located and selected, false otherwise
    */
   private boolean selectTabByTabWidget(Widget tabWidget) {
     int numTabs = panel.getWidgetCount() - 1;
diff --git a/user/src/com/google/gwt/user/client/ui/TabListener.java b/user/src/com/google/gwt/user/client/ui/TabListener.java
index 5a42b70..478fac3 100644
--- a/user/src/com/google/gwt/user/client/ui/TabListener.java
+++ b/user/src/com/google/gwt/user/client/ui/TabListener.java
@@ -22,6 +22,7 @@
  * {@link com.google.gwt.user.client.ui.TabBar} and
  * {@link com.google.gwt.user.client.ui.TabPanel}.
  */
+@Deprecated
 public interface TabListener extends EventListener {
 
   /**
@@ -33,6 +34,7 @@
    * @return <code>false</code> to disallow the selection. If any listener
    *         returns false, then the selection will be disallowed.
    */
+  @Deprecated
   boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex);
 
   /**
@@ -41,5 +43,6 @@
    * @param sender the {@link TabBar} or {@link TabPanel} whose tab was selected
    * @param tabIndex the index of the tab that was selected
    */
+  @Deprecated
   void onTabSelected(SourcesTabEvents sender, int tabIndex);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/TabListenerCollection.java b/user/src/com/google/gwt/user/client/ui/TabListenerCollection.java
index dafb92e..2cf6fce 100644
--- a/user/src/com/google/gwt/user/client/ui/TabListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/TabListenerCollection.java
@@ -23,6 +23,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.TabListener}.
  */
+@Deprecated
 public class TabListenerCollection extends ArrayList<TabListener> {
 
   /**
@@ -31,6 +32,7 @@
    * @param sender the widget sending the event
    * @param tabIndex the index of the tab being selected
    */
+  @Deprecated
   public boolean fireBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
     for (TabListener listener : this) {
       if (!listener.onBeforeTabSelected(sender, tabIndex)) {
@@ -46,6 +48,7 @@
    * @param sender the widget sending the event
    * @param tabIndex the index of the tab being selected
    */
+  @Deprecated
   public void fireTabSelected(SourcesTabEvents sender, int tabIndex) {
     for (TabListener listener : this) {
       listener.onTabSelected(sender, tabIndex);
diff --git a/user/src/com/google/gwt/user/client/ui/TabPanel.java b/user/src/com/google/gwt/user/client/ui/TabPanel.java
index 3083eb2..e15f772 100644
--- a/user/src/com/google/gwt/user/client/ui/TabPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/TabPanel.java
@@ -15,6 +15,14 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
+import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
+import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+
 import java.util.Iterator;
 
 /**
@@ -34,20 +42,21 @@
  * {@link com.google.gwt.user.client.ui.HasWidgets}.
  * </p>
  * 
- * <h3>CSS Style Rules</h3>
- * <ul class='css'>
- * <li>.gwt-TabPanel { the tab panel itself }</li>
- * <li>.gwt-TabPanelBottom { the bottom section of the tab panel (the deck
- * containing the widget) }</li>
- * </ul>
+ * <h3>CSS Style Rules</h3> <ul class='css'> <li>.gwt-TabPanel { the tab panel
+ * itself }</li> <li>.gwt-TabPanelBottom { the bottom section of the tab panel
+ * (the deck containing the widget) }</li> </ul>
  * 
  * <p>
  * <h3>Example</h3>
  * {@example com.google.gwt.examples.TabPanelExample}
  * </p>
  */
+
+//Cannot do anything about tab panel implementing TabListener until next release.
+@SuppressWarnings("deprecation")
 public class TabPanel extends Composite implements TabListener,
-    SourcesTabEvents, HasWidgets, HasAnimation, IndexedPanel {
+    SourcesTabEvents, HasWidgets, HasAnimation, IndexedPanel,
+    HasBeforeSelectionHandlers<Integer>, HasSelectionHandlers<Integer> {
   /**
    * This extension of DeckPanel overrides the public mutator methods to prevent
    * external callers from adding to the state of the DeckPanel.
@@ -179,7 +188,6 @@
 
   private UnmodifiableTabBar tabBar = new UnmodifiableTabBar();
   private TabbedDeckPanel deck = new TabbedDeckPanel(tabBar);
-  private TabListenerCollection tabListeners;
 
   /**
    * Creates an empty tab panel.
@@ -239,11 +247,19 @@
     insert(w, tabWidget, getWidgetCount());
   }
 
+  public HandlerRegistration addBeforeSelectionHandler(
+      BeforeSelectionHandler<Integer> handler) {
+    return addHandler(handler, BeforeSelectionEvent.getType());
+  }
+
+  public HandlerRegistration addSelectionHandler(
+      SelectionHandler<Integer> handler) {
+    return addHandler(handler, SelectionEvent.getType());
+  }
+
+  @Deprecated
   public void addTabListener(TabListener listener) {
-    if (tabListeners == null) {
-      tabListeners = new TabListenerCollection();
-    }
-    tabListeners.add(listener);
+    ListenerWrapper.Tab.add(this, listener);
   }
 
   public void clear() {
@@ -335,18 +351,26 @@
     return deck.iterator();
   }
 
-  public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
-    if (tabListeners != null) {
-      return tabListeners.fireBeforeTabSelected(this, tabIndex);
+  public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
+    if (!onBeforeTabSelected(tabBar, event.getItem().intValue())) {
+      event.cancel();
     }
-    return true;
   }
 
+  @Deprecated
+  public boolean onBeforeTabSelected(SourcesTabEvents sender, int tabIndex) {
+    BeforeSelectionEvent<Integer> event = BeforeSelectionEvent.fire(this, tabIndex);
+    return event == null || !event.isCanceled();
+  }
+
+  public void onSelection(SelectionEvent<Integer> event) {
+    onTabSelected(tabBar, event.getSelectedItem().intValue());
+  }
+
+  @Deprecated
   public void onTabSelected(SourcesTabEvents sender, int tabIndex) {
     deck.showWidget(tabIndex);
-    if (tabListeners != null) {
-      tabListeners.fireTabSelected(this, tabIndex);
-    }
+    SelectionEvent.fire(this, tabIndex);
   }
 
   public boolean remove(int index) {
@@ -364,10 +388,9 @@
     return deck.remove(widget);
   }
 
+  @Deprecated
   public void removeTabListener(TabListener listener) {
-    if (tabListeners != null) {
-      tabListeners.remove(listener);
-    }
+    ListenerWrapper.Tab.remove(this, listener);
   }
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/TableListener.java b/user/src/com/google/gwt/user/client/ui/TableListener.java
index 2180d2d..eab2ec9 100644
--- a/user/src/com/google/gwt/user/client/ui/TableListener.java
+++ b/user/src/com/google/gwt/user/client/ui/TableListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for table events.
  */
+@Deprecated
 public interface TableListener extends EventListener {
 
   /**
@@ -29,5 +30,6 @@
    * @param row the row of the cell being clicked
    * @param cell the index of the cell being clicked
    */
+  @Deprecated
   void onCellClicked(SourcesTableEvents sender, int row, int cell);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/TableListenerCollection.java b/user/src/com/google/gwt/user/client/ui/TableListenerCollection.java
index fcb4f7a..638f7d2 100644
--- a/user/src/com/google/gwt/user/client/ui/TableListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/TableListenerCollection.java
@@ -23,6 +23,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.TableListener}.
  */
+@Deprecated
 public class TableListenerCollection extends ArrayList<TableListener> {
 
   /**
@@ -32,6 +33,7 @@
    * @param row the row of the cell being clicked
    * @param cell the index of the cell being clicked
    */
+  @Deprecated
   public void fireCellClicked(SourcesTableEvents sender, int row, int cell) {
     for (TableListener listener : this) {
       listener.onCellClicked(sender, row, cell);
diff --git a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
index 69da0d0..3a8554e 100644
--- a/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
+++ b/user/src/com/google/gwt/user/client/ui/TextBoxBase.java
@@ -17,6 +17,12 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.HasChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.ui.impl.TextBoxImpl;
@@ -25,7 +31,7 @@
  * Abstract base class for all text entry widgets.
  */
 public class TextBoxBase extends FocusWidget implements SourcesChangeEvents,
-    HasText, HasName {
+    HasChangeHandlers, HasText, HasName, HasValue<String> {
 
   /**
    * Text alignment constant, used in
@@ -69,7 +75,6 @@
 
   private static TextBoxImpl impl = GWT.create(TextBoxImpl.class);
 
-  private ChangeListenerCollection changeListeners;
   private Event currentEvent;
 
   /**
@@ -82,12 +87,26 @@
     super(elem);
   }
 
+  public HandlerRegistration addChangeHandler(ChangeHandler handler) {
+    return addDomHandler(handler, ChangeEvent.getType());
+  }
+
+  @Deprecated
   public void addChangeListener(ChangeListener listener) {
-    if (changeListeners == null) {
-      changeListeners = new ChangeListenerCollection();
-      sinkEvents(Event.ONCHANGE);
+    addChangeHandler(new ListenerWrapper.Change(listener));
+  }
+
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<String> handler) {
+    // Initialization code
+    if (!isEventHandled(ValueChangeEvent.getType())) {
+      addChangeHandler(new ChangeHandler() {
+        public void onChange(ChangeEvent event) {
+          setValue(getText());
+        }
+      });
     }
-    changeListeners.add(listener);
+    return addHandler(handler, ValueChangeEvent.getType());
   }
 
   /**
@@ -142,6 +161,10 @@
     return DOM.getElementProperty(getElement(), "value");
   }
 
+  public String getValue() {
+    return getText();
+  }
+
   /**
    * Determines whether or not the widget is read-only.
    * 
@@ -163,21 +186,15 @@
       // handlers.
       super.onBrowserEvent(event);
       currentEvent = null;
-    } else if (type == Event.ONCHANGE) {
-      // Fire the change event.
-      if (changeListeners != null) {
-        changeListeners.fireChange(this);
-      }
     } else {
       // Handles Focus and Click events.
       super.onBrowserEvent(event);
     }
   }
 
+  @Deprecated
   public void removeChangeListener(ChangeListener listener) {
-    if (changeListeners != null) {
-      changeListeners.remove(listener);
-    }
+    ListenerWrapper.Change.remove(this, listener);
   }
 
   /**
@@ -279,6 +296,18 @@
     DOM.setStyleAttribute(getElement(), "textAlign", align.getTextAlignString());
   }
 
+  public void setValue(String value) {
+    setValue(value, false);
+  }
+
+  public void setValue(String value, boolean fireEvents) {
+    String oldValue = getText();
+    setText(value);
+    if (fireEvents) {
+      ValueChangeEvent.fireIfNotEqual(this, oldValue, value);
+    }
+  }
+
   protected TextBoxImpl getImpl() {
     return impl;
   }
diff --git a/user/src/com/google/gwt/user/client/ui/ToggleButton.java b/user/src/com/google/gwt/user/client/ui/ToggleButton.java
index 77f9a70..efc6595 100644
--- a/user/src/com/google/gwt/user/client/ui/ToggleButton.java
+++ b/user/src/com/google/gwt/user/client/ui/ToggleButton.java
@@ -16,6 +16,8 @@
 
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.ClickHandler;
+
 /**
  * A <code>ToggleButton</code> is a stylish stateful button which allows the
  * user to toggle between <code>up</code> and <code>down</code> states.
@@ -24,10 +26,9 @@
  * <img class='gallery' src='ToggleButton.png'/>
  * </p>
  * 
- * <h3>CSS Style Rules</h3>
- * <ul class="css">
- * <li>.gwt-ToggleButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled {.html-face}</li>
- * </ul>
+ * <h3>CSS Style Rules</h3> <ul class="css"> <li>
+ * .gwt-ToggleButton-up/down/up-hovering/down-hovering/up-disabled/down-disabled
+ * {.html-face}</li> </ul>
  * 
  * <p>
  * <h3>Example</h3> {@example com.google.gwt.examples.ToggleButtonExample}
@@ -64,11 +65,23 @@
    * @param upImage image for the default (up) face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public ToggleButton(Image upImage, ClickListener listener) {
     super(upImage, listener);
   }
 
   /**
+   * Constructor for <code>ToggleButton</code>. The supplied image is used to
+   * construct the default face of the button.
+   * 
+   * @param upImage image for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public ToggleButton(Image upImage, ClickHandler handler) {
+    super(upImage, handler);
+  }
+
+  /**
    * Constructor for <code>ToggleButton</code>.
    * 
    * @param upImage image for the default(up) face of the button
@@ -85,11 +98,23 @@
    * @param downImage image for the down face of the button
    * @param listener clickListener
    */
+  @Deprecated
   public ToggleButton(Image upImage, Image downImage, ClickListener listener) {
     super(upImage, downImage, listener);
   }
 
   /**
+   * Constructor for <code>ToggleButton</code>.
+   * 
+   * @param upImage image for the default(up) face of the button
+   * @param downImage image for the down face of the button
+   * @param handler the click handler
+   */
+  public ToggleButton(Image upImage, Image downImage, ClickHandler handler) {
+    super(upImage, downImage, handler);
+  }
+
+  /**
    * Constructor for <code>ToggleButton</code>. The supplied text is used to
    * construct the default face of the button.
    * 
@@ -106,11 +131,23 @@
    * @param upText the text for the default (up) face of the button
    * @param listener the click listener
    */
+  @Deprecated
   public ToggleButton(String upText, ClickListener listener) {
     super(upText, listener);
   }
 
   /**
+   * Constructor for <code>ToggleButton</code>. The supplied text is used to
+   * construct the default face of the button.
+   * 
+   * @param upText the text for the default (up) face of the button
+   * @param handler the click handler
+   */
+  public ToggleButton(String upText, ClickHandler handler) {
+    super(upText, handler);
+  }
+
+  /**
    * Constructor for <code>ToggleButton</code>.
    * 
    * @param upText the text for the default (up) face of the button
@@ -125,13 +162,13 @@
     // Changes access to public.
     return super.isDown();
   }
-  
+
   @Override
   public void setDown(boolean down) {
     // Changes access to public.
     super.setDown(down);
   }
-  
+
   @Override
   protected void onClick() {
     toggleDown();
diff --git a/user/src/com/google/gwt/user/client/ui/Tree.java b/user/src/com/google/gwt/user/client/ui/Tree.java
index 0a26558..292bdfb 100644
--- a/user/src/com/google/gwt/user/client/ui/Tree.java
+++ b/user/src/com/google/gwt/user/client/ui/Tree.java
@@ -16,6 +16,42 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.HasAllFocusHandlers;
+import com.google.gwt.event.dom.client.HasAllKeyHandlers;
+import com.google.gwt.event.dom.client.HasAllMouseHandlers;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.MouseDownEvent;
+import com.google.gwt.event.dom.client.MouseDownHandler;
+import com.google.gwt.event.dom.client.MouseMoveEvent;
+import com.google.gwt.event.dom.client.MouseMoveHandler;
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.MouseWheelEvent;
+import com.google.gwt.event.dom.client.MouseWheelHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.HasCloseHandlers;
+import com.google.gwt.event.logical.shared.HasOpenHandlers;
+import com.google.gwt.event.logical.shared.HasSelectionHandlers;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.event.logical.shared.SelectionEvent;
+import com.google.gwt.event.logical.shared.SelectionHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
@@ -47,7 +83,9 @@
  * </p>
  */
 public class Tree extends Widget implements HasWidgets, SourcesTreeEvents,
-    HasFocus, HasAnimation {
+    HasFocus, HasAnimation, HasAllKeyHandlers, HasAllFocusHandlers,
+    HasSelectionHandlers<TreeItem>, HasOpenHandlers<TreeItem>,
+    HasCloseHandlers<TreeItem>, SourcesMouseEvents, HasAllMouseHandlers {
 
   /**
    * Provides images to support the the deprecated case where a url prefix is
@@ -76,13 +114,13 @@
 
       @Override
       public void applyTo(ImagePrototypeElement img) {
-        DOM.setImgSrc(img.<Element>cast(), imageUrl);
+        DOM.setImgSrc(img.<Element> cast(), imageUrl);
       }
 
       @Override
       public ImagePrototypeElement createElement() {
         Element img = DOM.createImg();
-        applyTo(img.<ImagePrototypeElement>cast());
+        applyTo(img.<ImagePrototypeElement> cast());
         return img.cast();
       }
 
@@ -145,10 +183,10 @@
       case OTHER_KEY_RIGHT:
       case OTHER_KEY_UP:
       case OTHER_KEY_LEFT:
-      case KeyboardListener.KEY_DOWN:
-      case KeyboardListener.KEY_RIGHT:
-      case KeyboardListener.KEY_UP:
-      case KeyboardListener.KEY_LEFT:
+      case KeyCodes.KEY_DOWN:
+      case KeyCodes.KEY_RIGHT:
+      case KeyCodes.KEY_UP:
+      case KeyCodes.KEY_LEFT:
         return true;
       default:
         return false;
@@ -162,23 +200,23 @@
   private static int standardizeKeycode(int code) {
     switch (code) {
       case OTHER_KEY_DOWN:
-        code = KeyboardListener.KEY_DOWN;
+        code = KeyCodes.KEY_DOWN;
         break;
       case OTHER_KEY_RIGHT:
-        code = KeyboardListener.KEY_RIGHT;
+        code = KeyCodes.KEY_RIGHT;
         break;
       case OTHER_KEY_UP:
-        code = KeyboardListener.KEY_UP;
+        code = KeyCodes.KEY_UP;
         break;
       case OTHER_KEY_LEFT:
-        code = KeyboardListener.KEY_LEFT;
+        code = KeyCodes.KEY_LEFT;
         break;
     }
     if (LocaleInfo.getCurrentLocale().isRTL()) {
-      if (code == KeyboardListener.KEY_RIGHT) {
-        code = KeyboardListener.KEY_LEFT;
-      } else if (code == KeyboardListener.KEY_LEFT) {
-        code = KeyboardListener.KEY_RIGHT;
+      if (code == KeyCodes.KEY_RIGHT) {
+        code = KeyCodes.KEY_LEFT;
+      } else if (code == KeyCodes.KEY_LEFT) {
+        code = KeyCodes.KEY_RIGHT;
       }
     }
     return code;
@@ -188,18 +226,21 @@
    * Map of TreeItem.widget -> TreeItem.
    */
   private final Map<Widget, TreeItem> childWidgets = new HashMap<Widget, TreeItem>();
+
   private TreeItem curSelection;
+
   private Element focusable;
-  private FocusListenerCollection focusListeners;
+
   private TreeImages images;
+
   private String indentValue;
+
   private boolean isAnimationEnabled = false;
-  private KeyboardListenerCollection keyboardListeners;
+
   private boolean lastWasKeyDown;
 
-  private TreeListenerCollection listeners;
-  private MouseListenerCollection mouseListeners = null;
   private TreeItem root;
+
   private boolean useLeafImages;
 
   /**
@@ -244,11 +285,21 @@
     addItem(widget);
   }
 
+  public HandlerRegistration addBlurHandler(BlurHandler handler) {
+    return addDomHandler(handler, BlurEvent.getType());
+  }
+
+  public HandlerRegistration addCloseHandler(CloseHandler<TreeItem> handler) {
+    return addHandler(handler, CloseEvent.getType());
+  }
+
+  public HandlerRegistration addFocusHandler(FocusHandler handler) {
+    return addDomHandler(handler, FocusEvent.getType());
+  }
+
+  @Deprecated
   public void addFocusListener(FocusListener listener) {
-    if (focusListeners == null) {
-      focusListeners = new FocusListenerCollection();
-    }
-    focusListeners.add(listener);
+    ListenerWrapper.Focus.add(this, listener);
   }
 
   /**
@@ -277,30 +328,70 @@
    * Adds a new tree item containing the specified widget.
    * 
    * @param widget the widget to be added
+   * @return the new item
    */
   public TreeItem addItem(Widget widget) {
     return root.addItem(widget);
   }
 
+  @Deprecated
   public void addKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners == null) {
-      keyboardListeners = new KeyboardListenerCollection();
-    }
-    keyboardListeners.add(listener);
+    ListenerWrapper.Keyboard.add(this, listener);
   }
 
+  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
+    return addDomHandler(handler, KeyDownEvent.getType());
+  }
+
+  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
+    return addDomHandler(handler, KeyPressEvent.getType());
+  }
+
+  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
+    return addDomHandler(handler, KeyUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
+    return addHandler(handler,MouseDownEvent.getType());
+  }
+
+  @Deprecated
   public void addMouseListener(MouseListener listener) {
-    if (mouseListeners == null) {
-      mouseListeners = new MouseListenerCollection();
-    }
-    mouseListeners.add(listener);
+    ListenerWrapper.Mouse.add(this, listener);
   }
 
+  public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
+    return addDomHandler(handler,MouseMoveEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
+    return addDomHandler(handler,MouseOutEvent.getType());
+  }
+
+  public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
+    return addDomHandler(handler,MouseOverEvent.getType());
+  }
+
+  public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
+    return addDomHandler(handler,MouseUpEvent.getType());
+  }
+
+  public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
+    return addDomHandler(handler,MouseWheelEvent.getType());
+  }
+
+  public final HandlerRegistration addOpenHandler(OpenHandler<TreeItem> handler) {
+    return addHandler(handler, OpenEvent.getType());
+  }
+
+  public HandlerRegistration addSelectionHandler(
+      SelectionHandler<TreeItem> handler) {
+    return addHandler(handler, SelectionEvent.getType());
+  }
+
+  @Deprecated
   public void addTreeListener(TreeListener listener) {
-    if (listeners == null) {
-      listeners = new TreeListenerCollection();
-    }
-    listeners.add(listener);
+    ListenerWrapper.Tree.add(this, listener);
   }
 
   /**
@@ -429,10 +520,6 @@
       }
 
       case Event.ONMOUSEDOWN: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-
         // Currently, the way we're using image bundles causes extraneous events
         // to be sunk on individual items' open/close images. This leads to an
         // extra event reaching the Tree, which we will ignore here.
@@ -441,49 +528,6 @@
         }
         break;
       }
-
-      case Event.ONMOUSEUP: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-      }
-
-      case Event.ONMOUSEMOVE: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-      }
-
-      case Event.ONMOUSEOVER: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-      }
-
-      case Event.ONMOUSEOUT: {
-        if (mouseListeners != null) {
-          mouseListeners.fireMouseEvent(this, event);
-        }
-        break;
-      }
-
-      case Event.ONFOCUS:
-        if (focusListeners != null) {
-          focusListeners.fireFocusEvent(this, event);
-        }
-        break;
-
-      case Event.ONBLUR: {
-        if (focusListeners != null) {
-          focusListeners.fireFocusEvent(this, event);
-        }
-
-        break;
-      }
-
       case Event.ONKEYDOWN: {
         keyboardNavigation(event);
         lastWasKeyDown = true;
@@ -499,7 +543,7 @@
       }
 
       case Event.ONKEYUP: {
-        if (DOM.eventGetKeyCode(event) == KeyboardListener.KEY_TAB) {
+        if (DOM.eventGetKeyCode(event) == KeyCodes.KEY_TAB) {
           ArrayList<Element> chain = new ArrayList<Element>();
           collectElementChain(chain, getElement(), DOM.eventGetTarget(event));
           TreeItem item = findItemByChain(chain, 0, root);
@@ -507,7 +551,6 @@
             setSelectedItem(item, true);
           }
         }
-
         lastWasKeyDown = false;
         break;
       }
@@ -519,18 +562,12 @@
         if (isArrowKey(DOM.eventGetKeyCode(event))) {
           DOM.eventCancelBubble(event, true);
           DOM.eventPreventDefault(event);
+          return;
         }
       }
-      // Intentional fall through
-      case Event.ONKEYPRESS: {
-        if (keyboardListeners != null) {
-          keyboardListeners.fireKeyboardEvent(this, event);
-        }
-        break;
-      }
     }
 
-    // We must call SynthesizedWidget's implementation for all other events.
+    // We must call super for all handlers.
     super.onBrowserEvent(event);
   }
 
@@ -546,10 +583,9 @@
     return true;
   }
 
+  @Deprecated
   public void removeFocusListener(FocusListener listener) {
-    if (focusListeners != null) {
-      focusListeners.remove(listener);
-    }
+    ListenerWrapper.Focus.remove(this, listener);
   }
 
   /**
@@ -570,16 +606,19 @@
     }
   }
 
+  @Deprecated
   public void removeKeyboardListener(KeyboardListener listener) {
-    if (keyboardListeners != null) {
-      keyboardListeners.remove(listener);
-    }
+    ListenerWrapper.Keyboard.remove(this, listener);
   }
 
+  @Deprecated
+  public void removeMouseListener(MouseListener listener) {
+    ListenerWrapper.Mouse.remove(this, listener);
+  }
+
+  @Deprecated
   public void removeTreeListener(TreeListener listener) {
-    if (listeners != null) {
-      listeners.remove(listener);
-    }
+    ListenerWrapper.Tree.remove(this, listener);
   }
 
   public void setAccessKey(char key) {
@@ -650,6 +689,8 @@
 
   /**
    * Iterator of tree items.
+   * 
+   * @return the iterator
    */
   public Iterator<TreeItem> treeItemIterator() {
     List<TreeItem> accum = new ArrayList<TreeItem>();
@@ -715,9 +756,11 @@
     widget.setParent(this);
   }
 
-  void fireStateChanged(TreeItem item) {
-    if (listeners != null) {
-      listeners.fireItemStateChanged(item);
+  void fireStateChanged(TreeItem item, boolean open) {
+    if (open) {
+      OpenEvent.fire(this, item);
+    } else {
+      CloseEvent.fire(this, item);
     }
   }
 
@@ -953,19 +996,19 @@
       int code = DOM.eventGetKeyCode(event);
 
       switch (standardizeKeycode(code)) {
-        case KeyboardListener.KEY_UP: {
+        case KeyCodes.KEY_UP: {
           moveSelectionUp(curSelection);
           break;
         }
-        case KeyboardListener.KEY_DOWN: {
+        case KeyCodes.KEY_DOWN: {
           moveSelectionDown(curSelection, true);
           break;
         }
-        case KeyboardListener.KEY_LEFT: {
+        case KeyCodes.KEY_LEFT: {
           maybeCollapseTreeItem();
           break;
         }
-        case KeyboardListener.KEY_RIGHT: {
+        case KeyCodes.KEY_RIGHT: {
           maybeExpandTreeItem();
           break;
         }
@@ -1119,7 +1162,6 @@
     if (curSelection != null) {
       curSelection.setSelected(false);
     }
-
     curSelection = item;
 
     if (moveFocus && curSelection != null) {
@@ -1127,8 +1169,8 @@
 
       // Select the item and fire the selection event.
       curSelection.setSelected(true);
-      if (fireEvents && (listeners != null)) {
-        listeners.fireItemSelected(curSelection);
+      if (fireEvents) {
+        SelectionEvent.fire(this, curSelection);
       }
     }
   }
diff --git a/user/src/com/google/gwt/user/client/ui/TreeItem.java b/user/src/com/google/gwt/user/client/ui/TreeItem.java
index 8b6c66f..c3c808f 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeItem.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeItem.java
@@ -521,8 +521,8 @@
   /**
    * Selects or deselects this item.
    * 
-   * @param selected <code>true</code> to select the item, <code>false</code>
-   *          to deselect it
+   * @param selected <code>true</code> to select the item, <code>false</code> to
+   *          deselect it
    */
   public void setSelected(boolean selected) {
     if (this.selected == selected) {
@@ -546,7 +546,6 @@
    * 
    * @param open whether the item is open
    * @param fireEvents <code>true</code> to allow open/close events to be
-   *          fired
    */
   public void setState(boolean open, boolean fireEvents) {
     if (open && getChildCount() == 0) {
@@ -557,10 +556,10 @@
     if (this.open != open) {
       this.open = open;
       updateState(true, true);
-    }
 
-    if (fireEvents && tree != null) {
-      tree.fireStateChanged(this);
+      if (fireEvents && tree != null) {
+        tree.fireStateChanged(this, open);
+      }
     }
   }
 
diff --git a/user/src/com/google/gwt/user/client/ui/TreeListener.java b/user/src/com/google/gwt/user/client/ui/TreeListener.java
index 03598ec..e879df6 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeListener.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeListener.java
@@ -20,6 +20,7 @@
 /**
  * Event listener interface for tree events.
  */
+@Deprecated
 public interface TreeListener extends EventListener {
 
   /**
@@ -27,6 +28,7 @@
    * 
    * @param item the item being selected.
    */
+  @Deprecated
   void onTreeItemSelected(TreeItem item);
 
   /**
@@ -34,5 +36,6 @@
    * 
    * @param item the item whose state is changing.
    */
+  @Deprecated
   void onTreeItemStateChanged(TreeItem item);
 }
diff --git a/user/src/com/google/gwt/user/client/ui/TreeListenerCollection.java b/user/src/com/google/gwt/user/client/ui/TreeListenerCollection.java
index d6d4f27..92a2320 100644
--- a/user/src/com/google/gwt/user/client/ui/TreeListenerCollection.java
+++ b/user/src/com/google/gwt/user/client/ui/TreeListenerCollection.java
@@ -22,6 +22,7 @@
  * subclass of {@link ArrayList} assumes that all objects added to it will be of
  * type {@link com.google.gwt.user.client.ui.ClickListener}.
  */
+@Deprecated
 public class TreeListenerCollection extends ArrayList<TreeListener> {
 
   /**
@@ -29,6 +30,7 @@
    * 
    * @param item the tree item being selected.
    */
+  @Deprecated
   public void fireItemSelected(TreeItem item) {
     for (TreeListener listener : this) {
       listener.onTreeItemSelected(item);
@@ -40,6 +42,7 @@
    * 
    * @param item the tree item whose state has changed.
    */
+  @Deprecated
   public void fireItemStateChanged(TreeItem item) {
     for (TreeListener listener : this) {
       listener.onTreeItemStateChanged(item);
diff --git a/user/src/com/google/gwt/user/client/ui/Widget.java b/user/src/com/google/gwt/user/client/ui/Widget.java
index 597a712..8a7411e 100644
--- a/user/src/com/google/gwt/user/client/ui/Widget.java
+++ b/user/src/com/google/gwt/user/client/ui/Widget.java
@@ -15,6 +15,12 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.DomEvent;
+import com.google.gwt.event.logical.shared.HasHandlers;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventListener;
@@ -24,11 +30,29 @@
  * support for receiving events from the browser and being added directly to
  * {@link com.google.gwt.user.client.ui.Panel panels}.
  */
-public class Widget extends UIObject implements EventListener {
-
+public class Widget extends UIObject implements EventListener, HasHandlers {
+  /**
+   * A bit-map of the events that should be sunk when the widget is attached to
+   * the DOM. (We delay the sinking of events to improve startup performance.)
+   * When the widget is attached, this is set to -1
+   * <p>
+   * Package protected to allow Composite to see it.
+   */
+  int eventsToSink;
   private boolean attached;
+
   private Object layoutData;
   private Widget parent;
+  private HandlerManager handlerManager;
+
+  /**
+   * Returns this widget's {@link HandlerManager} used for event management.
+   * 
+   * @return the handler manager
+   */
+  public final HandlerManager getHandlers() {
+    return handlerManager;
+  }
 
   /**
    * Gets this widget's parent panel.
@@ -50,7 +74,22 @@
     return attached;
   }
 
-  public void onBrowserEvent(Event event) {
+  /**
+   * Returns true if the widget has handlers of the given type. Used by some
+   * widget implementations to be lazy about initializing dom event handlers
+   * (e.g. a click handler on a checkbox) until the first relevant logical event
+   * handler is attached (e.g. in the <code>addValueChangeHandler</code>
+   * method).
+   * 
+   * @param type the event type
+   * @return true if the widget has handlers of the give type
+   */
+  public boolean isEventHandled(GwtEvent.Type<?> type) {
+    return handlerManager != null && handlerManager.isEventHandled(type);
+  }
+
+  public void onBrowserEvent(Event nativeEvent) {
+    DomEvent.fireNativeEvent(nativeEvent, handlerManager);
   }
 
   /**
@@ -70,8 +109,64 @@
   }
 
   /**
+   * Overridden to defer the call to super.sinkEvents until the first time this
+   * widget is attached to the dom, as a performance enhancement. Subclasses
+   * wishing to customize sinkEvents can preserve this deferred sink behavior
+   * by putting their implementation behind a check of {@link #isOrWasAttached()}:
+   * 
+   * <pre>
+   * {@literal @}Override
+   * public void sinkEvents(int eventBitsToAdd) {
+   *   if (isOrWasAttached()) {
+   *     /{@literal *} customized sink code goes here {@literal *}/
+   *   } else {
+   *     super.sinkEvents(eventBitsToAdd);
+   *  }
+   *} </pre>
+   */
+  @Override
+  public void sinkEvents(int eventBitsToAdd) {
+    if (isOrWasAttached()) {
+      super.sinkEvents(eventBitsToAdd);
+    } else {
+      eventsToSink |= eventBitsToAdd;
+    }
+  }
+
+  /**
+   * Adds a native event handler to the widget and sinks the corresponding
+   * native event. If you do not want to sink the native event, use the generic
+   * addHandler method instead.
+   * 
+   * @param <H> the type of handler to add
+   * @param type the event key
+   * @param handler the handler
+   * @return {@link HandlerRegistration} used to remove the handler
+   */
+  protected final <H extends EventHandler> HandlerRegistration addDomHandler(
+      final H handler, DomEvent.Type<H> type) {
+    assert handler != null : "handler must not be null";
+    assert type != null : "type must not be null";
+    sinkEvents(type.getEventToSink());
+    return ensureHandlers().addHandler(type, handler);
+  }
+
+  /**
+   * Adds this handler to the widget.
+   * 
+   * @param <H> the type of handler to add
+   * @param type the event type
+   * @param handler the handler
+   * @return {@link HandlerRegistration} used to remove the handler
+   */
+  protected final <H extends EventHandler> HandlerRegistration addHandler(
+      final H handler, GwtEvent.Type<H> type) {
+    return ensureHandlers().addHandler(type, handler);
+  }
+
+  /**
    * If a widget implements HasWidgets, it must override this method and call
-   * onAttach() for each of its child widgets.
+   * {@link #onAttach()} for each of its child widgets.
    * 
    * @see Panel#onAttach()
    */
@@ -88,6 +183,27 @@
   }
 
   /**
+   * Fires an event. Usually used when passing an event from one source to
+   * another.
+   * 
+   * @param event the event
+   */
+  protected void fireEvent(GwtEvent<?> event) {
+    if (handlerManager != null) {
+      handlerManager.fireEvent(event);
+    }
+  }
+
+  /**
+   * Has this widget ever been attached?
+   * 
+   * @return true if this widget ever been attached to the DOM, false otherwise
+   */
+  protected final boolean isOrWasAttached() {
+    return eventsToSink == -1;
+  }
+
+  /**
    * This method is called when a widget is attached to the browser's document.
    * To receive notification after a Widget has been added to the document,
    * override the {@link #onLoad} method.
@@ -107,7 +223,14 @@
     }
 
     attached = true;
+
+    // Event hookup code
     DOM.setEventListener(getElement(), this);
+    int bitsToAdd = eventsToSink;
+    eventsToSink = -1;
+    if (bitsToAdd > 0) {
+      sinkEvents(bitsToAdd);
+    }
     doAttachChildren();
 
     // onLoad() gets called only *after* all of the children are attached and
@@ -164,6 +287,16 @@
   }
 
   /**
+   * Ensures the existence of the handler manager.
+   * 
+   * @return the handler manager
+   * */
+  HandlerManager ensureHandlers() {
+    return handlerManager == null ? handlerManager = new HandlerManager(this)
+        : handlerManager;
+  }
+
+  /**
    * Gets the panel-defined layout data associated with this widget.
    * 
    * @return the widget's layout data
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
index 569695c..eecd5a8 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
@@ -76,7 +76,7 @@
         // Weird: this code has the context of the script frame, but we need the
         // event from the edit iframe's window.
         var evt = elem.contentWindow.event;
-        elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+        elem.__listener.@com.google.gwt.user.client.ui.Widget::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
       }
     };
 
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java
index cbb859b..96d0439 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java
@@ -167,7 +167,7 @@
 
       // Dispatch the event.
       if (elem.__listener) {
-        elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+        elem.__listener.@com.google.gwt.user.client.ui.Widget::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
       }
     };
 
@@ -187,13 +187,13 @@
     // there interferes with focus.
     elem.onfocus = function(evt) {
       if (elem.__listener) {
-        elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+        elem.__listener.@com.google.gwt.user.client.ui.Widget::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
       }
     };
 
     elem.onblur = function(evt) {
       if (elem.__listener) {
-        elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+        elem.__listener.@com.google.gwt.user.client.ui.Widget::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
       }
     };
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
index 0b688b6..1b8be0c 100644
--- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
+++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplStandard.java
@@ -267,7 +267,7 @@
 
     elem.__gwt_handler = function(evt) {
       if (elem.__listener) {
-        elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
+        elem.__listener.@com.google.gwt.user.client.ui.Widget::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt);
       }
     };
 
diff --git a/user/src/com/google/gwt/user/server/rpc/RPCRequest.java b/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
index df4d846..8663454 100644
--- a/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
+++ b/user/src/com/google/gwt/user/server/rpc/RPCRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -65,12 +65,50 @@
 
   /**
    * Returns the {@link SerializationPolicy} used to decode this request. This
-   * is also the <code>SerializationPolicy</code> that should be used to
-   * encode responses.
+   * is also the <code>SerializationPolicy</code> that should be used to encode
+   * responses.
    * 
    * @return {@link SerializationPolicy} used to decode this request
    */
   public SerializationPolicy getSerializationPolicy() {
     return serializationPolicy;
   }
+
+  /**
+   * For debugging use only.
+   */
+  @Override
+  public String toString() {
+    StringBuilder callSignature = new StringBuilder();
+
+    // Add the class and method names
+    callSignature.append(method.getDeclaringClass().getName());
+    callSignature.append('.');
+    callSignature.append(method.getName());
+
+    // Add the list of parameters
+    callSignature.append('(');
+    for (Object param : parameters) {
+      if (param instanceof String) {
+        // Put it within quotes and escape quotes, for readability
+        callSignature.append('"');
+        String strParam = (String) param;
+        String escapedStrParam = strParam.replaceAll("\\\"", "\\\\\"");
+        callSignature.append(escapedStrParam);
+        callSignature.append('"');
+      } else {
+        // We assume that anyone who wants to use this method will implement
+        // toString on his serializable objects.
+        callSignature.append(param.toString());
+      }
+      callSignature.append(", ");
+    }
+
+    // Remove the last ", "
+    int length = callSignature.length();
+    callSignature.delete(length - 2, length);
+    callSignature.append(')');
+
+    return callSignature.toString();
+  }
 }
diff --git a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
index 7e11b43..c43128c 100644
--- a/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
+++ b/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
@@ -162,6 +162,7 @@
   public String processCall(String payload) throws SerializationException {
     try {
       RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass(), this);
+      onAfterRequestDeserialized(rpcRequest);
       return RPC.invokeAndEncodeResponse(this, rpcRequest.getMethod(),
           rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
     } catch (IncompatibleRemoteServiceException ex) {
@@ -262,15 +263,15 @@
   /**
    * Override this method to control what should happen when an exception
    * escapes the {@link #processCall(String)} method. The default implementation
-   * will log the failure and send a generic failure response to the client.<p/>
-   * 
+   * will log the failure and send a generic failure response to the client.
+   * <p>
    * An "expected failure" is an exception thrown by a service method that is
    * declared in the signature of the service method. These exceptions are
    * serialized back to the client, and are not passed to this method. This
    * method is called only for exceptions or errors that are not part of the
    * service method's signature, or that result from SecurityExceptions,
-   * SerializationExceptions, or other failures within the RPC framework.<p/>
-   * 
+   * SerializationExceptions, or other failures within the RPC framework.
+   * <p>
    * Note that if the desired behavior is to both send the GENERIC_FAILURE_MSG
    * response AND to rethrow the exception, then this method should first send
    * the GENERIC_FAILURE_MSG response itself (using getThreadLocalResponse), and
@@ -286,9 +287,9 @@
   }
 
   /**
-   * Gets the <code>HttpServletRequest</code> object for the current call. It
-   * is stored thread-locally so that simultaneous invocations can have
-   * different request objects.
+   * Gets the <code>HttpServletRequest</code> object for the current call. It is
+   * stored thread-locally so that simultaneous invocations can have different
+   * request objects.
    */
   protected final HttpServletRequest getThreadLocalRequest() {
     return perThreadRequest.get();
@@ -304,6 +305,14 @@
   }
 
   /**
+   * Override this method to examine the deserialized version of the request
+   * before the call to the servlet method is made. The default implementation
+   * does nothing and need not be called by subclasses.
+   */
+  protected void onAfterRequestDeserialized(RPCRequest rpcRequest) {
+  }
+
+  /**
    * Override this method to examine the serialized response that will be
    * returned to the client. The default implementation does nothing and need
    * not be called by subclasses.
diff --git a/user/test/com/google/gwt/core/ext/LinkerSuite.java b/user/test/com/google/gwt/core/ext/LinkerSuite.java
index eacccab..f679fde 100644
--- a/user/test/com/google/gwt/core/ext/LinkerSuite.java
+++ b/user/test/com/google/gwt/core/ext/LinkerSuite.java
@@ -16,7 +16,6 @@
 package com.google.gwt.core.ext;
 
 import com.google.gwt.core.ext.test.IFrameLinkerTest;
-import com.google.gwt.core.ext.test.LinkerTest;
 import com.google.gwt.core.ext.test.XSLinkerTest;
 import com.google.gwt.junit.tools.GWTTestSuite;
 
@@ -37,7 +36,7 @@
      *  Note: Single-script linking is disabled by default, because
      *  it only works when the test is run for a single permutation.
      */
-    //suite.addTestSuite(SingleScriptLinkerTest.class);
+    // suite.addTestSuite(SingleScriptLinkerTest.class);
     // $JUnit-END$
     return suite;
   }
diff --git a/user/test/com/google/gwt/dev/jjs/test/HostedTest.java b/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
index a28f341..7d88116 100644
--- a/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/HostedTest.java
@@ -14,9 +14,7 @@
  * the License.
  */
 /**********************
- *                    *
- *   DO NOT FORMAT    *
- *                    *
+ * * DO NOT FORMAT * *
  **********************/
 package com.google.gwt.dev.jjs.test;
 
@@ -369,32 +367,32 @@
   public void testJsniParamUnboxedPrimitives() {
     class Inner {
       native boolean nativeJsniParamUnboxedBoolean(boolean param) /*-{
-        return (param == true);        
-      }-*/;
+    return (param == true);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedByte(byte param) /*-{
-        return (param == 99);
-      }-*/;
+    return (param == 99);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedCharacter(char param) /*-{
-        return (param == 77);
-      }-*/;
+    return (param == 77);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedDouble(double param) /*-{
-        return (param == 1234.56789);
-      }-*/;
+    return (param == 1234.56789);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedFloat(float param) /*-{
-        return (param == 1234.5);
-      }-*/;
+    return (param == 1234.5);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedInteger(int param) /*-{
-        return (param == 9876543);
-      }-*/;
+    return (param == 9876543);
+  }-*/;
 
       native boolean nativeJsniParamUnboxedShort(short param) /*-{
-        return (param == 1234);
-      }-*/;
+    return (param == 1234);
+  }-*/;
     }
     Inner inner = new Inner();
 
@@ -417,37 +415,37 @@
   public void testJsniPassthroughPrimitives() {
     class Inner {
       native boolean nativeBoolean(boolean param) /*-{
-         return param;        
-      }-*/;
+    return param;
+  }-*/;
 
       native byte nativeByte(byte param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       native char nativeCharacter(char param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       native double nativeDouble(double param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       native float nativeFloat(float param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       native int nativeInteger(int param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       @UnsafeNativeLong
       native long nativeLong(long param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
 
       native short nativeShort(short param) /*-{
-        return param;
-      }-*/;
+    return param;
+  }-*/;
     }
     Inner inner = new Inner();
 
@@ -460,7 +458,7 @@
     assertEquals("nativeByte", inner.nativeByte((byte) 127), (byte) 127);
     assertEquals("nativeByte", inner.nativeByte((byte) -127), (byte) -127);
     assertEquals("nativeByte", inner.nativeByte(Byte.MAX_VALUE), Byte.MAX_VALUE);
-    assertEquals("nativeByte", inner.nativeByte(Byte.MIN_VALUE), Byte.MIN_VALUE);    
+    assertEquals("nativeByte", inner.nativeByte(Byte.MIN_VALUE), Byte.MIN_VALUE);
 
     assertEquals("nativeCharacter", inner.nativeCharacter((char) 0), (char) 0);
     assertEquals("nativeCharacter", inner.nativeCharacter((char) 1), (char) 1);
@@ -472,7 +470,7 @@
     assertEquals("nativeCharacter", inner.nativeCharacter(Character.MAX_VALUE),
         Character.MAX_VALUE);
     assertEquals("nativeCharacter", inner.nativeCharacter(Character.MIN_VALUE),
-        Character.MIN_VALUE);    
+        Character.MIN_VALUE);
 
     assertEquals("nativeDouble", inner.nativeDouble(0.0), 0.0);
     assertEquals("nativeDouble", inner.nativeDouble(1.0), 1.0);
@@ -485,7 +483,7 @@
         Double.MAX_VALUE);
     assertEquals("nativeDouble MIN", inner.nativeDouble(Double.MIN_VALUE),
         Double.MIN_VALUE);
-    
+
     assertEquals("nativeFloat", inner.nativeFloat((float) 0.0), (float) 0.0);
     assertEquals("nativeFloat", inner.nativeFloat((float) 1.0), (float) 1.0);
     assertEquals("nativeFloat", inner.nativeFloat((float) -1.0), (float) -1.0);
@@ -497,17 +495,17 @@
         Float.MAX_VALUE);
     assertEquals("nativeFloat", inner.nativeFloat(Float.MIN_VALUE),
         Float.MIN_VALUE);
-    
+
     assertEquals("nativeInteger", inner.nativeInteger(0), 0);
     assertEquals("nativeInteger", inner.nativeInteger(1), 1);
     assertEquals("nativeInteger", inner.nativeInteger(-1), -1);
     assertEquals("nativeInteger", inner.nativeInteger(2147483647), 2147483647);
     assertEquals("nativeInteger", inner.nativeInteger(-2147483647), -2147483647);
-    assertEquals("nativeInteger MAX", inner.nativeInteger(Integer.MAX_VALUE), 
+    assertEquals("nativeInteger MAX", inner.nativeInteger(Integer.MAX_VALUE),
         Integer.MAX_VALUE);
-    assertEquals("nativeInteger MIN", inner.nativeInteger(Integer.MIN_VALUE), 
+    assertEquals("nativeInteger MIN", inner.nativeInteger(Integer.MIN_VALUE),
         Integer.MIN_VALUE);
-    
+
     assertEquals("nativeLong", inner.nativeLong(0L), 0L);
     assertEquals("nativeLong", inner.nativeLong(1L), 1L);
     assertEquals("nativeLong", inner.nativeLong(-1L), -1L);
@@ -515,10 +513,8 @@
         9223372036854775807L);
     assertEquals("nativeLong", inner.nativeLong(-9223372036854775807L),
         -9223372036854775807L);
-    assertEquals("nativeLong", inner.nativeLong(Long.MAX_VALUE), 
-        Long.MAX_VALUE);
-    assertEquals("nativeLong", inner.nativeLong(Long.MIN_VALUE), 
-        Long.MIN_VALUE);    
+    assertEquals("nativeLong", inner.nativeLong(Long.MAX_VALUE), Long.MAX_VALUE);
+    assertEquals("nativeLong", inner.nativeLong(Long.MIN_VALUE), Long.MIN_VALUE);
 
     assertEquals("nativeShort", inner.nativeShort((short) 0), (short) 0);
     assertEquals("nativeShort", inner.nativeShort((short) 1), (short) 1);
@@ -526,10 +522,10 @@
     assertEquals("nativeShort", inner.nativeShort((short) 32767), (short) 32767);
     assertEquals("nativeShort", inner.nativeShort((short) -32767),
         (short) -32767);
-    assertEquals("nativeShort MAX", inner.nativeShort(Short.MAX_VALUE), 
+    assertEquals("nativeShort MAX", inner.nativeShort(Short.MAX_VALUE),
         Short.MAX_VALUE);
-    assertEquals("nativeShort MIN", inner.nativeLong(Short.MIN_VALUE), 
-        Short.MIN_VALUE);        
+    assertEquals("nativeShort MIN", inner.nativeLong(Short.MIN_VALUE),
+        Short.MIN_VALUE);
   }
 
   /**
@@ -538,32 +534,32 @@
   public void testJsniReturnUnboxedPrimitives() {
     class Inner {
       native boolean nativeJsniReturnUnboxedBoolean() /*-{
-        return true;        
-      }-*/;
+    return true;
+  }-*/;
 
       native byte nativeJsniReturnUnboxedByte() /*-{
-        return 99;
-      }-*/;
+    return 99;
+  }-*/;
 
       native char nativeJsniReturnUnboxedCharacter() /*-{
-        return 77;
-      }-*/;
+    return 77;
+  }-*/;
 
       native double nativeJsniReturnUnboxedDouble() /*-{
-        return 1234.56789;
-      }-*/;
+    return 1234.56789;
+  }-*/;
 
       native float nativeJsniReturnUnboxedFloat() /*-{
-        return 1234.5;
-      }-*/;
+    return 1234.5;
+  }-*/;
 
       native int nativeJsniReturnUnboxedInteger() /*-{
-        return 9876543;
-      }-*/;
+    return 9876543;
+  }-*/;
 
       native short nativeJsniReturnUnboxedShort() /*-{
-        return 1234;
-      }-*/;
+    return 1234;
+  }-*/;
     }
     Inner inner = new Inner();
 
@@ -598,49 +594,6 @@
     assertEquals("FOO", callJSNIToString(new Foo()));
   }
 
-  public void testLocalJsni() {
-
-    class Foo {
-      native String a() /*-{
-        return "blah";
-      }-*/;
-
-      native String b() /*-{
-        return this.@com.google.gwt.dev.jjs.test.HostedTest$2Foo::a()();
-      }-*/;
-
-      String c() {
-        return a();
-      }
-    }
-
-    Foo f = new Foo();
-    assertEquals(f.a(), "blah");
-    assertEquals(f.b(), "blah");
-    assertEquals(f.c(), "blah");
-
-    Foo fo = new Foo() {
-      @Override
-      native String a() /*-{
-        return "oblah";
-      }-*/;
-
-      @Override
-      native String b() /*-{
-        return this.@com.google.gwt.dev.jjs.test.HostedTest$2Foo::a()();
-      }-*/;
-
-      @Override
-      native String c() /*-{
-        return this.@com.google.gwt.dev.jjs.test.HostedTest$1::a()();
-      }-*/;
-    };
-
-    assertEquals(fo.a(), "oblah");
-    assertEquals(fo.b(), "oblah");
-    assertEquals(fo.c(), "oblah");
-  }
-
   /*
    * Test that returning strings from methods declared as returning Object
    * works, and that returning a primitive does not.
@@ -725,10 +678,10 @@
   }-*/;
 
   /*
-   * Since we can't generate a generic instance from within JS, K and V
-   * have to actually be compatible.
+   * Since we can't generate a generic instance from within JS, K and V have to
+   * actually be compatible.
    */
-  private native <K,V> V genericGet(K key) /*-{
+  private native <K, V> V genericGet(K key) /*-{
     return key;
   }-*/;
 
@@ -755,53 +708,75 @@
     return this.@com.google.gwt.dev.jjs.test.HostedTest::foo(Ljava/lang/String;);
   }-*/;
 
-  private native void jsniA()/*-{}-*/;
+  private native void jsniA()/*-{
+
+  }-*/;
 
   private native void jsniB()/*-{
+
   }-*/;
 
   private native void jsniC()
   /*-{
+
   }-*/;
 
   private native void jsniD()
-  /*-{}-*/;
+  /*-{
+
+  }-*/;
 
   /**
    * comment.
    */
-  private native void jsniE()/*-{}-*/;
+  private native void jsniE()/*-{
+
+  }-*/;
 
   /** comment. */
-  private native void jsniF()/*-{}-*/;
+  private native void jsniF()/*-{
 
-  /** comment */private native void jsniG()/*-{}-*/;
+  }-*/;
+
+  /** comment */
+  private native void jsniG()/*-{
+
+  }-*/;
 
   /*
    * comment
    */
-  private native void jsniH()/*-{}-*/;
+  private native void jsniH()/*-{
 
-  /* comment */private native void jsniI()/*-{}-*/;
-
-  // comment
-  private native void jsniJ()/*-{}-*/;
-
-  private
-  native
-  void 
-  jsniK()
-  /*-{
   }-*/;
 
-  /*-{ try to mess with compiler }-*/
-  private native void jsniL()/*-{}-*/;
+  /* comment */private native void jsniI()/*-{
+
+  }-*/;
+
+  // comment
+  private native void jsniJ()/*-{
+
+  }-*/;
+
+  private native void jsniK()
+  /*-{
+
+  }-*/;
+
+  /*-{
+    try to mess with compiler
+  }-*/
+  private native void jsniL()/*-{
+
+  }-*/;
 
   // test that JS can pass a series of arguments to a varargs function
   // TODO: not sure if we want to support this
   // private native String[] varargsFromJS1() /*-{
   // return
-  // this.@com.google.gwt.dev.jjs.test.HostedTest::varargsPassthrough([Ljava/lang/String;)("foo",
+  // this.@com.google.gwt.dev.jjs.test.HostedTest::varargsPassthrough([Ljava/lang
+  // /String;)("foo",
   // "bar");
   // }-*/;
 
diff --git a/user/test/com/google/gwt/event/EventSuite.java b/user/test/com/google/gwt/event/EventSuite.java
new file mode 100644
index 0000000..905c866
--- /dev/null
+++ b/user/test/com/google/gwt/event/EventSuite.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event;
+
+import com.google.gwt.event.dom.client.DomEventTest;
+import com.google.gwt.event.logical.shared.LogicalEventsTest;
+import com.google.gwt.event.shared.HandlerManagerTest;
+import com.google.gwt.junit.tools.GWTTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Test for suite for the com.google.gwt.event module.
+ */
+public class EventSuite {
+  public static Test suite() {
+    GWTTestSuite suite = new GWTTestSuite(
+        "Test for suite for the com.google.gwt.event module.");
+
+    // ...logical.shared
+    suite.addTestSuite(LogicalEventsTest.class);
+
+    // ...dom.client
+    suite.addTestSuite(DomEventTest.class);
+
+    // ...dom.shared
+    suite.addTestSuite(HandlerManagerTest.class);
+
+    return suite;
+  }
+}
diff --git a/user/test/com/google/gwt/event/dom/client/DomEventTest.java b/user/test/com/google/gwt/event/dom/client/DomEventTest.java
new file mode 100644
index 0000000..5655c59
--- /dev/null
+++ b/user/test/com/google/gwt/event/dom/client/DomEventTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.dom.client;
+
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.event.shared.HandlerTestBase;
+
+/**
+ * Events test.
+ */
+// TODO(ECC) check that max handlers work properly.
+public class DomEventTest extends HandlerTestBase {
+  private HandlerManager manager;
+  static class Flag {
+    public boolean flag = false;
+  }
+
+  public void testKeyEvents() {
+
+    final Flag flag = new Flag();
+    manager = new HandlerManager(flag);
+    HandlerRegistration downRegistration = manager.addHandler(
+        KeyDownEvent.getType(), new KeyDownHandler() {
+          public void onKeyDown(KeyDownEvent event) {
+            flag.flag = true;
+          }
+        });
+    HandlerRegistration upRegistration = manager.addHandler(
+        KeyUpEvent.getType(), new KeyUpHandler() {
+          public void onKeyUp(KeyUpEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration pressRegistration = manager.addHandler(
+        KeyPressEvent.getType(), new KeyPressHandler() {
+          public void onKeyPress(KeyPressEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    checkFire(new KeyDownEvent(), downRegistration, flag, "onKeyDown");
+    checkFire(new KeyUpEvent(), upRegistration, flag, "onKeyUp");
+    checkFire(new KeyPressEvent(), pressRegistration, flag, "onKeyPressed");
+  }
+
+  public void testMouseEvents() {
+
+    final Flag flag = new Flag();
+    manager = new HandlerManager(flag);
+
+    HandlerRegistration downRegistration = manager.addHandler(
+        MouseDownEvent.getType(), new MouseDownHandler() {
+          public void onMouseDown(MouseDownEvent event) {
+            flag.flag = true;
+          }
+        });
+    HandlerRegistration upRegistration = manager.addHandler(
+        MouseUpEvent.getType(), new MouseUpHandler() {
+          public void onMouseUp(MouseUpEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration clickRegistration = manager.addHandler(
+        ClickEvent.getType(), new ClickHandler() {
+          public void onClick(ClickEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration dblclickRegistration = manager.addHandler(
+        DoubleClickEvent.getType(), new DoubleClickHandler() {
+          public void onDoubleClick(DoubleClickEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration outRegistration = manager.addHandler(
+        MouseOutEvent.getType(), new MouseOutHandler() {
+          public void onMouseOut(MouseOutEvent event) {
+            flag.flag = true;
+          }
+        });
+    HandlerRegistration overRegistration = manager.addHandler(
+        MouseOverEvent.getType(), new MouseOverHandler() {
+          public void onMouseOver(MouseOverEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration moveRegistration = manager.addHandler(
+        MouseMoveEvent.getType(), new MouseMoveHandler() {
+          public void onMouseMove(MouseMoveEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    HandlerRegistration wheelRegistration = manager.addHandler(
+        MouseWheelEvent.getType(), new MouseWheelHandler() {
+          public void onMouseWheel(MouseWheelEvent event) {
+            flag.flag = true;
+          }
+        });
+
+    checkFire(new MouseDownEvent(), downRegistration, flag, "onMouseDown");
+    checkFire(new MouseUpEvent(), upRegistration, flag, "onMouseUp");
+    checkFire(new MouseOutEvent(), outRegistration, flag, "onMouseOut");
+    checkFire(new MouseOverEvent(), overRegistration, flag, "onMouseOver");
+    checkFire(new MouseMoveEvent(), moveRegistration, flag, "onMouseMove");
+    checkFire(new MouseWheelEvent(), wheelRegistration, flag, "onMouseWheel");
+    checkFire(new ClickEvent(), clickRegistration, flag, "onClick");
+    checkFire(new DoubleClickEvent(), dblclickRegistration, flag,
+        "onDoubleClick");
+  }
+
+  private void checkFire(DomEvent<?> event, HandlerRegistration registration,
+      Flag flag, String eventName) {
+
+    flag.flag = false;
+    manager.fireEvent(event);
+    assertTrue(eventName + " didn't fire.", flag.flag);
+
+    flag.flag = false;
+    registration.removeHandler();
+    // event.reset(null);
+    manager.fireEvent(event);
+    assertTrue(eventName + " fired when it shouldn't have.", !flag.flag);
+  }
+}
diff --git a/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java b/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java
new file mode 100644
index 0000000..985c79a
--- /dev/null
+++ b/user/test/com/google/gwt/event/logical/shared/LogicalEventsTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.event.logical.shared;
+
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests of logical events.
+ */
+public class LogicalEventsTest extends TestCase {
+
+  static class Fire implements SelectionHandler<String>,
+      BeforeSelectionHandler<String>, CloseHandler<String>,
+      OpenHandler<String>, ResizeHandler, ValueChangeHandler<String> {
+    public boolean flag = false;
+
+    public void onBeforeSelection(BeforeSelectionEvent<String> event) {
+      flag = true;
+    }
+
+    public void onClose(CloseEvent<String> event) {
+      flag = true;
+    }
+
+    public void onOpen(OpenEvent<String> event) {
+      flag = true;
+    }
+
+    public void onResize(ResizeEvent event) {
+      flag = true;
+    }
+
+    public void onSelection(SelectionEvent<String> event) {
+      flag = true;
+    }
+
+    public void onValueChange(ValueChangeEvent<String> event) {
+      flag = true;
+    }
+  }
+
+  private HandlerManager manager;
+
+  @Override
+  public void setUp() {
+    manager = new HandlerManager(this);
+  }
+
+  public void testSimpleFire() {
+    simpleFire(BeforeSelectionEvent.getType(),
+        new BeforeSelectionEvent<String>());
+    simpleFire(SelectionEvent.getType(), new SelectionEvent<String>(null));
+    simpleFire(CloseEvent.getType(), new CloseEvent<String>(null,false));
+    simpleFire(OpenEvent.getType(), new OpenEvent<String>(null));
+    simpleFire(ResizeEvent.getType(), new ResizeEvent(0, 0));
+    simpleFire(ValueChangeEvent.getType(), new ValueChangeEvent<String>(null));
+  }
+
+  @SuppressWarnings("unchecked")
+  private <H extends EventHandler> void simpleFire(GwtEvent.Type<H> type,
+      GwtEvent instance) {
+    Fire f = new Fire();
+    manager.addHandler(type, (H) f);
+    manager.fireEvent(instance);
+    assertTrue(f.flag);
+  }
+}
diff --git a/user/test/com/google/gwt/event/shared/HandlerManagerTest.java b/user/test/com/google/gwt/event/shared/HandlerManagerTest.java
new file mode 100644
index 0000000..ec450f2
--- /dev/null
+++ b/user/test/com/google/gwt/event/shared/HandlerManagerTest.java
@@ -0,0 +1,264 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.shared;

+

+import com.google.gwt.core.client.GWT;

+import com.google.gwt.event.dom.client.ClickEvent;

+import com.google.gwt.event.dom.client.MouseDownEvent;

+import com.google.gwt.event.dom.client.MouseDownHandler;

+

+/**

+ * Handler manager test.

+ */

+public class HandlerManagerTest extends HandlerTestBase {

+

+  public void testAddHandlers() {

+

+    HandlerManager manager = new HandlerManager("bogus source");

+    addHandlers(manager);

+  }

+

+  @SuppressWarnings("deprecation")

+  private void addHandlers(HandlerManager manager) {

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+    manager.addHandler(MouseDownEvent.getType(), mouse2);

+    manager.addHandler(MouseDownEvent.getType(), adaptor1);

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertEquals(3, manager.getHandlerCount(MouseDownEvent.getType()));

+    assertFired(mouse1, mouse2, adaptor1);

+    manager.addHandler(MouseDownEvent.getType(), mouse3);

+    assertEquals(4, manager.getHandlerCount(MouseDownEvent.getType()));

+

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+    manager.addHandler(MouseDownEvent.getType(), mouse2);

+    manager.addHandler(MouseDownEvent.getType(), adaptor1);

+

+    // You can indeed add handlers twice, they will only be removed one at a

+    // time though.

+    assertEquals(7, manager.getHandlerCount(MouseDownEvent.getType()));

+    manager.addHandler(ClickEvent.getType(), adaptor1);

+    manager.addHandler(ClickEvent.getType(), click1);

+    manager.addHandler(ClickEvent.getType(), click2);

+

+    assertEquals(7, manager.getHandlerCount(MouseDownEvent.getType()));

+    assertEquals(3, manager.getHandlerCount(ClickEvent.getType()));

+

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(mouse1, mouse2, mouse3, adaptor1);

+    assertNotFired(click1, click2);

+  }

+

+  @SuppressWarnings("deprecation")

+  public void testRemoveHandlers() {

+    HandlerManager manager = new HandlerManager("bogus source");

+    addHandlers(manager);

+    // Gets rid of first instance.

+    manager.removeHandler(MouseDownEvent.getType(), adaptor1);

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(mouse1, mouse2, mouse3, adaptor1);

+    assertNotFired(click1, click2);

+

+    // Gets rid of second instance.

+    manager.removeHandler(MouseDownEvent.getType(), adaptor1);

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+

+    assertFired(mouse1, mouse2, mouse3);

+    assertNotFired(adaptor1, click1, click2);

+

+    // Checks to see if click events are still working.

+    reset();

+    manager.fireEvent(new ClickEvent() {

+    });

+

+    assertNotFired(mouse1, mouse2, mouse3);

+    assertFired(click1, click2, adaptor1);

+  }

+

+  public void testConcurrentAdd() {

+    final HandlerManager manager = new HandlerManager("bogus source");

+    final MouseDownHandler two = new MouseDownHandler() {

+      public void onMouseDown(MouseDownEvent event) {

+        add(this);

+      }

+    };

+    MouseDownHandler one = new MouseDownHandler() {

+      public void onMouseDown(MouseDownEvent event) {

+        manager.addHandler(MouseDownEvent.getType(), two);

+        add(this);

+      }

+    };

+    manager.addHandler(MouseDownEvent.getType(), one);

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+    manager.addHandler(MouseDownEvent.getType(), mouse2);

+    manager.addHandler(MouseDownEvent.getType(), mouse3);

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one, mouse1, mouse2, mouse3);

+    assertNotFired(two);

+

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one, two, mouse1, mouse2, mouse3);

+  }

+

+  class ShyHandler implements MouseDownHandler {

+    HandlerRegistration r;

+

+    public void onMouseDown(MouseDownEvent event) {

+      add(this);

+      r.removeHandler();

+    }

+  }

+

+  public void testConcurrentRemove() {

+    final HandlerManager manager = new HandlerManager("bogus source");

+

+    ShyHandler h = new ShyHandler();

+

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+    h.r = manager.addHandler(MouseDownEvent.getType(), h);

+    manager.addHandler(MouseDownEvent.getType(), mouse2);

+    manager.addHandler(MouseDownEvent.getType(), mouse3);

+

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(h, mouse1, mouse2, mouse3);

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(mouse1, mouse2, mouse3);

+    assertNotFired(h);

+  }

+

+  public void testConcurrentAddAndRemoveByNastyUsersTryingToHurtUs() {

+    final HandlerManager manager = new HandlerManager("bogus source");

+    final MouseDownHandler two = new MouseDownHandler() {

+      public void onMouseDown(MouseDownEvent event) {

+        add(this);

+      }

+

+      @Override

+      public String toString() {

+        return "two";

+      }

+    };

+    MouseDownHandler one = new MouseDownHandler() {

+      public void onMouseDown(MouseDownEvent event) {

+        manager.addHandler(MouseDownEvent.getType(), two).removeHandler();

+        add(this);

+      }

+

+      @Override

+      public String toString() {

+        return "one";

+      }

+    };

+    manager.addHandler(MouseDownEvent.getType(), one);

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+    manager.addHandler(MouseDownEvent.getType(), mouse2);

+    manager.addHandler(MouseDownEvent.getType(), mouse3);

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one, mouse1, mouse2, mouse3);

+    assertNotFired(two);

+

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one, mouse1, mouse2, mouse3);

+    assertNotFired(two);

+  }

+

+  @SuppressWarnings("deprecation")

+  public void testConcurrentAddAfterRemoveIsNotClobbered() {

+    final HandlerManager manager = new HandlerManager("bogus source");

+

+    MouseDownHandler one = new MouseDownHandler() {

+      public void onMouseDown(MouseDownEvent event) {

+        manager.removeHandler(MouseDownEvent.getType(), mouse1);

+        manager.addHandler(MouseDownEvent.getType(), mouse1);

+        add(this);

+      }

+    };

+    manager.addHandler(MouseDownEvent.getType(), one);

+

+    if (!GWT.isScript()) {

+      try {

+        manager.fireEvent(new MouseDownEvent() {

+        });

+        fail("Should have thrown on remove");

+      } catch (AssertionError e) { /* pass */

+      }

+      return;

+    }

+

+    // Web mode, no asserts, so remove will quietly succeed.

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one);

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(one, mouse1);

+  }

+

+  @SuppressWarnings("deprecation")

+  public void testMultiFiring() {

+

+    HandlerManager manager = new HandlerManager("source1");

+

+    final HandlerManager manager2 = new HandlerManager("source2");

+

+    manager.addHandler(MouseDownEvent.getType(), mouse1);

+

+    manager.addHandler(MouseDownEvent.getType(), new MouseDownHandler() {

+

+      public void onMouseDown(MouseDownEvent event) {

+        manager2.fireEvent(event);

+      }

+

+    });

+    manager.addHandler(MouseDownEvent.getType(), mouse3);

+    manager2.addHandler(MouseDownEvent.getType(), adaptor1);

+    manager2.addHandler(MouseDownEvent.getType(), new MouseDownHandler() {

+

+      public void onMouseDown(MouseDownEvent event) {

+        assertEquals("source2", event.getSource());

+      }

+

+    });

+    manager.addHandler(MouseDownEvent.getType(), new MouseDownHandler() {

+

+      public void onMouseDown(MouseDownEvent event) {

+        assertEquals("source1", event.getSource());

+      }

+

+    });

+

+    reset();

+    manager.fireEvent(new MouseDownEvent() {

+    });

+    assertFired(mouse1, adaptor1, mouse3);

+  }

+}

diff --git a/user/test/com/google/gwt/event/shared/HandlerTestBase.java b/user/test/com/google/gwt/event/shared/HandlerTestBase.java
new file mode 100644
index 0000000..303ff12
--- /dev/null
+++ b/user/test/com/google/gwt/event/shared/HandlerTestBase.java
@@ -0,0 +1,146 @@
+/*

+ * Copyright 2008 Google Inc.

+ * 

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

+ * use this file except in compliance with the License. You may obtain a copy of

+ * the License at

+ * 

+ * http://www.apache.org/licenses/LICENSE-2.0

+ * 

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the

+ * License for the specific language governing permissions and limitations under

+ * the License.

+ */

+

+package com.google.gwt.event.shared;

+

+import com.google.gwt.event.dom.client.ClickEvent;

+import com.google.gwt.event.dom.client.ClickHandler;

+import com.google.gwt.event.dom.client.MouseDownEvent;

+import com.google.gwt.event.dom.client.MouseDownHandler;

+import com.google.gwt.junit.client.GWTTestCase;

+

+import java.util.HashSet;

+

+/**

+ * Support code for handler tests.

+ */

+public abstract class HandlerTestBase extends GWTTestCase {

+

+  public String getModuleName() {

+    return "com.google.gwt.event.Event";

+  }

+

+  class Adaptor implements ClickHandler, MouseDownHandler {

+

+    public void onClick(ClickEvent event) {

+      add(this);

+    }

+

+    public void onMouseDown(MouseDownEvent event) {

+      add(this);

+    }

+

+    @Override

+    public String toString() {

+      return "adaptor 1";

+    }

+  }

+

+  Adaptor adaptor1 = new Adaptor();

+

+  private HashSet<EventHandler> active = new HashSet<EventHandler>();

+

+  MouseDownHandler mouse1 = new MouseDownHandler() {

+    public void onMouseDown(MouseDownEvent event) {

+      add(mouse1);

+    }

+

+    @Override

+    public String toString() {

+      return "mouse 1";

+    }

+  };

+

+  MouseDownHandler mouse2 = new MouseDownHandler() {

+    public void onMouseDown(MouseDownEvent event) {

+      add(mouse2);

+    }

+

+    @Override

+    public String toString() {

+      return "mouse 2";

+    }

+  };

+

+  MouseDownHandler mouse3 = new MouseDownHandler() {

+    public void onMouseDown(MouseDownEvent event) {

+      add(mouse3);

+    }

+

+    @Override

+    public String toString() {

+      return "mouse 3";

+    }

+  };

+

+  ClickHandler click1 = new ClickHandler() {

+

+    public void onClick(ClickEvent event) {

+      add(click1);

+    }

+

+    @Override

+    public String toString() {

+      return "click 1";

+    }

+  };

+

+  ClickHandler click2 = new ClickHandler() {

+

+    public void onClick(ClickEvent event) {

+      add(click2);

+    }

+

+    @Override

+    public String toString() {

+      return "click 2";

+    }

+  };

+

+  ClickHandler click3 = new ClickHandler() {

+

+    public void onClick(ClickEvent event) {

+      add(click3);

+    }

+

+    @Override

+    public String toString() {

+      return "click 3";

+    }

+  };

+

+  void add(EventHandler handler) {

+    active.add(handler);

+  }

+

+  void assertFired(EventHandler... handler) {

+    for (int i = 0; i < handler.length; i++) {

+      assertTrue(handler[i] + " should have fired", active.contains(handler[i]));

+    }

+  }

+

+  void assertNotFired(EventHandler... handler) {

+    for (int i = 0; i < handler.length; i++) {

+      assertFalse(handler[i] + " should not have fired",

+          active.contains(handler[i]));

+    }

+  }

+

+  void reset() {

+    active.clear();

+  }

+

+}

diff --git a/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java b/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
index 671236a..28f6003 100644
--- a/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
+++ b/user/test/com/google/gwt/i18n/client/DateTimeFormat_de_Test.java
@@ -23,6 +23,7 @@
  * Tests formatting functionality in {@link DateTimeFormat} for the German
  * language.
  */
+@SuppressWarnings("deprecation")
 public class DateTimeFormat_de_Test extends GWTTestCase {
 
   public String getModuleName() {
@@ -31,20 +32,19 @@
 
   public void test_EEEEMMMddyy() {
     Date date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
-    assertEquals("Donnerstag,Juli 27, 2006", 
-        DateTimeFormat.getFormat("EEEE,MMMM dd, yyyy").format(date));
+    assertEquals("Donnerstag,Juli 27, 2006", DateTimeFormat.getFormat(
+        "EEEE,MMMM dd, yyyy").format(date));
   }
 
   public void test_EEEMMMddyy() {
     Date date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
-    assertEquals("Do, Jul 27, 06", 
+    assertEquals("Do, Jul 27, 06",
         DateTimeFormat.getFormat("EEE, MMM d, yy").format(date));
   }
 
   public void test_HHmmss() {
     Date date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
-    assertEquals("13:10:10", 
-        DateTimeFormat.getFormat("HH:mm:ss").format(date));
+    assertEquals("13:10:10", DateTimeFormat.getFormat("HH:mm:ss").format(date));
   }
 
   public void test_hhmmssa() {
@@ -85,52 +85,52 @@
     Date date;
 
     date = new Date(2006 - 1900, 0, 27, 13, 10, 10);
-    assertEquals("1. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("1. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 1, 27, 13, 10, 10);
-    assertEquals("1. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("1. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 2, 27, 13, 10, 10);
-    assertEquals("1. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("1. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 3, 27, 13, 10, 10);
-    assertEquals("2. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("2. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 4, 27, 13, 10, 10);
-    assertEquals("2. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("2. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 5, 27, 13, 10, 10);
-    assertEquals("2. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("2. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
-    assertEquals("3. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("3. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 7, 27, 13, 10, 10);
-    assertEquals("3. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("3. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 8, 27, 13, 10, 10);
-    assertEquals("3. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("3. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 9, 27, 13, 10, 10);
-    assertEquals("4. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("4. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 10, 27, 13, 10, 10);
-    assertEquals("4. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("4. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
 
     date = new Date(2006 - 1900, 11, 27, 13, 10, 10);
-    assertEquals("4. Quartal 06", 
-        DateTimeFormat.getFormat("QQQQ yy").format(date));
+    assertEquals("4. Quartal 06", DateTimeFormat.getFormat("QQQQ yy").format(
+        date));
   }
 
   public void test_QQyyyy() {
@@ -201,17 +201,16 @@
     date.setHours(13);
     date.setMinutes(10);
     date.setSeconds(10);
-    assertEquals("13 o'clock", 
+    assertEquals("13 o'clock",
         DateTimeFormat.getFormat("HH 'o''clock'").format(date));
-    assertEquals("13 oclock", 
-        DateTimeFormat.getFormat("HH 'oclock'").format(date));
-    assertEquals("13 '", 
-        DateTimeFormat.getFormat("HH ''").format(date));
+    assertEquals("13 oclock", DateTimeFormat.getFormat("HH 'oclock'").format(
+        date));
+    assertEquals("13 '", DateTimeFormat.getFormat("HH ''").format(date));
   }
 
   public void test_yyyyyMMMMM() {
     Date date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
-    assertEquals("2006.J.27 n. Chr. 01:10 nachm.", 
-        DateTimeFormat.getFormat("yyyyy.MMMMM.dd GGG hh:mm aaa").format(date));
+    assertEquals("2006.J.27 n. Chr. 01:10 nachm.", DateTimeFormat.getFormat(
+        "yyyyy.MMMMM.dd GGG hh:mm aaa").format(date));
   }
 }
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java
index 24d44ec..499446a 100644
--- a/user/test/com/google/gwt/user/RPCSuite.java
+++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -26,6 +26,7 @@
 import com.google.gwt.user.client.rpc.ValueTypesTest;
 import com.google.gwt.user.rebind.rpc.SerializableTypeOracleBuilderTest;
 import com.google.gwt.user.rebind.rpc.TypeHierarchyUtilsTest;
+import com.google.gwt.user.server.rpc.RPCRequestTest;
 import com.google.gwt.user.server.rpc.RPCServletUtilsTest;
 import com.google.gwt.user.server.rpc.RPCTest;
 import com.google.gwt.user.server.rpc.SerializationPolicyLoaderTest;
@@ -68,6 +69,7 @@
     suite.addTestSuite(StandardSerializationPolicyTest.class);
     suite.addTestSuite(SerializationPolicyLoaderTest.class);
     suite.addTestSuite(RPCServletUtilsTest.class);
+    suite.addTestSuite(RPCRequestTest.class);
     return suite;
   }
 }
diff --git a/user/test/com/google/gwt/user/UISuite.java b/user/test/com/google/gwt/user/UISuite.java
index 90e2c08..1452667 100644
--- a/user/test/com/google/gwt/user/UISuite.java
+++ b/user/test/com/google/gwt/user/UISuite.java
@@ -32,7 +32,6 @@
 import com.google.gwt.user.client.ui.DecoratedTabBarTest;
 import com.google.gwt.user.client.ui.DecoratedTabPanelTest;
 import com.google.gwt.user.client.ui.DecoratorPanelTest;
-import com.google.gwt.user.client.ui.DelegatingKeyboardListenerCollectionTest;
 import com.google.gwt.user.client.ui.DialogBoxTest;
 import com.google.gwt.user.client.ui.DisclosurePanelTest;
 import com.google.gwt.user.client.ui.DockPanelTest;
@@ -101,7 +100,8 @@
     suite.addTestSuite(DecoratedTabBarTest.class);
     suite.addTestSuite(DecoratedTabPanelTest.class);
     suite.addTestSuite(DecoratorPanelTest.class);
-    suite.addTestSuite(DelegatingKeyboardListenerCollectionTest.class);
+    // TEMP
+    // suite.addTestSuite(DelegatingKeyboardListenerCollectionTest.class);
     suite.addTestSuite(DialogBoxTest.class);
     suite.addTestSuite(DisclosurePanelTest.class);
     suite.addTestSuite(DockPanelTest.class);
diff --git a/user/test/com/google/gwt/user/client/WindowTest.java b/user/test/com/google/gwt/user/client/WindowTest.java
index a04f83f..04e2302 100644
--- a/user/test/com/google/gwt/user/client/WindowTest.java
+++ b/user/test/com/google/gwt/user/client/WindowTest.java
@@ -131,7 +131,8 @@
     Window.enableScrolling(false);
     final int oldClientHeight = Window.getClientHeight();
     final int oldClientWidth = Window.getClientWidth();
-    assertTrue(oldClientHeight > 0);
+    assertTrue("Expect positive oldClientHeight. "
+        + "This will fail in WebKit if run headless", oldClientHeight > 0);
     assertTrue(oldClientWidth > 0);
 
     // Compare to the dimensions with scroll bars
diff --git a/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java b/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
index c38ea16..78a47e4 100644
--- a/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/AbsolutePanelTest.java
@@ -62,7 +62,8 @@
     int absY = lbl.getAbsoluteTop() - Document.get().getBodyOffsetTop();
     assertEquals(3, x);
     assertEquals(7, y);
-    assertEquals(3 + 100, absX);
+    assertEquals("absX should be 103. This will fail in WebKit if run headless", 
+        3 + 100, absX);
     assertEquals(7 + 200, absY);
   }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/AnchorTest.java b/user/test/com/google/gwt/user/client/ui/AnchorTest.java
index b981b54..c98d156 100644
--- a/user/test/com/google/gwt/user/client/ui/AnchorTest.java
+++ b/user/test/com/google/gwt/user/client/ui/AnchorTest.java
@@ -16,6 +16,8 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.HasDirection;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.DOM;
@@ -24,6 +26,23 @@
  * Tests for {@link Anchor}.
  */
 public class AnchorTest extends GWTTestCase {
+  private final class TestClickHandler implements ClickHandler {
+    private int clicks = 0;
+    private Object lastSender;
+
+    public void onClick(ClickEvent event) {
+      clicks++;
+      lastSender = event.getSource();
+    }
+
+    public int getClicks() {
+      return clicks;
+    }
+
+    public Object getLastSender() {
+      return lastSender;
+    }
+  }
 
   private static final String TEST_URL0 = "http://www.google.com/";
   private static final String TEST_URL1 = "http://code.google.com/";
@@ -58,6 +77,7 @@
     assertEquals(42, anchor.getTabIndex());
   }
 
+  @Deprecated
   private final class TestClickListener implements ClickListener {
     private int clicks = 0;
     private Widget lastSender;
@@ -104,8 +124,7 @@
     assertEquals("Foo", anchor.getText());
     assertAttributeHasValue("javascript:", anchor.getElement(), "href");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref", "target"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref", "target"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -121,8 +140,7 @@
     assertEquals("SPAN", DOM.getChild(anchor.getElement(), 0).getTagName());
     assertAttributeHasValue("javascript:", anchor.getElement(), "href");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref", "target"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref", "target"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -136,10 +154,16 @@
     TestClickListener testListener = new TestClickListener();
     anchor.addClickListener(testListener);
 
+    TestClickHandler handler = new TestClickHandler();
+    anchor.addClickHandler(handler);
+
     assertEquals(0, testListener.getClicks());
+    assertEquals(0, handler.getClicks());
     triggerEvent(anchor.getElement(), "click", false, "MouseEvents");
     assertEquals(1, testListener.getClicks());
+    assertEquals(1, handler.getClicks());
     assertEquals(anchor, testListener.getLastSender());
+    assertEquals(anchor, handler.getLastSender());
   }
 
   public void testLink() {
@@ -153,8 +177,7 @@
     assertEquals("Click me!", anchor.getText());
     assertAttributeHasValue("http://nowhere.org/", anchor.getElement(), "href");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref", "target"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref", "target"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -174,8 +197,7 @@
     assertAttributeHasValue("http://still.nowhere.org/", anchor.getElement(),
         "href");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref", "target"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref", "target"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -194,8 +216,7 @@
         anchor.getElement(), "href");
     assertAttributeHasValue("popup", anchor.getElement(), "target");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -215,8 +236,7 @@
     assertAttributeHasValue("http://more.ads.com/", anchor.getElement(), "href");
     assertAttributeHasValue("_blank", anchor.getElement(), "target");
 
-    for (String attribute : new String[] {
-        "name", "id", "rel", "ref"}) {
+    for (String attribute : new String[] {"name", "id", "rel", "ref"}) {
       assertAttributeNotPresent(attribute, anchor.getElement());
     }
   }
@@ -265,7 +285,8 @@
     assertEquals("Hieronymous", anchor.getElement().getAttribute("name"));
 
     anchor.setTabIndex(42);
-    assertEquals(42, Integer.parseInt(anchor.getElement().getAttribute("tabIndex")));
+    System.err.println(anchor.getElement().getPropertyInt("tabIndex"));
+    assertEquals(42, anchor.getElement().getPropertyInt("tabIndex"));
   }
 
   /**
diff --git a/user/test/com/google/gwt/user/client/ui/CheckBoxTest.java b/user/test/com/google/gwt/user/client/ui/CheckBoxTest.java
index 963308b..5bb0f60 100644
--- a/user/test/com/google/gwt/user/client/ui/CheckBoxTest.java
+++ b/user/test/com/google/gwt/user/client/ui/CheckBoxTest.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
@@ -27,6 +29,18 @@
   @Override
   public String getModuleName() {
     return "com.google.gwt.user.DebugTest";
+  }  
+
+  @Override
+  protected void gwtSetUp() throws Exception {
+    super.gwtSetUp();
+    RootPanel.get().clear();
+  }
+
+  @Override
+  protected void gwtTearDown() throws Exception {
+    RootPanel.get().clear();
+    super.gwtTearDown();
   }
 
   /**
@@ -71,4 +85,36 @@
     UIObjectTest.assertDebugId("myCheck-input", newInput);
     UIObjectTest.assertDebugIdContents("myCheck-label", "myLabel");
   }
+  
+  public void testValueChangeEvent() {
+    CheckBox cb = new CheckBox();
+    Handler h = new Handler();
+    cb.addValueChangeHandler(h);
+    cb.setChecked(false);
+    assertNull(h.received);
+    cb.setChecked(true);
+    assertNull(h.received);
+    
+    cb.setValue(false);
+    assertNull(h.received);
+    cb.setValue(true);
+    assertNull(h.received);
+
+    cb.setValue(true, true);
+    assertNull(h.received);
+    
+    cb.setValue(false, true);
+    assertFalse(h.received);
+
+    cb.setValue(true, true);
+    assertTrue(h.received);
+  }
+  
+  private static class Handler implements ValueChangeHandler<Boolean> {
+    Boolean received = null;
+    
+    public void onValueChange(ValueChangeEvent<Boolean> event) {
+      received = event.getValue();
+    }
+  }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/CompositeTest.java b/user/test/com/google/gwt/user/client/ui/CompositeTest.java
index 3082092..b037981 100644
--- a/user/test/com/google/gwt/user/client/ui/CompositeTest.java
+++ b/user/test/com/google/gwt/user/client/ui/CompositeTest.java
@@ -15,8 +15,14 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
 import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Event;
 
 /**
@@ -24,6 +30,7 @@
  */
 public class CompositeTest extends GWTTestCase {
 
+  @Override
   public String getModuleName() {
     return "com.google.gwt.user.User";
   }
@@ -32,6 +39,8 @@
     TextBox tb = new TextBox();
     boolean widgetFocusFired;
     boolean widgetLostFocusFired;
+    boolean widgetFocusHandlerFired;
+    boolean widgetBlurHandlerFired;
     boolean domFocusFired;
     boolean domBlurFired;
 
@@ -48,6 +57,17 @@
           widgetFocusFired = true;
         }
       });
+
+      tb.addFocusHandler(new FocusHandler() {
+        public void onFocus(FocusEvent event) {
+          widgetFocusHandlerFired = true;
+        }
+      });
+      tb.addBlurHandler(new BlurHandler() {
+        public void onBlur(BlurEvent event) {
+          widgetBlurHandlerFired = true;
+        }
+      });
     }
 
     @Override
@@ -68,38 +88,47 @@
     }
   }
 
-  public void testBrowserEvents() {
-// TODO: re-enable this test when we figure out why the focus events aren't
-// firing on some browsers.
-//
-//    final EventTestComposite c = new EventTestComposite();
-//    RootPanel.get().add(c);
-//
-//    this.delayTestFinish(1000);
-//
-//    // Focus, then blur, the composite's text box. This has to be done in
-//    // deferred commands, because focus events usually require the event loop
-//    // to be pumped in order to fire.
-//    DeferredCommand.addCommand(new Command() {
-//      public void execute() {
-//        DeferredCommand.addCommand(new Command() {
-//          public void execute() {
-//            // Ensure all events fired as expected.
-//            assertTrue(c.domFocusFired);
-//            assertTrue(c.domBlurFired);
-//            assertTrue(c.widgetLostFocusFired);
-//
-//            // Ensure that the widget's focus event was eaten by the
-//            // composite's implementation of onBrowserEvent().
-//            assertFalse(c.widgetFocusFired);
-//            finishTest();
-//          }
-//        });
-//
-//        c.tb.setFocus(false);
-//      }
-//    });
-//
-//    c.tb.setFocus(true);
+  public void disabledTestBrowserEvents() {
+    // TODO: re-enable this test when we figure out why the focus events aren't
+    // firing on some browsers.
+    final EventTestComposite c = new EventTestComposite();
+    RootPanel.get().add(c);
+
+    this.delayTestFinish(1000);
+
+    // Focus, then blur, the composite's text box. This has to be done in
+    // deferred commands, because focus events usually require the event loop
+    // to be pumped in order to fire.
+    DeferredCommand.addCommand(new Command() {
+      public void execute() {
+        DeferredCommand.addCommand(new Command() {
+          public void execute() {
+            // Ensure all events fired as expected.
+            assertTrue(c.domFocusFired);
+            assertTrue(c.domBlurFired);
+            assertTrue(c.widgetLostFocusFired);
+            assertTrue(c.widgetBlurHandlerFired);
+
+            // Ensure that the widget's focus event was eaten by the
+            // composite's implementation of onBrowserEvent().
+            assertFalse(c.widgetFocusFired);
+            assertFalse(c.widgetFocusHandlerFired);
+            finishTest();
+          }
+        });
+
+        c.tb.setFocus(false);
+      }
+    });
+
+    c.tb.setFocus(true);
+  }
+
+  /**
+   * This test is here to prevent a "No tests found" warning in Junit.
+   * 
+   * TODO: Remove this when testBrowserEvents is enabled
+   */
+  public void testNothing() {
   }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/DeckPanelTest.java b/user/test/com/google/gwt/user/client/ui/DeckPanelTest.java
index 66155a5..3d0b620 100644
--- a/user/test/com/google/gwt/user/client/ui/DeckPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DeckPanelTest.java
@@ -94,7 +94,9 @@
       public void onLoad() {
         // Verify that the offsetWidth/Height are greater than zero
         assertTrue(this.getOffsetHeight() > 0);
-        assertTrue(this.getOffsetWidth() > 0);
+        assertTrue("Expect positive offsetWidth. "
+            + "This will fail in WebKit if run headless",
+            this.getOffsetWidth() > 0);
         setText("attached");
       }
     };
diff --git a/user/test/com/google/gwt/user/client/ui/DisclosurePanelTest.java b/user/test/com/google/gwt/user/client/ui/DisclosurePanelTest.java
index f7f96e9..5412215 100644
--- a/user/test/com/google/gwt/user/client/ui/DisclosurePanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DisclosurePanelTest.java
@@ -15,6 +15,9 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.OpenEvent;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Timer;
@@ -22,6 +25,7 @@
 /**
  * Tests core functionality of {@link DisclosurePanel}.
  */
+@SuppressWarnings("deprecation")
 public class DisclosurePanelTest extends GWTTestCase {
   private static final int OPEN = 0;
 
@@ -43,7 +47,7 @@
         "none"));
 
     panel.setOpen(true);
-    
+
     // Allow the animation time to finish
     Timer t = new Timer() {
       @Override
@@ -75,9 +79,22 @@
         DOM.getParent(header.getElement()));
   }
 
+  public void testEvents() {
+    final DisclosurePanel panel = createTestPanel();
+    assertEquals(1, panel.getHandlers().getHandlerCount(CloseEvent.getType()));
+    panel.addCloseHandler(new CloseHandler<DisclosurePanel>() {
+
+      public void onClose(CloseEvent<DisclosurePanel> event) {
+        // for now nothing.
+      }
+    });
+    assertEquals(2, panel.getHandlers().getHandlerCount(CloseEvent.getType()));
+  }
+
   /**
    * Test to ensure that event handler dispatch function appropriately.
    */
+  @SuppressWarnings("deprecation")
   public void testEventHandlers() {
 
     final boolean[] aDidFire = new boolean[2];
@@ -108,7 +125,11 @@
 
     panel.addEventHandler(handleA);
     panel.addEventHandler(handleB);
+    // There is one to begin with.
+    assertEquals(3, panel.getHandlers().getHandlerCount(CloseEvent.getType()));
+    assertEquals(3, panel.getHandlers().getHandlerCount(OpenEvent.getType()));
 
+    
     panel.setOpen(true);
     // We expect onOpen to fire and onClose to not fire.
     assertTrue(aDidFire[OPEN] && bDidFire[OPEN] && !aDidFire[CLOSE]
@@ -124,12 +145,17 @@
     aDidFire[OPEN] = bDidFire[CLOSE] = false;
 
     panel.removeEventHandler(handleB);
+    assertEquals(2, panel.getHandlers().getHandlerCount(OpenEvent.getType()));
+    assertEquals(2, panel.getHandlers().getHandlerCount(CloseEvent.getType()));
+
 
     panel.setOpen(true);
     panel.setOpen(false);
     // We expect a to have fired both events, and b to have fired none.
-    assertTrue(aDidFire[OPEN] && aDidFire[CLOSE] && !bDidFire[OPEN]
-        && !bDidFire[CLOSE]);
+    assertTrue(aDidFire[OPEN]);
+    assertTrue(aDidFire[CLOSE]);
+    assertTrue(!bDidFire[OPEN]);
+    assertTrue(!bDidFire[CLOSE]);
   }
 
   private DisclosurePanel createTestPanel() {
diff --git a/user/test/com/google/gwt/user/client/ui/ImageTest.java b/user/test/com/google/gwt/user/client/ui/ImageTest.java
index 7f1bd20..a59794d 100644
--- a/user/test/com/google/gwt/user/client/ui/ImageTest.java
+++ b/user/test/com/google/gwt/user/client/ui/ImageTest.java
@@ -16,6 +16,10 @@
 package com.google.gwt.user.client.ui;
 
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.event.dom.client.ErrorEvent;
+import com.google.gwt.event.dom.client.ErrorHandler;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
 import com.google.gwt.junit.client.GWTTestCase;
 
 /**
@@ -23,7 +27,46 @@
  * are tested, along with the transitions between the two modes.
  */
 public class ImageTest extends GWTTestCase {
+  private static class TestErrorHandler implements ErrorHandler {
+    private Image image;
 
+    public TestErrorHandler(Image image) {
+      this.image = image;
+    }
+
+    public void onError(ErrorEvent event) {
+      fail("The image " + image.getUrl() + " failed to load.");
+    }
+  }
+
+  @Deprecated
+  private abstract static class TestLoadListener implements LoadListener {
+    private Image image;
+    private boolean finished = false;
+
+    public TestLoadListener(Image image) {
+      this.image = image;
+    }
+
+    public void onError(Widget sender) {
+      fail("The image " + image.getUrl() + " failed to load.");
+    }
+
+    /**
+     * Mark the test as finished.
+     */
+    public void finish() {
+      finished = true;
+    }
+
+    /**
+     * @return true if the test has finished
+     */
+    public boolean isFinished() {
+      return finished;
+    }
+  }
+  
   /**
    * Helper method that allows us to 'peek' at the private <code>state</code>
    * field in the Image object, and call the <code>state.getStateName()</code>
@@ -158,21 +201,35 @@
     final Image image = new Image("counting-forwards.png",
         16, 16, 16, 16);
 
-    image.addLoadListener(new LoadListener() {
+    final TestLoadListener listener = new TestLoadListener(image) {
       private int onLoadEventCount = 0;
 
-      public void onError(Widget sender) {
-        fail("The image " + ((Image) sender).getUrl() + " failed to load.");
-      }
-
       public void onLoad(Widget sender) {
         if (++onLoadEventCount == 1) {
           assertEquals(16, image.getWidth());
           assertEquals(16, image.getHeight());
-          finishTest();
+          finish();
+        }
+      }
+    };
+    image.addLoadListener(listener);
+
+    image.addLoadHandler(new LoadHandler() {
+      private int onLoadEventCount = 0;
+
+      public void onLoad(LoadEvent event) {
+        if (++onLoadEventCount == 1) {
+          assertEquals(16, image.getWidth());
+          assertEquals(16, image.getHeight());
+          if (listener.isFinished()) {
+            finishTest();
+          } else {
+            fail("Listener did not fire first");
+          }
         }
       }
     });
+    image.addErrorHandler(new TestErrorHandler(image));
 
     RootPanel.get().add(image);
     assertEquals(16, image.getOriginLeft());
@@ -223,13 +280,9 @@
     final Image image = new Image("counting-backwards.png",
         12, 12, 12, 12);
 
-    image.addLoadListener(new LoadListener() {
+    final TestLoadListener listener = new TestLoadListener(image) {
       private int onLoadEventCount = 0;
 
-      public void onError(Widget sender) {
-        fail("The image " + ((Image) sender).getUrl() + " failed to load.");
-      }
-
       public void onLoad(Widget sender) {
         if (++onLoadEventCount == 2) {
           assertEquals(0, image.getOriginLeft());
@@ -237,10 +290,31 @@
           assertEquals(16, image.getWidth());
           assertEquals(16, image.getHeight());
           assertEquals("clipped", getCurrentImageStateName(image));
-          finishTest();
+          finish();
+        }
+      }
+    };
+    image.addLoadListener(listener);
+
+    image.addLoadHandler(new LoadHandler() {
+      private int onLoadEventCount = 0;
+
+      public void onLoad(LoadEvent event) {
+        if (++onLoadEventCount == 2) {
+          assertEquals(0, image.getOriginLeft());
+          assertEquals(16, image.getOriginTop());
+          assertEquals(16, image.getWidth());
+          assertEquals(16, image.getHeight());
+          assertEquals("clipped", getCurrentImageStateName(image));
+          if (listener.isFinished()) {
+            finishTest();
+          } else {
+            fail("Listener did not fire first");
+          }
         }
       }
     });
+    image.addErrorHandler(new TestErrorHandler(image));
 
     RootPanel.get().add(image);
     assertEquals("clipped", getCurrentImageStateName(image));
@@ -252,43 +326,34 @@
 
   /**
    * Tests the behavior of
-   * <code>setUrlAndVisibleRect(String, int, int, int, int)</code> method on
-   * an unclipped image, which causes a state transition to the clipped state.
+   * <code>setUrlAndVisibleRect(String, int, int, int, int)</code> method on an
+   * unclipped image, which causes a state transition to the clipped state.
    */
-  /* This test has been commented out because of issue #863
-  public void testSetUrlAndVisibleRectOnUnclippedImage() {
-    final Image image = new Image("counting-backwards.png");
-
-    image.addLoadListener(new LoadListener() {
-      private int onLoadEventCount = 0;
-
-      public void onError(Widget sender) {
-        fail("The image " + ((Image) sender).getUrl() + " failed to load.");
-      }
-
-      public void onLoad(Widget sender) {
-        if (getCurrentImageStateName(image).equals("unclipped")) {
-          image.setUrlAndVisibleRect("counting-forwards.png",
-              0, 16, 16, 16);
-        }
-
-        if (++onLoadEventCount == 2) {
-          assertEquals(0, image.getOriginLeft());
-          assertEquals(16, image.getOriginTop());
-          assertEquals(16, image.getWidth());
-          assertEquals(16, image.getHeight());
-          assertEquals("clipped", getCurrentImageStateName(image));
-          finishTest();
-        }
-      }
-    });
-
-    RootPanel.get().add(image);
-    assertEquals("unclipped", getCurrentImageStateName(image));
-
-    delayTestFinish(5000);
-  }
-  */
+  /*
+   * This test has been commented out because of issue #863 public void
+   * testSetUrlAndVisibleRectOnUnclippedImage() { final Image image = new
+   * Image("counting-backwards.png");
+   * 
+   * image.addLoadListener(new LoadListener() { private int onLoadEventCount =
+   * 0;
+   * 
+   * public void onError(Widget sender) { fail("The image " + ((Image)
+   * sender).getUrl() + " failed to load."); }
+   * 
+   * public void onLoad(Widget sender) { if
+   * (getCurrentImageStateName(image).equals("unclipped")) {
+   * image.setUrlAndVisibleRect("counting-forwards.png", 0, 16, 16, 16); }
+   * 
+   * if (++onLoadEventCount == 2) { assertEquals(0, image.getOriginLeft());
+   * assertEquals(16, image.getOriginTop()); assertEquals(16, image.getWidth());
+   * assertEquals(16, image.getHeight()); assertEquals("clipped",
+   * getCurrentImageStateName(image)); finishTest(); } } });
+   * 
+   * RootPanel.get().add(image); assertEquals("unclipped",
+   * getCurrentImageStateName(image));
+   * 
+   * delayTestFinish(5000); }
+   */
 
   /**
    * Tests the firing of onload events when calling
@@ -296,22 +361,33 @@
    * on a clipped image.
    */
   public void testSetVisibleRectAndLoadEventsOnClippedImage() {
-    final Image image = new Image("counting-backwards.png",
-        16, 16, 16, 16);
+    final Image image = new Image("counting-backwards.png", 16, 16, 16, 16);
 
-    image.addLoadListener(new LoadListener() {
+    final TestLoadListener listener = new TestLoadListener(image) {
       private int onLoadEventCount = 0;
 
-      public void onError(Widget sender) {
-        fail("The image " + ((Image) sender).getUrl() + " failed to load.");
-      }
-
       public void onLoad(Widget sender) {
         if (++onLoadEventCount == 4) {
-          finishTest();
+          finish();
+        }
+      }
+    };
+    image.addLoadListener(listener);
+
+    image.addLoadHandler(new LoadHandler() {
+      private int onLoadEventCount = 0;
+
+      public void onLoad(LoadEvent event) {
+        if (++onLoadEventCount == 4) {
+          if (listener.isFinished()) {
+            finishTest();
+          } else {
+            fail("Listener did not fire first");
+          }
         }
       }
     });
+    image.addErrorHandler(new TestErrorHandler(image));
 
     RootPanel.get().add(image);
     image.setVisibleRect(0, 0, 16, 16);
diff --git a/user/test/com/google/gwt/user/client/ui/TextAreaTest.java b/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
index a8a984a..1abe0d9 100644
--- a/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
+++ b/user/test/com/google/gwt/user/client/ui/TextAreaTest.java
@@ -16,7 +16,6 @@
 
 package com.google.gwt.user.client.ui;
 
-
 /**
  * Tests a {@link TextArea}.
  */
diff --git a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
index 375fd69..bf47218 100644
--- a/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
+++ b/user/test/com/google/gwt/user/client/ui/TextBoxBaseTestBase.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.junit.client.GWTTestCase;
 
 /**
@@ -93,4 +95,37 @@
       area.selectAll();
     }
   }
+  
+  public void testValueChangeEvent() {
+    TextBoxBase tb = createTextBoxBase();
+
+    // To work cross-platform, the tb must be added to the root panel.
+    RootPanel.get().add(tb);
+    Handler h = new Handler();
+    tb.addValueChangeHandler(h);
+    tb.setText("able");
+    assertNull(h.received);
+    
+    tb.setValue("able");
+    assertNull(h.received);
+    tb.setValue("baker");
+    assertNull(h.received);
+
+    tb.setValue("baker", true);
+    assertNull(h.received);
+    
+    tb.setValue("able", true);
+    assertEquals("able", h.received);
+
+    tb.setValue("baker", true);
+    assertEquals("baker", h.received);
+  }
+  
+  private static class Handler implements ValueChangeHandler<String> {
+    String received = null;
+    
+    public void onValueChange(ValueChangeEvent<String> event) {
+      received = event.getValue();
+    }
+  }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java b/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
index ec4bd20..e305a2e 100644
--- a/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
+++ b/user/test/com/google/gwt/user/client/ui/impl/ClippedImagePrototypeTest.java
@@ -15,15 +15,17 @@
  */
 package com.google.gwt.user.client.ui.impl;
 
+import com.google.gwt.event.dom.client.ErrorEvent;
+import com.google.gwt.event.dom.client.ErrorHandler;
+import com.google.gwt.event.dom.client.LoadEvent;
+import com.google.gwt.event.dom.client.LoadHandler;
 import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.ImageTest;
-import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.LoadListener;
+import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.Timer;
-
-import java.util.ArrayList;
 
 /**
  * Tests for the ClippedImagePrototype implementation. Tests are done to ensure
@@ -34,11 +36,45 @@
  * application of the prototype to the image.
  */
 public class ClippedImagePrototypeTest extends GWTTestCase {
+  @Deprecated
+  private static class TestLoadListener implements LoadListener {
+    private int onloadEventFireCount = 0;
+    private Image image;
 
+    public TestLoadListener(Image image) {
+      this.image = image;
+    }
+
+    public void onError(Widget sender) {
+      fail("The image " + image.getUrl() + " failed to load.");
+    }
+
+    public int getOnloadEventFireCount() {
+      return onloadEventFireCount;
+    }
+
+    public void onLoad(Widget sender) {
+      onloadEventFireCount++;
+    }
+  }
+  
+  private static class TestLoadHandler implements LoadHandler {
+    private int onloadEventFireCount = 0;
+
+    public int getOnloadEventFireCount() {
+      return onloadEventFireCount;
+    }
+
+    public void onLoad(LoadEvent event) {
+      onloadEventFireCount++;
+    }
+  }
+  
+  @Override
   public String getModuleName() {
     return "com.google.gwt.user.UserTest";
   }
-
+ 
   /**
    * Tests that a clipped image can be transformed to match a given prototype.
    * Also checks to make sure that a load event is fired on when
@@ -55,15 +91,10 @@
     assertEquals(8, image.getHeight());
     assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
 
-    final ArrayList onloadEventFireCounter = new ArrayList();
-
-    image.addLoadListener(new LoadListener() {
-      public void onError(Widget sender) {
-        fail("The image " + ((Image) sender).getUrl() + " failed to load.");
-      }
-
+    final TestLoadListener listener = new TestLoadListener(image) {
+      @Override
       public void onLoad(Widget sender) {
-        onloadEventFireCounter.add(new Object());
+        super.onLoad(sender);
 
         if (image.getOriginLeft() == 12 && image.getOriginTop() == 13) {
           ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
@@ -78,14 +109,43 @@
           assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
         }
       }
-    });
+    };
+    image.addLoadListener(listener);
 
+    final TestLoadHandler handler = new TestLoadHandler() {
+      @Override
+      public void onLoad(LoadEvent event) {
+        super.onLoad(event);
+
+        if (image.getOriginLeft() == 12 && image.getOriginTop() == 13) {
+          ClippedImagePrototype clippedImagePrototype = new ClippedImagePrototype(
+              "counting-forwards.png", 16, 16, 16, 16);
+
+          clippedImagePrototype.applyTo(image);
+
+          assertEquals(16, image.getOriginLeft());
+          assertEquals(16, image.getOriginTop());
+          assertEquals(16, image.getWidth());
+          assertEquals(16, image.getHeight());
+          assertEquals("clipped", ImageTest.getCurrentImageStateName(image));
+        }
+      }
+    };
+    image.addLoadHandler(handler);
+    image.addErrorHandler(new ErrorHandler() {
+      public void onError(ErrorEvent event) {
+        fail("The image " + image.getUrl() + " failed to load.");
+      }
+    });
+    
     RootPanel.get().add(image);
     delayTestFinish(2000);
 
     Timer t = new Timer() {
+      @Override
       public void run() {
-        assertEquals(2, onloadEventFireCounter.size());
+        assertEquals(2, listener.getOnloadEventFireCount());
+        assertEquals(2, handler.getOnloadEventFireCount());
         finishTest();
       }
     };
diff --git a/user/test/com/google/gwt/user/server/rpc/RPCRequestTest.java b/user/test/com/google/gwt/user/server/rpc/RPCRequestTest.java
new file mode 100644
index 0000000..a8d4bfa
--- /dev/null
+++ b/user/test/com/google/gwt/user/server/rpc/RPCRequestTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.server.rpc;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Method;
+
+/**
+ * Tests the deserialized RPC request object.
+ */
+public class RPCRequestTest extends TestCase {
+
+  /**
+   * Just a class to get a dummy method from for the request.
+   */
+  private class MockRequestImplementation {
+    public String doSomething(String a, int b) {
+      // This is never called, we just reflect on it
+      return null;
+    }
+  }
+
+  /**
+   * Tests getting the equivalent string of an RPC request.
+   */
+  public void testToString() throws Exception {
+    Method method = MockRequestImplementation.class.getMethod("doSomething",
+        String.class, int.class);
+
+    // Test simple case
+    Object params[] = new Object[] {"abcdefg", 1234};
+    RPCRequest request = new RPCRequest(method, params, null);
+    String strRequest = request.toString();
+    assertEquals("com.google.gwt.user.server.rpc.RPCRequestTest$"
+        + "MockRequestImplementation.doSomething(\"abcdefg\", 1234)",
+        strRequest);
+
+    // Test case with a string that needs escaping
+    Object params2[] = new Object[] {"ab\"cde\"fg", 1234};
+    RPCRequest request2 = new RPCRequest(method, params2, null);
+    String strRequest2 = request2.toString();
+    System.out.println(strRequest2);
+    assertEquals("com.google.gwt.user.server.rpc.RPCRequestTest$"
+        + "MockRequestImplementation.doSomething(\"ab\\\"cde\\\"fg\", 1234)",
+        strRequest2);
+  }
+}
\ No newline at end of file