Merge branch 'develop' into task/JAL-3130_Java_11_investigations-getdown_src
authorJim Procter <jprocter@issues.jalview.org>
Thu, 11 Apr 2019 13:52:20 +0000 (14:52 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Thu, 11 Apr 2019 13:52:20 +0000 (14:52 +0100)
1  2 
.classpath
build-j11.xml
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/gui/AlignFrame.java
test/jalview/bin/CommandLineOperations.java
test/jalview/gui/SeqPanelTest.java
test/jalview/util/PlatformTest.java

diff --combined .classpath
@@@ -3,11 -3,15 +3,11 @@@
        <classpathentry kind="src" path="src"/>
        <classpathentry kind="src" path="utils"/>
        <classpathentry kind="src" path="test"/>
 -      <classpathentry kind="lib" path="lib/activation.jar"/>
        <classpathentry kind="lib" path="lib/axis.jar" sourcepath="D:/axis-1_2RC2-src/axis-1_2RC2"/>
        <classpathentry kind="lib" path="lib/commons-discovery.jar"/>
        <classpathentry kind="lib" path="lib/jaxrpc.jar"/>
        <classpathentry kind="lib" path="lib/jhall.jar"/>
 -      <classpathentry kind="lib" path="lib/mail.jar"/>
        <classpathentry kind="lib" path="lib/regex.jar"/>
 -      <classpathentry kind="lib" path="lib/saaj.jar"/>
 -      <classpathentry kind="lib" path="lib/wsdl4j.jar"/>
        <classpathentry kind="lib" path="lib/xercesImpl.jar"/>
        <classpathentry kind="lib" path="lib/JGoogleAnalytics_0.3.jar" sourcepath="/JGoogleAnalytics/src/main/java"/>
        <classpathentry kind="lib" path="lib/vamsas-client.jar"/>
        <classpathentry kind="lib" path="lib/VAqua5-patch.jar"/>
        <classpathentry kind="lib" path="utils/classgraph-4.1.6.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin"/>
 -      <classpathentry kind="lib" path="lib/xml-apis.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Plugin.jar"/>
        <classpathentry kind="lib" path="lib/jersey-client-1.19.jar"/>
        <classpathentry kind="lib" path="lib/jersey-core-1.19.jar"/>
 -      <classpathentry kind="lib" path="lib/jsr311-api-1.1.1.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin.jar"/>
        <classpathentry kind="lib" path="lib/jetty-server-9.2.10.v20150310.jar"/>
 -      <classpathentry kind="lib" path="lib/servlet-api-3.1.jar"/>
        <classpathentry kind="lib" path="lib/jetty-util-9.2.10.v20150310.jar"/>
        <classpathentry kind="lib" path="lib/jetty-http-9.2.10.v20150310.jar"/>
        <classpathentry kind="lib" path="lib/jetty-io-9.2.10.v20150310.jar"/>
@@@ -60,6 -67,6 +60,6 @@@
        <classpathentry kind="lib" path="lib/htsjdk-2.12.0.jar"/>
        <classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
-       <classpathentry kind="lib" path="lib/intervalstore-v0.4.jar"/>
+       <classpathentry kind="lib" path="lib/intervalstore-v1.0.jar"/>
        <classpathentry kind="output" path="classes"/>
  </classpath>
diff --combined build-j11.xml
@@@ -44,7 -44,6 +44,7 @@@
      <echo message="note: compile and makeApplet optionally compile/obfuscate applet against a different Java version by specifying -Djava118.home=PathtoJDK/lib which is the lib directory in the JDK install that contains rt.jar " />
      <echo message="Useful -D flags: -Ddonotobfuscate will prevent applet obfuscation" />
      <echo message="Useful -D flags: -Dclover.jar to specify path to openclover for testng coverage report" />
 +    <echo message="Useful -D flags: -Ddeprecation=true to add -Xlint:deprecation to the java compiler" />
    </target>
  
  
      <condition property="java9">
        <equals arg1="${ant.java.version}" arg2="9"/>
      </condition>
 +    <!-- Java 10 JVM args -->
 +    <condition property="java10">
 +      <equals arg1="${ant.java.version}" arg2="10"/>
 +    </condition>
 +    <!-- Java 11 JVM args -->
 +    <condition property="java11">
 +      <equals arg1="${ant.java.version}" arg2="11"/>
 +    </condition>
 +    <echo message="ant.java.version is ${ant.java.version}"/>
  
      <!-- Don't change anything below here unless you know what you are doing! -->
      <!-- Url path for WebStart in JNLP file -->
      <!-- Anne's version needs 1.7 - should rebuild VARNA to java 1.6 for release -->
      <property name="j2sev" value="1.7+" />
      <!-- Java Compilation settings - source and target javac version -->
 -    <property name="javac.source" value="1.8" />
 -    <property name="javac.target" value="1.8" />
 +    <property name="javac.source" value="11" if:set="java11" />
 +    <property name="javac.target" value="11" if:set="java11" />
 +    <property name="javac.source" value="1.8" unless:set="java11" />
 +    <property name="javac.target" value="1.8" unless:set="java11" />
 +    <echo message="javac.source is ${javac.source}"/>
 +    <echo message="javac.target is ${javac.target}"/>
  
      <!-- Permissions for running Java applets and applications. -->
      <!-- Defaults are those suitable for deploying jalview webstart www.jalview.org -->
  
      <!-- build directory configuration -->
      <property name="libDir" value="lib" />
 +    <property name="j11libDir" value="j11lib" />
      <property name="resourceDir" value="resources" />
      <property name="helpDir" value="help" />
      <property name="docDir" value="doc" />
          <include name="*.jar" />
          <include name="**/*.jar" />
        </fileset>
 +      <fileset dir="${j11libDir}">
 +        <include name="*.jar" />
 +        <include name="**/*.jar" />
 +      </fileset>
        <fileset dir="${libDir}">
          <include name="*.jar" />
          <include name="**/*.jar" />
          <include name="${jmolJar}" />
          <include name="${varnaJar}" />
        </fileset>
 +      <pathelement location="${clover.jar}" if:set="clover.jar"/>
      </path>
      <path id="test.classpath">
        <pathelement path="${outputDir}" />
  
    <target name="build" depends="prepare">
      <!-- not efficient yet. -->
 -    <javac source="${javac.source}" target="${javac.target}" srcdir="${sourceDir}" destdir="${outputDir}" debug="${javac.debug}" classpathref="build.classpath">
 +    <!-- Echo the build.classpath
 +    <pathconvert property="echoClasspath" refid="build.classpath" />
 +    <echo message="build.classpath is '${echoClasspath}'" />
 +    -->
 +    <echo message="javac.target is '${javac.target}'" />
 +    <echo message="adding -Xlint:deprecation to javac" if:set="deprecation"/>
 +    <javac includeantruntime="false" source="${javac.source}" target="${javac.target}" srcdir="${sourceDir}" destdir="${outputDir}" debug="${javac.debug}" classpathref="build.classpath">
 +      <compilerarg value="-Xlint:deprecation" if:set="deprecation" />
        <exclude name="jalview/*applet*" />
        <exclude name="jalview/appletgui/**" />
        <exclude name="com/stevesoft/**" />
    <taskdef resource="testngtasks" classpath="utils/testnglibs/testng.jar" />
  
    <target name="testng" depends="buildTests">
 +    <loadfile property="j11modules" srcFile="modules">
 +      <filterchain>
 +        <striplinebreaks/>
 +      </filterchain>
 +    </loadfile>
 +    <echo message="j11libDir is '${j11libDir}'" />
 +    <echo message="j11modules is '${j11modules}'" />
      <testng outputDir="${reportDir}" haltOnFailure="false" groups="${testng-groups}" mode="testng"
        verbose="2">
        <classpath>
          <pathelement location="${clover.jar}" if:set="clover.jar"/>
          <path refid="test.classpath" />
        </classpath>
 +      <!--
 +      <jvmarg value="DASH_DASH_module-path=${j11libDir}:${java.home}/jmods" if:set="java11"/>
 +      -->
 +      <jvmarg value="--module-path=${j11libDir}" if:set="java11"/>
 +      <jvmarg value="--add-modules=${j11modules}" if:set="java11"/>
        <jvmarg value="--add-modules=java.se.ee" if:set="java9"/>
        <jvmarg value="--illegal-access=warn" if:set="java9"/>
        <classfileset dir="${testOutputDir}" includes="**/*.class" />
 +    </testng>
 +  </target>
 +
 +  <target name="testngclass" depends="buildTests">
 +    <condition property="propsSpecified">
 +      <isset property="class.name" />
 +    </condition>
 +    <fail unless="propsSpecified" message="class.name property not specified."/>
 +    <echo message="testng-groups is '${testng-groups}'" />
 +    <loadfile property="j11modules" srcFile="modules"/>
 +    <testng outputDir="${reportDir}" haltOnFailure="false" groups="${testng-groups}" mode="testng" verbose="2">
 +      <classpath>
 +        <pathelement location="${testOutputDir}" />
 +        <pathelement location="${clover.jar}" if:set="clover.jar"/>
 +        <path refid="test.classpath" />
 +      </classpath>
 +      <jvmarg value="--module-path=${j11libDir}:${java.home}/jmods" if:set="java11"/>
 +      <jvmarg value="--add-modules=${j11modules}" if:set="java11"/>
 +      <jvmarg value="--add-modules=java.se.ee" if:set="java9"/>
 +      <jvmarg value="--illegal-access=warn" if:set="java9"/>
 +      <classfileset dir="${testOutputDir}" includes="${class.name}" />
      </testng>
    </target>
  
  </target>
  
  <target name="signApplet" description="internal target to sign applet" depends="-signappletnotsa,-signapplettsa" />
+ <target name="pubapplet" description="Dummy target to keep legacy Jalview build system happy. We don't actually publish the applet anymore."/>
  
- <target name="pubapplet" description="installs the jalviewLite applet and dependent jars into an applet examples directory built under ${outputDir}" depends="makeApplet, signApplet">
+ <target name="_pubapplet" description="installs the jalviewLite applet and dependent jars into an applet examples directory built under ${outputDir}" depends="makeApplet, signApplet">
  
    <!-- bizarre bug causes JmolApplet to always get signed, even if excluded from above. so copy explicitly -->
    <copy file="appletlib/${jmolJar}" tofile="${packageDir}/examples/u_${jmolJar}" overwrite="true" />
@@@ -32,7 -32,6 +32,7 @@@ action.load_project = Load Projec
  action.save_project = Save Project
  action.save_project_as = Save Project as...
  action.quit = Quit
 +label.quit_jalview = Quit Jalview?
  action.expand_views = Expand Views
  action.gather_views = Gather Views
  action.page_setup = Page Setup...
@@@ -185,22 -184,22 +185,22 @@@ label.out_to_textbox = Output to Textbo
  label.occupancy = Occupancy
  # delete Clustal - use FileFormat name instead
  label.clustal = Clustal
- # label.colourScheme_<schemeName> as in JalviewColourScheme
+ # label.colourScheme_<schemeName> as in JalviewColourScheme, spaces removed
  label.colourScheme_clustal = Clustalx
  label.colourScheme_blosum62 = BLOSUM62 Score
- label.colourScheme_%_identity = Percentage Identity
+ label.colourScheme_%identity = Percentage Identity
  label.colourScheme_zappo = Zappo
  label.colourScheme_taylor = Taylor
  label.colourScheme_hydrophobic = Hydrophobicity
- label.colourScheme_helix_propensity = Helix Propensity
- label.colourScheme_strand_propensity = Strand Propensity
- label.colourScheme_turn_propensity = Turn Propensity
- label.colourScheme_buried_index = Buried Index
+ label.colourScheme_helixpropensity = Helix Propensity
+ label.colourScheme_strandpropensity = Strand Propensity
+ label.colourScheme_turnpropensity = Turn Propensity
+ label.colourScheme_buriedindex = Buried Index
  label.colourScheme_purine/pyrimidine = Purine/Pyrimidine
  label.colourScheme_nucleotide = Nucleotide
- label.colourScheme_t-coffee_scores = T-Coffee Scores
- label.colourScheme_rna_helices = By RNA Helices
- label.colourScheme_sequence_id = Sequence ID Colour
+ label.colourScheme_t-coffeescores = T-Coffee Scores
+ label.colourScheme_rnahelices = By RNA Helices
+ label.colourScheme_sequenceid = Sequence ID Colour
  label.blc = BLC
  label.fasta = Fasta
  label.msf = MSF
@@@ -32,7 -32,6 +32,7 @@@ action.load_project = Cargar proyect
  action.save_project = Guardar proyecto
  action.save_project_as = Guardar proyecto como...
  action.quit = Salir
 +label.quit_jalview = Salir Javliew?
  action.expand_views = Expandir vistas
  action.gather_views = Capturar vistas
  action.page_setup = Configuración de la página
@@@ -184,19 -183,19 +184,19 @@@ label.clustal = Clusta
  # label.colourScheme_<schemeName> as in JalviewColourScheme
  label.colourScheme_clustal = Clustalx
  label.colourScheme_blosum62 = Puntuación del BLOSUM62
- label.colourScheme_%_identity = Porcentaje de identidad
+ label.colourScheme_%identity = Porcentaje de identidad
  label.colourScheme_zappo = Zappo
  label.colourScheme_taylor = Taylor
  label.colourScheme_hydrophobic = Hidrofobicidad
- label.colourScheme_helix_propensity = Tendencia de la hélice
- label.colourScheme_strand_propensity = Tendencia de la hebra
- label.colourScheme_turn_propensity = Tendencia de giro
- label.colourScheme_buried_index = Índice de encubrimiento
+ label.colourScheme_helixpropensity = Tendencia de la hélice
+ label.colourScheme_strandpropensity = Tendencia de la hebra
+ label.colourScheme_turnpropensity = Tendencia de giro
+ label.colourScheme_buriedindex = Índice de encubrimiento
  label.colourScheme_purine/pyrimidine = Purina/Pirimidina
  label.colourScheme_nucleotide = Nucleótido
- label.colourScheme_t-coffee_scores = Puntuación del T-Coffee
- label.colourScheme_rna_helices = Por hélices de RNA
- label.colourScheme_sequence_id = Color de ID de secuencia
+ label.colourScheme_t-coffeescores = Puntuación del T-Coffee
+ label.colourScheme_rnahelices = Por hélices de RNA
+ label.colourScheme_sequenceid = Color de ID de secuencia
  label.blc = BLC
  label.fasta = Fasta
  label.msf = MSF
@@@ -974,7 -974,7 +974,7 @@@ public class AlignFrame extends GAlignF
    @Override
    public void setStatus(String text)
    {
-     statusBar.setText(text);
+     statusBar.setText(text == null || text.isEmpty() ? " " : text);
    }
  
    /*
            PrintWriter out = new PrintWriter(
                    new FileWriter(backupfiles.getTempFilePath()));
  
 +          // TESTING code here
 +          boolean TESTING = true;
 +          if (TESTING)
 +          {
 +            out.print("; TESTSTART\n");
 +            int count = 20;
 +            for (int i = 0; i < count; i++)
 +            {
 +              // Thread.sleep(1000);
 +              out.println("; TEST: " + (count - 1 - i));
 +            }
 +          }
            out.print(output);
 +          if (TESTING)
 +          {
 +            out.print("; TESTEND\n");
 +          }
            out.close();
            this.setTitle(file);
            statusBar.setText(MessageManager.formatMessage(
                      newGraphGroups.add(q, null);
                    }
                    newGraphGroups.set(newann.graphGroup,
 -                          new Integer(++fgroup));
 +                          Integer.valueOf(++fgroup));
                  }
                  newann.graphGroup = newGraphGroups.get(newann.graphGroup)
                          .intValue();
                      newGraphGroups.add(q, null);
                    }
                    newGraphGroups.set(newann.graphGroup,
 -                          new Integer(++fgroup));
 +                          Integer.valueOf(++fgroup));
                  }
                  newann.graphGroup = newGraphGroups.get(newann.graphGroup)
                          .intValue();
    protected void scaleAbove_actionPerformed(ActionEvent e)
    {
      viewport.setScaleAboveWrapped(scaleAbove.isSelected());
-     // TODO: do we actually need to update overview for scale above change ?
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
    protected void scaleLeft_actionPerformed(ActionEvent e)
    {
      viewport.setScaleLeftWrapped(scaleLeft.isSelected());
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
    protected void scaleRight_actionPerformed(ActionEvent e)
    {
      viewport.setScaleRightWrapped(scaleRight.isSelected());
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
              int assocfiles = 0;
              if (filesmatched.size() > 0)
              {
 -              boolean autoAssociate = Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
 +              boolean autoAssociate = Cache
 +                      .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
                if (!autoAssociate)
                {
                  String msg = MessageManager.formatMessage(
@@@ -20,6 -20,9 +20,9 @@@
   */
  package jalview.bin;
  
+ import static org.testng.Assert.assertNotNull;
+ import static org.testng.Assert.assertTrue;
  import jalview.gui.JvOptionPane;
  
  import java.io.BufferedReader;
@@@ -48,8 -51,7 +51,8 @@@ public class CommandLineOperation
      JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
    }
  
 -  private static final int TEST_TIMEOUT = 9000; // Note longer timeout needed on
 +  private static final int TEST_TIMEOUT = 9000; // Note longer timeout needed
 +                                                // on
                                                  // full test run than on
                                                  // individual tests
  
      return classpath;
    }
  
