1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package complex.XUserInputInterception; 29 30 import com.sun.star.accessibility.AccessibleRole; 31 import com.sun.star.accessibility.XAccessible; 32 import com.sun.star.accessibility.XAccessibleComponent; 33 import com.sun.star.accessibility.XAccessibleContext; 34 import com.sun.star.awt.KeyEvent; 35 import com.sun.star.awt.MouseEvent; 36 import com.sun.star.awt.Point; 37 import com.sun.star.awt.Rectangle; 38 import com.sun.star.awt.XKeyHandler; 39 import com.sun.star.awt.XMouseClickHandler; 40 import com.sun.star.awt.XUserInputInterception; 41 import com.sun.star.awt.XWindow; 42 import com.sun.star.chart.XChartDocument; 43 import com.sun.star.frame.*; 44 import com.sun.star.lang.*; 45 import com.sun.star.lang.EventObject; 46 import com.sun.star.sheet.XSpreadsheetDocument; 47 import com.sun.star.text.XTextDocument; 48 import com.sun.star.uno.UnoRuntime; 49 import com.sun.star.uno.XInterface; 50 import com.sun.star.util.*; 51 import java.awt.Robot; 52 import java.awt.event.InputEvent; 53 54 import util.AccessibilityTools; 55 import util.SOfficeFactory; 56 57 // ---------- junit imports ----------------- 58 import org.junit.After; 59 import org.junit.AfterClass; 60 import org.junit.Before; 61 import org.junit.BeforeClass; 62 import org.junit.Test; 63 import org.openoffice.test.OfficeConnection; 64 import static org.junit.Assert.*; 65 // ------------------------------------------ 66 //----------------------------------------------- 67 /** 68 * This <CODE>ComplexTest</CODE> checks the interface 69 * <CODE>XUserInputInterception</CODE>. Therefore it creates a document, 70 * adds a mouse and a key listener onto the interface and fire the 71 * correspond events. If all listener works as expected the test resluts in 72 * <CODE>OK</CODE> status. 73 * @short Check the interface XUserInputIntercaption 74 * @descr checks is a simple way the interface XUserInputInteraction 75 */ 76 public class EventTest { 77 //------------------------------------------- 78 // some const 79 80 //------------------------------------------- 81 // member 82 83 /** points to the global uno service manager. */ 84 private XMultiServiceFactory m_xMSF = null; 85 86 /** indicates if the mousePressed event was called*/ 87 private boolean m_mousePressed = false; 88 /** indicates if the mouseReleased event was called*/ 89 private boolean m_mouseReleased = false; 90 91 /** indicates if the mousePressed event was called*/ 92 private boolean m_keyPressed = false; 93 /** indicates if the mouseReleased event was called*/ 94 private boolean m_keyReleased = false; 95 96 /** points to a global StarOffice factory */ 97 private SOfficeFactory m_SOF = null; 98 99 /** 100 * define the miliseconds to wait until a <CODE>EventTrigger</CODE> thread should 101 * be finished with its work 102 */ 103 final int m_threadWait = 3000; 104 105 //------------------------------------------- 106 // test environment 107 108 //------------------------------------------- 109 /** 110 * The test methods are: 111 * <ul> 112 * <li><CODE>checkTextDocument</CODE></LI> 113 * <li><CODE>checkCalcDocument</CODE></LI> 114 * <li><CODE>checkDrawDocument</CODE></LI> 115 * <li><CODE>checkImpressDocument</CODE></LI> 116 * <li><CODE>checkChartDocument</CODE></LI> 117 * <li><CODE>checkMathDocument</CODE></li> 118 * </ul> 119 * @short A function to tell the framework, 120 * which test functions are available. 121 * @return All test methods. 122 * @todo Think about selection of tests from outside ... 123 */ 124 // public String[] getTestMethodNames() { 125 // return new String[] 126 // { "checkTextDocument", 127 // "checkCalcDocument", 128 // "checkDrawDocument", 129 // "checkImpressDocument", 130 // "checkChartDocument", 131 // "checkMathDocument", 132 // }; 133 // } 134 135 //------------------------------------------- 136 /** 137 * creates the mebmer <CODE>m_xMSF</CODE> and <CODE>m_SOF</CODE> 138 * @short Create the environment for following tests. 139 * @descr create an empty test frame, where we can load 140 * different components inside. 141 */ 142 @Before public void before() { 143 // get uno service manager from global test environment 144 m_xMSF = getMSF(); 145 146 // create frame instance 147 try { 148 // get a soffice factory object 149 m_SOF = SOfficeFactory.getFactory(getMSF()); 150 151 } catch(java.lang.Throwable ex) { 152 fail("Could not create the XUserInputInterception instance."); 153 } 154 } 155 156 //------------------------------------------- 157 /** 158 * closes the document 159 * @short close the document. 160 * @param xDoc the document to close 161 */ 162 public void closeDoc(XInterface xDoc) { 163 XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xDoc); 164 try { 165 xClose.close(false); 166 } catch(com.sun.star.util.CloseVetoException exVeto) { 167 System.out.println("document couldn't be closed successfully."); 168 } 169 } 170 171 /** 172 * creates a text document and check the <CODE>XMouseClickHandler</CODE> and 173 * <CODE>XKeyHandler</CODE> 174 * @see com.sun.star.awt.XKeyHandler 175 * @see com.sun.star.awt.XMouseClickHandler 176 */ 177 @Test public void checkTextDocument(){ 178 179 XTextDocument xDoc = null; 180 181 try{ 182 xDoc = m_SOF.createTextDoc("WriterTest"); 183 } catch (com.sun.star.uno.Exception e){ 184 fail("Could not create a text document: " +e.toString()); 185 } 186 187 checkListener(xDoc); 188 189 closeDoc(xDoc); 190 } 191 192 /** 193 * creates an impress document and check the <CODE>XMouseClickHandler</CODE> and 194 * <CODE>XKeyHandler</CODE> 195 * @see com.sun.star.awt.XKeyHandler 196 * @see com.sun.star.awt.XMouseClickHandler 197 */ 198 @Test public void checkImpressDocument(){ 199 200 XComponent xDoc = null; 201 202 try{ 203 xDoc = m_SOF.createImpressDoc("ImpressTest"); 204 } catch (com.sun.star.uno.Exception e){ 205 fail("Could not create an impress document: " +e.toString()); 206 } 207 208 checkListener(xDoc); 209 210 closeDoc(xDoc); 211 } 212 213 /** 214 * creates a chart document and check the <CODE>XMouseClickHandler</CODE> and 215 * <CODE>XKeyHandler</CODE> 216 * @see com.sun.star.awt.XKeyHandler 217 * @see com.sun.star.awt.XMouseClickHandler 218 */ 219 // TODO! 220 // @Test public void checkChartDocument(){ 221 // 222 // XChartDocument xDoc = null; 223 // 224 // try{ 225 // xDoc = m_SOF.createChartDoc("ChartTest"); 226 // } catch (com.sun.star.uno.Exception e){ 227 // fail("Could not create a chart document: " +e.toString()); 228 // } 229 // 230 // checkListener(xDoc); 231 // 232 // closeDoc(xDoc); 233 // } 234 235 /** 236 * creates a math document and check the <CODE>XMouseClickHandler</CODE> and 237 * <CODE>XKeyHandler</CODE> 238 * @see com.sun.star.awt.XKeyHandler 239 * @see com.sun.star.awt.XMouseClickHandler 240 */ 241 @Test public void checkMathDocument(){ 242 243 XComponent xDoc = null; 244 245 try{ 246 xDoc = m_SOF.createMathDoc("MathTest"); 247 } catch (com.sun.star.uno.Exception e){ 248 fail("Could not create a math document: " +e.toString()); 249 } 250 251 checkListener(xDoc); 252 253 closeDoc(xDoc); 254 } 255 256 /** 257 * creates a draw document and check the <CODE>XMouseClickHandler</CODE> and 258 * <CODE>XKeyHandler</CODE> 259 * @see com.sun.star.awt.XKeyHandler 260 * @see com.sun.star.awt.XMouseClickHandler 261 */ 262 @Test public void checkDrawDocument(){ 263 264 XComponent xDoc = null; 265 266 try{ 267 xDoc = m_SOF.createDrawDoc("DrawTest"); 268 } catch (com.sun.star.uno.Exception e){ 269 fail("Could not create a draw document: " +e.toString()); 270 } 271 272 checkListener(xDoc); 273 274 closeDoc(xDoc); 275 } 276 277 /** 278 * creates a calc document and check the <CODE>XMouseClickHandler</CODE> and 279 * <CODE>XKeyHandler</CODE> 280 * @see com.sun.star.awt.XKeyHandler 281 * @see com.sun.star.awt.XMouseClickHandler 282 */ 283 @Test public void checkCalcDocument(){ 284 285 XSpreadsheetDocument xDoc = null; 286 287 try{ 288 xDoc = m_SOF.createCalcDoc("CalcTest"); 289 } catch (com.sun.star.uno.Exception e){ 290 fail("Could not create a calc document: " +e.toString()); 291 } 292 293 checkListener(xDoc); 294 closeDoc(xDoc); 295 } 296 297 /** 298 * This is the central test method. It is called by ceck[DOCTYPE]Document. It 299 * creates the <CODE>XUserInputInterception</CODE> from the document and call the 300 * <CODE>checkMouseListener</CODE> test and the <CODE>checkKeyListener</CODE> test 301 * @param xDoc the document to test 302 */ 303 private void checkListener(XInterface xDoc){ 304 305 XModel xModel = UnoRuntime.queryInterface(XModel.class, xDoc); 306 307 XUserInputInterception xUII = getUII(xModel); 308 309 checkMouseListener(xUII, xModel); 310 checkKeyListener(xUII, xModel); 311 } 312 313 /** 314 * Creates a <CODE>MyKeyHandler</CODE> and adds it to the 315 * <CODE>XUserInputInterception</CODE>. Then an <CODE>EventTrigger</CODE> thread 316 * was created and started. 317 * Has <CODE>OK</CODE> if the members <CODE>m_keyPressed</CODE> and 318 * <CODE>m_keyReleased</CODE> are <CODE>TRUE</CODE> 319 * @param xUII the XUserInputInterception 320 * @param xModel the XModel of a document 321 * @see EventTest.MyKeyHander 322 * @see EventTest.EventTrigger 323 */ 324 private void checkKeyListener(XUserInputInterception xUII, XModel xModel) { 325 m_keyPressed = false; 326 m_keyReleased = false; 327 328 MyKeyHandler keyListener = new MyKeyHandler(); 329 330 xUII.addKeyHandler(keyListener); 331 332 System.out.println("starting thread to check the key listener..."); 333 EventTrigger et = new EventTrigger(xModel, EventTriggerType.KEY_TEXT_INTO_DOC); 334 335 et.run(); 336 337 util.utils.shortWait(m_threadWait); 338 System.out.println("key listener thread should be finished."); 339 340 assertTrue("key event does not work!", m_keyPressed && m_keyReleased); 341 xUII.removeKeyHandler(keyListener); 342 343 } 344 345 /** 346 * Creates a <CODE>MyMouseClickHandler</CODE> and adds it to the 347 * <CODE>XUserInputInterception</CODE>. Then an <CODE>EventTrigger</CODE> thread 348 * was created and started. 349 * Has <CODE>OK</CODE> if the members <CODE>m_mousePressed</CODE> and 350 * <CODE>m_mouseReleased</CODE> are <CODE>TRUE</CODE> 351 * @param xUII the XUserInputInterception 352 * @param xModel the XModel of a document 353 * @see EventTest.MyMouseClickHander 354 * @see EventTest.EventTrigger 355 */ 356 357 private void checkMouseListener(XUserInputInterception xUII, XModel xModel) { 358 359 m_mousePressed = false; 360 m_mouseReleased = false; 361 362 MyMouseClickHandler mouseListener = new MyMouseClickHandler(); 363 364 xUII.addMouseClickHandler(mouseListener); 365 366 System.out.println("starting thread to check the mouse listener..."); 367 EventTrigger et = new EventTrigger(xModel, EventTriggerType.MOUSE_KLICK_INTO_DOC); 368 369 et.run(); 370 371 util.utils.shortWait(m_threadWait); 372 System.out.println("mouse listener thread should be finished."); 373 374 assertTrue("mouse event does not work!", m_mousePressed && m_mouseReleased); 375 xUII.removeMouseClickHandler(mouseListener); 376 } 377 378 /** 379 * returns the <CODE>XUserInputInterception</CODE> from the <CODE>XMdoel</CODE> 380 * @param xModel the XModel of a document 381 * @return the <CODE>XUserInputInterception</CODE> of the document 382 */ 383 private XUserInputInterception getUII(XModel xModel){ 384 385 XController xController = xModel.getCurrentController(); 386 387 XUserInputInterception xUII = UnoRuntime.queryInterface(XUserInputInterception.class, xController); 388 if (xUII == null) { 389 fail("could not get XUserInputInterception from XContoller"); 390 } 391 return xUII; 392 } 393 394 /** 395 * Listener which added and its method must be called 396 * on <code>keyPressed</code> and <code>keyReleased</code> call. 397 */ 398 public class MyKeyHandler implements XKeyHandler { 399 /** 400 * This event sets the member <code>m_keyPressed</coed> to 401 * <code>true</code> 402 * @param oEvent The key event informs about the pressed key. 403 * @return returns <CODE>TRUE</CODE> in erery case 404 */ 405 public boolean keyPressed( KeyEvent oEvent ){ 406 System.out.println("XKeyHandler: keyPressed-Event"); 407 m_keyPressed = true; 408 return true; 409 } 410 /** 411 * This event sets the member <code>m_keyReleased</coed> to 412 * <code>true</code> 413 * @param oEvent The key event informs about the pressed key. 414 * @return returns <CODE>TRUE</CODE> in erery case 415 */ 416 public boolean keyReleased( KeyEvent oEvent ){ 417 System.out.println("XKeyHandler: keyReleased-Event"); 418 m_keyReleased = true; 419 return true; 420 } 421 /** 422 * This event does nothing usefull 423 * @param oEvent refers to the object that fired the event. 424 */ 425 public void disposing( EventObject oEvent ){ 426 System.out.println("XKeyHandler: disposing-Event"); 427 } 428 } 429 430 /** 431 * Listener which added and its method must be called 432 * on <code>mousePressed</code> and <code>mouseReleased</code> call. 433 */ 434 public class MyMouseClickHandler implements XMouseClickHandler { 435 /** 436 * This event sets the member <code>m_mousePressed</coed> to 437 * <code>true</code> 438 * @param oEvent The mouse event informs about the kind of mouse event. 439 * @return returns <CODE>TRUE</CODE> in erery case 440 */ 441 public boolean mousePressed( MouseEvent oEvent ){ 442 System.out.println("XMouseClickHandler: mousePressed-Event"); 443 m_mousePressed = true; 444 return true; 445 } 446 /** 447 * This event sets the member <code>m_mouseReleased</coed> to 448 * <code>true</code> 449 * @param oEvent The mouse event informs about the kind of mouse event. 450 * @return returns <CODE>TRUE</CODE> in erery case 451 */ 452 public boolean mouseReleased( MouseEvent oEvent ){ 453 System.out.println("XMouseClickHandler: mouseReleased-Event"); 454 m_mouseReleased = true; 455 return true; 456 } 457 /** 458 * This event does nothing usefull 459 * @param oEvent refers to the object that fired the event. 460 */ 461 public void disposing( EventObject oEvent ){ 462 System.out.println("XMouseClickHandler: disposing-Event"); 463 } 464 }; 465 466 /** 467 * To check the events this class is a thread which click a mouse button and 468 * press a key with the <CODE>Robot</CODE> class 469 * @see java.awt.Robot 470 */ 471 private class EventTrigger extends Thread{ 472 473 /** 474 * represents a <CODE>AccessibilityTools</CODE> 475 */ 476 private final AccessibilityTools at = new AccessibilityTools(); 477 /** 478 * represents an <CODE>EventType</CODE> 479 * @see EventTest.EventTriggerType 480 */ 481 private int eventType = 0; 482 /** 483 * represents a <CODE>XModel</CODE> of a document 484 */ 485 private XModel xModel = null; 486 487 /** 488 * Creates an instacne of this class. The parameter <CODE>eType</CODE> represents 489 * the kind of event wich will be triggert at <CODE>run()</CODE> 490 * @param model the model of a document 491 * @param eType the kind of event which should be trigger 492 */ 493 public EventTrigger(XModel model, int eType) 494 { 495 this.xModel = model; 496 this.eventType = eType; 497 } 498 499 /** 500 * Triggers the event wich is represented by <CODE>eventType</CODE> 501 * The scenarios are: 502 * <ul> 503 * <li>EventTest.EventTriggerType.MOUSE_KLICK_INTO_DOC 504 * which calls 505 * <li><CODE>clickIntoDoc</CODE></LI> 506 * </LI> 507 * <li>EventTest.EventTriggerType.KEY_TEXT_INTO_DOC 508 * which calls 509 * <li><CODE>clickIntodoc</CODE></LI> 510 * <li><CODE>keyIntoDoc</CODE></LI> 511 * </LI> 512 * </UL> 513 */ 514 public void run(){ 515 516 switch (this.eventType){ 517 518 case EventTriggerType.MOUSE_KLICK_INTO_DOC: 519 clickIntoDoc(); 520 break; 521 case EventTriggerType.KEY_TEXT_INTO_DOC: 522 clickIntoDoc(); 523 keyIntoDoc(); 524 break; 525 526 } 527 } 528 /** 529 * This method cklicks into the middel of a document. It uses Accessibility 530 * to get the document and query for its position and its range to calculate 531 * the middle. This values was used for <CODE>Robot</CODE> Class. This 532 * Robot class is able to move the mouse and to cklick a mouse button 533 * @see java.awt.Robot 534 */ 535 private void clickIntoDoc(){ 536 try{ 537 // get the position and the range of a scroll bar 538 539 XWindow xWindow = at.getCurrentWindow( 540 getMSF(), 541 xModel); 542 543 XAccessible xRoot = at.getAccessibleObject(xWindow); 544 545 546 547 XAccessibleContext xPanel = at.getAccessibleObjectForRole(xRoot, AccessibleRole.PANEL); 548 XAccessibleComponent xPanelCont = UnoRuntime.queryInterface(XAccessibleComponent.class, xPanel); 549 550 // the position of the panel 551 Point point = xPanelCont.getLocationOnScreen(); 552 553 // the range of the panel 554 Rectangle rect = xPanelCont.getBounds(); 555 556 try { 557 Robot rob = new Robot(); 558 int x = point.X + (rect.Width / 2); 559 int y = point.Y + (rect.Height / 2); 560 System.out.println("try to klick into the middle of the document"); 561 rob.mouseMove(x, y); 562 rob.mousePress(InputEvent.BUTTON1_MASK); 563 rob.mouseRelease(InputEvent.BUTTON1_MASK); 564 } catch (java.awt.AWTException e) { 565 System.out.println("couldn't press mouse button"); 566 } 567 } catch (java.lang.Exception e){ 568 System.out.println("could not click into the scroll bar: " + e.toString()); 569 } 570 } 571 572 /** 573 * This method press the "A" key. Therefore it uses the <CODE>Robot</CODE> 574 * class. 575 * @see java.awt.Robot 576 */ 577 private void keyIntoDoc(){ 578 try { 579 Robot rob = new Robot(); 580 System.out.println("try to press 'A'"); 581 rob.keyPress(java.awt.event.KeyEvent.VK_A); 582 rob.keyRelease(java.awt.event.KeyEvent.VK_A); 583 } catch (java.awt.AWTException e) { 584 System.out.println("couldn't press key"); 585 } 586 587 } 588 } 589 590 /** This interface represents all possible actions which could be used 591 * in the <CODE>EventTrigger</CODE> class. 592 * @see EventTest.EventTrigger 593 */ 594 private interface EventTriggerType{ 595 596 /** klick the mouse into the scroll bar*/ 597 final public static int MOUSE_KLICK_INTO_DOC = 1; 598 599 /** write some text into a spread sheet*/ 600 final public static int KEY_TEXT_INTO_DOC = 2; 601 } 602 603 604 605 606 private XMultiServiceFactory getMSF() 607 { 608 final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); 609 return xMSF1; 610 } 611 612 // setup and close connections 613 @BeforeClass public static void setUpConnection() throws Exception { 614 System.out.println("setUpConnection()"); 615 connection.setUp(); 616 } 617 618 @AfterClass public static void tearDownConnection() 619 throws InterruptedException, com.sun.star.uno.Exception 620 { 621 System.out.println("tearDownConnection()"); 622 connection.tearDown(); 623 } 624 625 private static final OfficeConnection connection = new OfficeConnection(); 626 627 }