1 /*
   2  * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25   @test
  26   @key headful
  27   @bug 6497109 6734341
  28   @summary TextArea must have selection expanding, and also be autoscrolled, if mouse is dragged from inside.
  29   @library ../../regtesthelpers
  30   @build Util
  31   @author Konstantin Voloshin: area=TextArea
  32   @run main SelectionAutoscrollTest
  33 */
  34 
  35 /**
  36  * SelectionAutoscrollTest.java
  37  *
  38  * summary: TextArea should be auto-scrolled and text should be selected to
  39  *   the end, if mouse is dragged from inside box-for-text to outside it, and
  40  *   is hold pressed there.
  41  */
  42 
  43 
  44 import java.awt.Frame;
  45 import java.awt.Panel;
  46 import java.awt.GridLayout;
  47 import java.awt.TextArea;
  48 import java.awt.Point;
  49 import java.awt.Dimension;
  50 import java.awt.event.MouseEvent;
  51 import java.awt.Robot;
  52 import java.awt.Toolkit;
  53 import test.java.awt.regtesthelpers.Util;
  54 
  55 
  56 public class SelectionAutoscrollTest {
  57     TextArea textArea;
  58     Robot robot;
  59     final int desiredSelectionEnd = ('z'-'a'+1)*2;  // 52
  60     final static int SCROLL_DELAY = 10; // ms
  61 
  62     public static void main(String[] args) {
  63         SelectionAutoscrollTest selectionAutoscrollTest
  64                 = new SelectionAutoscrollTest();
  65         selectionAutoscrollTest.createObjects();
  66         selectionAutoscrollTest.manipulateMouse();
  67         selectionAutoscrollTest.checkResults();
  68     }
  69 
  70     void createObjects() {
  71         textArea = new TextArea( bigString() );
  72         robot = Util.createRobot();
  73 
  74         Panel panel = new Panel();
  75         panel.setLayout( new GridLayout(3,3) );
  76 
  77         for( int y=0; y<3; ++y ) {
  78             for( int x=0; x<3; ++x ) {
  79                 if( x==1 && y==1 ) {
  80                     panel.add( textArea );
  81                 } else {
  82                     panel.add( new Panel() );
  83                 }
  84             }
  85         }
  86 
  87         Frame frame = new Frame( "TextArea cursor icon test" );
  88         frame.setSize( 300, 300 );
  89         frame.add( panel );
  90         frame.setVisible( true );
  91     }
  92 
  93     static String bigString() {
  94         String s = "";
  95         for( char c='a'; c<='z'; ++c ) {
  96             s += c+"\n";
  97         }
  98         return s;
  99     }
 100 
 101     void manipulateMouse() {
 102         moveMouseToCenterOfTextArea();
 103         Util.waitForIdle( robot );
 104 
 105         robot.mousePress( MouseEvent.BUTTON1_MASK );
 106         Util.waitForIdle( robot );
 107 
 108         for( int tremble=0; tremble < 10; ++tremble ) {
 109             // Mouse is moved repeatedly here (with conservatively chosen
 110             // ammount of times), to give some time/chance for TextArea to
 111             // autoscroll and for text-selection to expand to the end.
 112             // This is because:
 113             // - On Windows,
 114             //   autoscrolling and selection-expansion happens only once per
 115             //   each mouse-dragged event received, and only for some ammount,
 116             //   not to the end. So, we have to drag mouse repeatedly.
 117             // - on X,
 118             //   only 1 mouse-dragged event is required for autoscrolling/
 119             //   selection-expanding to commence. Once commenced, it will
 120             //   continue to the end of text (provided that mouse-button is
 121             //   hold pressed), but it may take hardly predictable ammount of
 122             //   time. However, repeatedly dragging mouse seems perfectly help
 123             //   here, instead of having to use 'Thread.sleep( ??? )'.
 124             // Note: It's required here to move mouse 2 times to receive the
 125             //   1-st drag-event. After 1-st movement, only mouse-exited event
 126             //   will be generated. If mouse was released after first movement
 127             //   here, we would even get mouse-clicked event (at least for now,
 128             //   and this is probably a bug). But, starting with 2nd iteration,
 129             //   all events received will be mouse-dragged events.
 130 
 131             moveMouseBelowTextArea( tremble );
 132             Util.waitForIdle( robot );
 133             // it is needed to add some small delay on Gnome
 134             waitUntilScrollIsPerformed(robot);
 135         }
 136 
 137         robot.mouseRelease( MouseEvent.BUTTON1_MASK );
 138         Util.waitForIdle( robot );
 139     }
 140 
 141     void moveMouseToCenterOfTextArea() {
 142         Dimension d = textArea.getSize();
 143         Point l = textArea.getLocationOnScreen();
 144         Util.mouseMove(robot, l, new Point((int) (l.x + d.width * .5),
 145                 (int) (l.y + d.height * .5)));
 146     }
 147 
 148     void moveMouseBelowTextArea(int tremble) {
 149         Dimension d = textArea.getSize();
 150         Point l = textArea.getLocationOnScreen();
 151         Point p1;
 152         if (tremble == 0) {
 153             p1 = new Point((int) (l.x + d.width * .5),
 154                     (int) (l.y + d.height * 0.5));
 155         } else {
 156             p1 = new Point((int) (l.x + d.width * .5),
 157                     (int) (l.y + d.height * 1.5));
 158         }
 159         Point p2 = new Point((int) (l.x + d.width * .5),
 160                 (int) (l.y + d.height * 1.5) + 15);
 161         if (tremble % 2 == 0) {
 162             Util.mouseMove(robot, p1, p2);
 163         } else {
 164             Util.mouseMove(robot, p2, p1);
 165         }
 166     }
 167 
 168     void waitUntilScrollIsPerformed(Robot robot) {
 169         try {
 170             Thread.sleep( SCROLL_DELAY );
 171         }
 172         catch( Exception e ) {
 173             throw new RuntimeException( e );
 174         }
 175     }
 176 
 177     void checkResults() {
 178         final int currentSelectionEnd = textArea.getSelectionEnd();
 179         System.out.println(
 180                 "TEST: Selection range after test is: ( "
 181                 + textArea.getSelectionStart() + ", "
 182                 + currentSelectionEnd + " )"
 183         );
 184 
 185         boolean resultOk = ( currentSelectionEnd == desiredSelectionEnd );
 186         String desiredSelectionEndString = "" + desiredSelectionEnd;
 187 
 188         // On Windows, last empty line is surprisingly not selected.
 189         // Even if it's a bug, it's not for this test.
 190         // So, we have 2 acceptable results in this case.
 191         String toolkitName = Toolkit.getDefaultToolkit().getClass().getName();
 192         if( toolkitName.equals("sun.awt.windows.WToolkit") ) {
 193             final int desiredSelectionEnd2 = desiredSelectionEnd-1;  // 51
 194             resultOk |= ( currentSelectionEnd == desiredSelectionEnd2 );
 195             desiredSelectionEndString += " or " + desiredSelectionEnd2;
 196         }
 197 
 198         if( resultOk ) {
 199             System.out.println(
 200                 "TEST: passed: Text is selected to the end"
 201                 + " (expected selection range end is "
 202                 + desiredSelectionEndString + ")."
 203             );
 204         } else {
 205             System.out.println(
 206                 "TEST: FAILED: Text should be selected to the end"
 207                 + " (selection range end should be "
 208                 + desiredSelectionEndString + ")."
 209             );
 210             throw new RuntimeException(
 211                 "TEST: FAILED: Text should be selected to the end, but it is not."
 212             );
 213         }
 214     }
 215 }