-   private Worker jalviewDesktopRunner(boolean withAwt, String cmd,
+   private Worker getJalviewDesktopRunner(boolean withAwt, String cmd,
            int timeout)
    {
      // Note: JAL-3065 - don't include quotes for lib/* because the arguments are
      // not expanded by the shell
      String classpath = getClassPath();
 -    String _cmd = "java "
 -            + (withAwt ? "-Djava.awt.headless=true" : "")
 +    String _cmd = "java " + (withAwt ? "-Djava.awt.headless=true" : "")
              + " -classpath " + classpath + " jalview.bin.Jalview ";
      Process ls2_proc = null;
      Worker worker = null;
      try
      {
        ls2_proc = Runtime.getRuntime().exec(_cmd + cmd);
-     } catch (IOException e1)
+     } catch (Throwable e1)
      {
        e1.printStackTrace();
      }
          worker.join(timeout);
        } catch (InterruptedException e)
        {
-         // e.printStackTrace();
+         System.err.println("Thread interrupted");
        }
        worker.setOutputReader(outputReader);
        worker.setErrorReader(errorReader);
    public void setUpForHeadlessCommandLineInputOperations()
            throws IOException
    {
-     String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props FILE -colour zappo "
-             + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree -dasserver nickname=www.test.com "
+     String cmds = "nodisplay -open examples/uniref50.fa -sortbytree -props test/jalview/io/testProps.jvprops -colour zappo "
+             + "-jabaws http://www.compbio.dundee.ac.uk/jabaws -nosortbytree "
              + "-features examples/testdata/plantfdx.features -annotations examples/testdata/plantfdx.annotations -tree examples/testdata/uniref50_test_tree";
-     Worker worker = jalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
+     Worker worker = getJalviewDesktopRunner(true, cmds, SETUP_TIMEOUT);
      String ln = null;
      while ((ln = worker.getOutputReader().readLine()) != null)
      {
        System.out.println(ln);
        successfulCMDs.add(ln);
      }
+     while ((ln = worker.getErrorReader().readLine()) != null)
+     {
+       System.err.println(ln);
+     }
    }
  
    @BeforeTest(alwaysRun = true)
    public void setUpForCommandLineInputOperations() throws IOException
    {
      String cmds = "-open examples/uniref50.fa -noquestionnaire -nousagestats";
-     Worker worker = jalviewDesktopRunner(false, cmds, SETUP_TIMEOUT);
+     Worker worker = getJalviewDesktopRunner(false, cmds, SETUP_TIMEOUT);
      String ln = null;
      int count = 0;
      while ((ln = worker.getErrorReader().readLine()) != null)
      }
    }
  
-   @Test(groups = { "Functional" }, dataProvider = "allInputOpearationsData")
+   @Test(groups = { "Functional" }, dataProvider = "allInputOperationsData")
    public void testAllInputOperations(String expectedString,
            String failureMsg)
    {
    }
  
    @Test(
 -    groups = { "Functional" },
 +    groups =
 +    { "Functional", "testben" },
      dataProvider = "headlessModeOutputOperationsData")
    public void testHeadlessModeOutputOperations(String harg, String type,
            String fileName, boolean withAWT, int expectedMinFileSize,
      String cmd = harg + type + " " + fileName;
      // System.out.println(">>>>>>>>>>>>>>>> Command : " + cmd);
      File file = new File(fileName);
-     Worker worker = jalviewDesktopRunner(withAWT, cmd, timeout);
-     FileAssert.assertFile(file,
-             "Didn't create an output" + type + " file.[" + harg + "]");
-     // System.out.println( "File '" + file.getName() + "' has size " +
-     // file.length());
-     // FileAssert.assertMinLength(new File(fileName), expectedMinFileSize);
+     file.deleteOnExit();
+     Worker worker = getJalviewDesktopRunner(withAWT, cmd, timeout);
+     assertNotNull(worker, "worker is null");
+     String msg = "Didn't create an output" + type + " file.[" + harg + "]";
+     assertTrue(file.exists(), msg);
+     FileAssert.assertFile(file, msg);
      FileAssert.assertMinLength(file, expectedMinFileSize);
      if (worker != null && worker.exit == null)
      {
        worker.interrupt();
        Thread.currentThread().interrupt();
        worker.process.destroy();
 -      Assert.fail("Jalview did not exit after "
 -              + type
 +      Assert.fail("Jalview did not exit after " + type
                + " generation (try running test again to verify - timeout at "
 -              + SETUP_TIMEOUT + "ms). ["
 -              + harg + "]");
 +              + timeout + "ms). [" + harg + "]");
      }
-     new File(fileName).delete();
+     file.delete();
    }
  
-   @DataProvider(name = "allInputOpearationsData")
+   @DataProvider(name = "allInputOperationsData")
    public Object[][] getHeadlessModeInputParams()
    {
      return new Object[][] {
          // headless mode input operations
          { "CMD [-color zappo] executed successfully!",
              "Failed command : -color zappo" },
-         { "CMD [-props FILE] executed successfully!",
+         { "CMD [-props test/jalview/io/testProps.jvprops] executed successfully!",
              "Failed command : -props File" },
          { "CMD [-sortbytree] executed successfully!",
              "Failed command : -sortbytree" },
              "Failed command : -open examples/uniref50.fa" },
          { "CMD [-nosortbytree] executed successfully!",
              "Failed command : -nosortbytree" },
-         {
-             "CMD [-features examples/testdata/plantfdx.features]  executed successfully!",
+         { "CMD [-features examples/testdata/plantfdx.features]  executed successfully!",
              "Failed command : -features examples/testdata/plantfdx.features" },
          { "CMD [-annotations examples/testdata/plantfdx.annotations] executed successfully!",
              "Failed command : -annotations examples/testdata/plantfdx.annotations" },
              "Failed command : -nousagestats" },
          { "CMD [-noquestionnaire] executed successfully!",
              "Failed command : -noquestionnaire" } };
    }
  
    @DataProvider(name = "headlessModeOutputOperationsData")
    public static Object[][] getHeadlessModeOutputParams()
    {
--    return new Object[][] {
--        { "nodisplay -open examples/uniref50.fa", " -eps",
-             "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
 -            "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
 -            TEST_TIMEOUT },
++    return new Object[][] { { "nodisplay -open examples/uniref50.fa",
++        " -eps", "test/jalview/bin/test_uniref50_out.eps", true,
++        MINFILESIZE_BIG, TEST_TIMEOUT },
          { "nodisplay -open examples/uniref50.fa", " -eps",
-             "test_uniref50_out.eps", false, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.eps", false,
+             MINFILESIZE_BIG, TEST_TIMEOUT },
          { "nogui -open examples/uniref50.fa", " -eps",
-             "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
+             TEST_TIMEOUT },
          { "nogui -open examples/uniref50.fa", " -eps",
-             "test_uniref50_out.eps", false, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.eps", false,
+             MINFILESIZE_BIG, TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -eps",
-             "test_uniref50_out.eps", true, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.eps", true, MINFILESIZE_BIG,
+             TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -svg",
-             "test_uniref50_out.svg", false, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.svg", false,
+             MINFILESIZE_BIG, TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -png",
-             "test_uniref50_out.png", true, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.png", true, MINFILESIZE_BIG,
+             TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -html",
-             "test_uniref50_out.html", true, MINFILESIZE_BIG, TEST_TIMEOUT },
+             "test/jalview/bin/test_uniref50_out.html", true,
+             MINFILESIZE_BIG, TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -fasta",
 -            "test/jalview/bin/test_uniref50_out.mfa", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.mfa", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -clustal",
 -            "test/jalview/bin/test_uniref50_out.aln", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -msf",
 -            "test/jalview/bin/test_uniref50_out.msf", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.msf", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -pileup",
 -            "test/jalview/bin/test_uniref50_out.aln", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.aln", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -pir",
 -            "test/jalview/bin/test_uniref50_out.pir", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.pir", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -pfam",
 -            "test/jalview/bin/test_uniref50_out.pfam", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.pfam", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -blc",
 -            "test/jalview/bin/test_uniref50_out.blc", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT },
 +            "test_uniref50_out.blc", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT },
          { "headless -open examples/uniref50.fa", " -jalview",
 -            "test/jalview/bin/test_uniref50_out.jvp", true,
 -            MINFILESIZE_SMALL, TEST_TIMEOUT }, };
 +            "test_uniref50_out.jvp", true, MINFILESIZE_SMALL,
 +            TEST_TIMEOUT }, };
    }
  }
@@@ -40,7 -40,8 +40,7 @@@ import jalview.io.DataSourceType
  import jalview.io.FileLoader;
  import jalview.util.MessageManager;
  
 -import java.awt.Event;
 -import java.awt.EventQueue;
 +import java.awt.event.InputEvent;import java.awt.EventQueue;
  import java.awt.event.MouseEvent;
  import java.lang.reflect.InvocationTargetException;
  
@@@ -240,7 -241,7 +240,7 @@@ public class SeqPanelTes
      /*
       * mouse at top left of unwrapped panel
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
              0, 0, 0, false, 0);
      MousePos pos = testee.findMousePosition(evt);
      assertEquals(pos.column, 0);
      av.setScaleAboveWrapped(false);
      av.setScaleLeftWrapped(false);
      av.setScaleRightWrapped(false);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     waitForSwing(); // for Swing thread
+     alignFrame.alignPanel.updateLayout();
  
      final int charHeight = av.getCharHeight();
      final int charWidth = av.getCharWidth();
       * mouse at top left of wrapped panel; there is a gap of charHeight
       * above the alignment
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
              0, 0, 0, false, 0);
      MousePos pos = testee.findMousePosition(evt);
      assertEquals(pos.column, 0);
       * cursor at bottom of gap above
       */
      y = charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor over top of first sequence
       */
      y = charHeight;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
       * cursor at bottom of first sequence
       */
      y = 2 * charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
       * cursor at top of second sequence
       */
      y = 2 * charHeight;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 1);
       * cursor at bottom of second sequence
       */
      y = 3 * charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 1);
       * cursor at bottom of last sequence
       */
      y = charHeight * (1 + alignmentHeight) - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
       * method reports index of nearest sequence above
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
       * cursor still in the gap above annotations, now at the bottom of it
       */
      y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
         * cursor at the top of the n'th annotation  
         */
        y += 1;
 -      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +      evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
                false, 0);
        pos = testee.findMousePosition(evt);
        assertEquals(pos.seqIndex, alignmentHeight - 1);
         * cursor at the bottom of the n'th annotation  
         */
        y += annotationRows[n].height - 1;
 -      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +      evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
                false, 0);
        pos = testee.findMousePosition(evt);
        assertEquals(pos.seqIndex, alignmentHeight - 1);
       * cursor in gap between wrapped widths  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at bottom of gap between wrapped widths  
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at top of first sequence, second wrapped width  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
      av.setScaleAboveWrapped(true);
      av.setScaleLeftWrapped(false);
      av.setScaleRightWrapped(false);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     waitForSwing();
+     alignFrame.alignPanel.updateLayout();
  
      final int charHeight = av.getCharHeight();
      final int charWidth = av.getCharWidth();
       * mouse at top left of wrapped panel; there is a gap of charHeight
       * above the alignment
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
              0, 0, 0, false, 0);
      MousePos pos = testee.findMousePosition(evt);
      assertEquals(pos.column, 0);
       * two charHeights including scale panel
       */
      y = 2 * charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor over top of first sequence
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
       * cursor at bottom of first sequence
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
       * cursor at top of second sequence
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 1);
       * cursor at bottom of second sequence
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 1);
       * (scale + gap + sequences)
       */
      y = charHeight * (2 + alignmentHeight) - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
       * cursor below sequences, in 3-pixel gap above annotations
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
       * method reports index of nearest sequence above  
       */
      y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
         * cursor at the top of the n'th annotation  
         */
        y += 1;
 -      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +      evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
                false, 0);
        pos = testee.findMousePosition(evt);
        assertEquals(pos.seqIndex, alignmentHeight - 1);
         * cursor at the bottom of the n'th annotation  
         */
        y += annotationRows[n].height - 1;
 -      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +      evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
                false, 0);
        pos = testee.findMousePosition(evt);
        assertEquals(pos.seqIndex, alignmentHeight - 1);
       * cursor in gap between wrapped widths  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at bottom of gap between wrapped widths  
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at top of scale, second wrapped width  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at bottom of scale, second wrapped width  
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at top of first sequence, second wrapped width  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
      av.setScaleAboveWrapped(false);
      av.setScaleLeftWrapped(false);
      av.setScaleRightWrapped(false);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     waitForSwing();
+     alignFrame.alignPanel.updateLayout();
  
      final int charHeight = av.getCharHeight();
      final int charWidth = av.getCharWidth();
       * mouse at top left of wrapped panel; there is a gap of charHeight
       * above the alignment
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
              0, 0, 0, false, 0);
      MousePos pos = testee.findMousePosition(evt);
      assertEquals(pos.column, 0);
       * cursor over top of first sequence
       */
      y = charHeight;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
       * cursor at bottom of last sequence
       */
      y = charHeight * (1 + alignmentHeight) - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, alignmentHeight - 1);
       * cursor below sequences, at top of charHeight gap between widths
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor below sequences, at top of charHeight gap between widths
       */
      y += charHeight - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, -1);
       * cursor at the top of the first sequence, second width  
       */
      y += 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
              false, 0);
      pos = testee.findMousePosition(evt);
      assertEquals(pos.seqIndex, 0);
      /*
       * mouse at top left of unwrapped panel
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
              0, 0, 0, false, 0);
      assertEquals(testee.findColumn(evt), 0);
      
       * not quite one charWidth across
       */
      x = charWidth-1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
              0, 0, 0, false, 0);
      assertEquals(testee.findColumn(evt), 0);
  
       * one charWidth across
       */
      x = charWidth;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), 1);
  
       * two charWidths across
       */
      x = 2 * charWidth;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), 2);
  
       * limited to last column of seqcanvas
       */
      x = 20000;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas;
      int w = seqCanvas.getWidth();
      alignFrame.getViewport().hideColumns(4, 9);
      x = 5 * charWidth + 2;
      // x is in 6th visible column, absolute column 12, or 11 base 0
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), 11);
    }
      av.setScaleAboveWrapped(false);
      av.setScaleLeftWrapped(false);
      av.setScaleRightWrapped(false);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     // need to wait for repaint to finish!
-     waitForSwing();
+     alignFrame.alignPanel.updateLayout();
      SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
      int x = 0;
      final int charWidth = av.getCharWidth();
      /*
       * mouse at top left of wrapped panel, no West (left) scale
       */
 -    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
 +    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
              0, 0, 0, false, 0);
      assertEquals(testee.findColumn(evt), 0);
      
       * not quite one charWidth across
       */
      x = charWidth-1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
              0, 0, 0, false, 0);
      assertEquals(testee.findColumn(evt), 0);
    
       * one charWidth across
       */
      x = charWidth;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), 1);
  
       * x over scale left (before drawn columns) results in -1
       */
      av.setScaleLeftWrapped(true);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     waitForSwing();
+     alignFrame.alignPanel.updateLayout();
      SeqCanvas seqCanvas = testee.seqCanvas;
      int labelWidth = (int) PA.getValue(seqCanvas, "labelWidthWest");
      assertTrue(labelWidth > 0);
      x = labelWidth - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), -1);
  
      x = labelWidth;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), 0);
  
      int residuesWide = av.getRanges().getViewportWidth();
      assertTrue(residuesWide > 0);
      x = labelWidth + charWidth * residuesWide - 1;
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), residuesWide - 1);
  
       * x over scale right (beyond drawn columns) results in -1
       */
      av.setScaleRightWrapped(true);
-     alignFrame.alignPanel.paintAlignment(false, false);
-     waitForSwing();
+     alignFrame.alignPanel.updateLayout();
      labelWidth = (int) PA.getValue(seqCanvas, "labelWidthEast");
      assertTrue(labelWidth > 0);
      int residuesWide2 = av.getRanges().getViewportWidth();
      assertTrue(residuesWide2 > 0);
      assertTrue(residuesWide2 < residuesWide); // available width reduced
      x += 1; // just over left edge of scale right
 -    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
 +    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
              false, 0);
      assertEquals(testee.findColumn(evt), -1);
      
@@@ -26,7 -26,8 +26,8 @@@ import static org.testng.Assert.assertT
  import jalview.gui.JvOptionPane;
  
  import java.awt.Button;
 -import java.awt.Event;
+ import java.awt.Toolkit;
 +import java.awt.event.InputEvent;
  import java.awt.event.MouseEvent;
  
  import org.testng.annotations.BeforeClass;
@@@ -51,6 -52,16 +52,16 @@@ public class PlatformTes
    @Test(groups = "Functional")
    public void testIsControlDown_mac()
    {
+     String toolkit = Toolkit.getDefaultToolkit().getClass().getName();
+     if ("sun.awt.X11.XToolkit".equals(toolkit))
+     {
+       /*
+        * this toolkit on the build server fails these tests,
+        * because it returns 2, not 4, for getMenuShortcutKeyMask
+        */
+       return;
+     }
      int clickCount = 1;
      boolean isPopupTrigger = false;
      int buttonNo = MouseEvent.BUTTON1;
      assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
              0, 0, clickCount, isPopupTrigger, buttonNo), mac));
  
 -    mods = Event.CTRL_MASK;
 +    mods = InputEvent.CTRL_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK;
      assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
              0, 0, clickCount, isPopupTrigger, buttonNo), mac));
  
 -    mods = Event.META_MASK;
 +    mods = InputEvent.META_DOWN_MASK | InputEvent.BUTTON1_DOWN_MASK;
      assertTrue(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
              0, 0, clickCount, isPopupTrigger, buttonNo), mac));
  
      assertFalse(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
              0, 0, clickCount, isPopupTrigger, buttonNo), mac));
  
 -    mods = Event.CTRL_MASK;
 +    mods = InputEvent.CTRL_DOWN_MASK;
      assertTrue(Platform.isControlDown(new MouseEvent(b, 0, 0L, mods, 0, 0,
              0, 0, clickCount, isPopupTrigger, buttonNo), mac));
  
 -    mods = Event.CTRL_MASK | Event.SHIFT_MASK | Event.ALT_MASK;
 +    mods = InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK
 +            | InputEvent.ALT_DOWN_MASK;
      clickCount = 2;
      buttonNo = 2;
      isPopupTrigger = true;