[
  {
    "path": ".gitignore",
    "content": "venv/\n.tox/\n\n*.pyc\n__pycache__/\n\ninstance/\n\n.pytest_cache/\n.coverage\nhtmlcov/\n\ndist/\nbuild/\n*.egg-info/\n\nPipfile.lock"
  },
  {
    "path": "AUTHORS.txt",
    "content": "Here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --\npeople who have submitted patches, reported bugs, added translations, helped\nanswer newbie questions, and generally made PyAutoGUI that much better:\n\nAbhijeet Singh https://github.com/cseas\nAl Sweigart https://github.com/asweigart/\nAlexandr Orlov https://github.com/hey-sancho\nalphaCTzo7G https://github.com/alphaCTzo7G\nAndrew Selzer https://github.com/afs2015\nAndy Dam https://github.com/andydam\nAnwar A. Ruff https://github.com/aaruff\nAri Lacenski https://github.com/tensory\nAshok Fernandez https://github.com/ashokfernandez/\nBrian Redmond https://github.com/bredmond\nChristopher Valles https://github.com/christophervalles\nclach04 https://github.com/clach04\nClayton A. Alves https://github.com/claytonaalves\ncryzed https://github.com/cryzed\nDaniel D. Beck https://github.com/ddbeck\ndanielboone https://github.com/danielboone\nDavee Nguyen https://github.com/daveenguyen\nDavid Siah https://github.com/dsiah\nDenilson Figueiredo de Sá https://github.com/denilsonsa\nDominik Schmelz https://github.com/DIDoS\ndragon778 https://github.com/dragon788\nDuxxi https://github.com/sjhhh3\nEric https://github.com/bleuetnoir\nErtugrulSener https://github.com/ErtugrulSener\nFornost461 https://github.com/Fornost461\nHarrison https://github.com/Sentdex\nHugo Salvador https://github.com/hugoesb\ni-need-to-tell-you-something https://github.com/i-need-to-tell-you-something\njakibaki https://github.com/\nJeff Triplett https://github.com/jefftriplett\nJeremy R. Gray https://github.com/jeremygray\nJeromie Kirchoff https://github.com/JayRizzo\nJoel Gomes da Silva https://github.com/joelgomes1994\njohnborgmann https://github.com/johnborgmann\nJon Winsley https://github.com/glitchassassin\njorg-j https://github.com/jorg-j\nJose Riha https://github.com/jose1711\nJulien Schueller https://github.com/jschueller\nKorons https://github.com/Korons\nlb1a https://github.com/lb1a\nLesmana Zimmer https://github.com/lesmana\nliberme https://github.com/liberme\nMatt Olsen https://github.com/digwanderlust\nmvbentes https://github.com/mvbentes\nnexcvon https://github.com/nexcvon\nOleg Höfling https://github.com/hoefling\noptroot https://github.com/optroot\npgkos https://github.com/pgkos\nqiujieqiong https://github.com/qiujieqiong\nRicardo Amendoeira https://github.com/ric2b\nScott Noyes https://github.com/snoyes\nSergio Encarnación https://github.com/Sergioenc28\nsneakypete81 https://github.com/sneakypete81\nStefan Hoelzl https://github.com/stefanhoelzl\nStephen Ellis https://github.com/saellis\nSteven Shave https://github.com/stevenshave\nTim Gates https://github.com/timgates42\nTimothy Crory https://github.com/tcrory\nundefx https://github.com/undefx\nVélmer Oliveira https://github.com/velmer\nValdemar B. Petersen https://github.com/ValdemarBirkegaardPetersen\nYoshiaki Ono https://github.com/fx-kirin\nStefan Hoelzl https://github.com/stefanhoelzl\nZander Møysal https://github.com/Zandertaiko"
  },
  {
    "path": "CHANGES.txt",
    "content": "v0.9.53, 2021/07/07 -- Fixed a compatibility issue with the pystray module.\nv0.9.52, 2020/10/06 -- Fixed hotkey() to work with PAUSE.\nv0.9.51, 2020/10/04 -- Added the hold() context manager, several bug fixes for mac mouse functions.\nv0.9.50, 2020/04/01 -- The 0.9.49 changes were incredibly buggy and have been reverted.\nv0.9.49, 2020/03/27 -- Migrated from Quartz to Rubicon\nv0.9.46, 2019/07/09 -- Added mouseinfo module.\nv0.9.45, 2019/06/18 -- Added left-click, made mouse buttons more explicit and fixed it so that the right mouse button is 2 and middle mouse button is 3. Added failsafe points in all corners. Added screenshot logging. Fixed _autoPause().\nv0.9.44, 2019/05/30 -- Adding ability to pass 4-integer box tuples to click() and other functions.\nv0.9.43, 2019/05/27 -- Renamed getFocusedWindow to getActiveWindow to keep it up to date with pygetwindow.\nv0.9.40, 2018/12/26 -- Created FAILSAFE_POINT constant instead of hard coding (0, 0), add move(), drag(), write() names. Adding PyGetWindow.\nv0.9.39, 2018/09/05 -- Added tox and fixed setup.py for Python 2 compatibility.\nv0.9.38, 2018/07/21 -- Removing non-ascii characters from readme because it causes failures when displaying on Windows.\nv0.9.37, 2018/07/18 -- Updating setup.py\nv0.9.36, 2017/04/20 -- Fixed Windows XP problem with the DPI scaling API call.\nv0.9.35, 2017/03/19 -- Fixed Windows DPI scaling issue.\nv0.9.34, 2017/03/18 -- Fixed several bugs after the Sentry OSS sprint, including Windows permission errors.\nv0.9.33, 2016/01/08 -- Fixed bug with missing keyword arg in hotkey(). Thanks jmcduffie!\nv0.9.32, 2015/10/28 -- Updated setup.py to pull info from source\nv0.9.31, 2015/09/06 -- Incorporated many fixes and changes from Denilson Figueiredo de Sá. Thanks!\nv0.9.30, 2015/05/06 -- Fixed issue #12 (size() on Mac Retina displays)\nv0.9.29, 2015/05/05 -- Fixed issue #29 (press('enter') doesn't work on Linux)\nv0.9.28, 2015/05/05 -- Fixed a small bug wheel scroll on OS X.\nv0.9.27, 2015/05/02 -- Fixed a bug with Linux's button parameter.\nv0.9.26, 2015/02/02 -- Added 'super' key to Windows and the presses keyword argument to press().\nv0.9.25, 2015/01/27 -- Fixed dragTo() bug on OS X\nv0.9.24, 2015/01/07 -- Added -x silent option to os x screencapture command.\nv0.9.23, 2015/01/06 -- Now allowing lists in addition to tuples for XY coordinate arguments.\nv0.9.22, 2015/01/06 -- Added \"pause\" keyword argument to functions to override PAUSE setting for specific calls.\nv0.9.21, 2014/12/15 -- Added keyword arguments to functions, improved unit tests.\nv0.9.20, 2014/10/11 -- Fixed parameter order bug on Linux.\nv0.9.19, 2014/09/24 -- Set fail-safe and pause features to be enabled by default.\nv0.9.18, 2014/09/16 -- Moved screenshot features to a separate \"PyScreeze\" module.\nv0.9.17, 2014/09/15 -- Added pixel() and pixelMatchesColor() functions.\nv0.9.16, 2014/09/15 -- Added locateCenterOnScreen() function.\nv0.9.15, 2014/09/12 -- Added fail-safe feature.\nv0.9.14, 2014/09/11 -- Fixed bug with locateOnScreen().\nv0.9.13, 2014/09/11 -- Fixed OS X scrolling bug. Added screenshot features.\nv0.9.12, 2014/09/10 -- Fixed import bugs.\nv0.9.11, 2014/09/08 -- Fixed bug where None was being passed to platform-specific mouse functions.\nv0.9.10, 2014/09/08 -- Fixing the previous bug, for real this time.\nv0.9.9, 2014/09/03 -- Bug fix with the mouseUp and mouseDown functions due to rearranging the parameters.\nv0.9.8, 2014/09/03 -- Moved tweening functions into pyautogui instead of separate pyautogui.tweens\nv0.9.7, 2014/09/03 -- Fixing a bug where single-character strings sent to press() were dropped. Added a unit test for this bug.\nv0.9.6, 2014/09/03 -- Added PyMsgBox & PyTweening as dependencies.\nv0.9.5, 2014/08/28 -- Made parameter order for mouseDown() and mouseUp() consistent with click().\nv0.9.4, 2014/08/28 -- Fixed uppercase bug.\nv0.9.3, 2014/08/21 -- Added ability to pass a list to press().\nv0.9.2, 2014/08/19 -- Added complete set of tween functions.\nv0.9.0, 2014/07/28 -- Initial release."
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2014, Al Sweigart\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the PyAutoGUI nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include *.md\ninclude LICENSE.txt\nrecursive-include docs *.bat\nrecursive-include docs *.py\nrecursive-include docs *.rst\nrecursive-include docs Makefile\nrecursive-include pyautogui *.py\nrecursive-include tests *.py\n"
  },
  {
    "path": "Pipfile",
    "content": "[[source]]\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\nname = \"pypi\"\n\n[packages]\npyautogui = {editable = true, path = \".\"}\n\n[dev-packages]\n\n[requires]\npython_version = \"3.11\"\n"
  },
  {
    "path": "README.md",
    "content": "PyAutoGUI\n=========\n\nPyAutoGUI is a  cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.\n\n`pip install pyautogui`\n\nFull documentation available at https://pyautogui.readthedocs.org\n\nSimplified Chinese documentation available at https://github.com/asweigart/pyautogui/blob/master/docs/simplified-chinese.ipynb\n\nSource code available at https://github.com/asweigart/pyautogui\n\nIf you need help installing Python, visit https://installpython3.com/\n\nDependencies\n============\n\nPyAutoGUI supports Python 2 and 3. If you are installing PyAutoGUI from PyPI using pip:\n\nWindows has no dependencies. The Win32 extensions do not need to be installed.\n\nmacOS needs the pyobjc-core and pyobjc module installed (in that order).\n\nLinux needs the python3-xlib (or python-xlib for Python 2) module installed.\n\nPillow needs to be installed, and on Linux you may need to install additional libraries to make sure Pillow's PNG/JPEG works correctly. See:\n\n    https://stackoverflow.com/questions/7648200/pip-install-pil-e-tickets-1-no-jpeg-png-support\n\n    http://ubuntuforums.org/showthread.php?t=1751455\n\nIf you want to do development and contribute to PyAutoGUI, you will need to install these modules from PyPI:\n\n* pyscreeze\n* pymsgbox\n* pytweening\n\nExample Usage\n=============\n\nKeyboard and Mouse Control\n--------------------------\n\nThe x, y coordinates used by PyAutoGUI has the 0, 0 origin coordinates in the top left corner of the screen. The x coordinates increase going to the right (just as in mathematics) but the y coordinates increase going down (the opposite of mathematics). On a screen that is 1920 x 1080 pixels in size, coordinates 0, 0 are for the top left while 1919, 1079 is for the bottom right.\n\nCurrently, PyAutoGUI only works on the primary monitor. PyAutoGUI isn't reliable for the screen of a second monitor (the mouse functions may or may not work on multi-monitor setups depending on your operating system and version).\n\nAll keyboard presses done by PyAutoGUI are sent to the window that currently has focus, as if you had pressed the physical keyboard key.\n\n```python\n    >>> import pyautogui\n    >>> screenWidth, screenHeight = pyautogui.size() # Returns two integers, the width and height of the screen. (The primary monitor, in multi-monitor setups.)\n    >>> currentMouseX, currentMouseY = pyautogui.position() # Returns two integers, the x and y of the mouse cursor's current position.\n    >>> pyautogui.moveTo(100, 150) # Move the mouse to the x, y coordinates 100, 150.\n    >>> pyautogui.click() # Click the mouse at its current location.\n    >>> pyautogui.click(200, 220) # Click the mouse at the x, y coordinates 200, 220.\n    >>> pyautogui.move(None, 10)  # Move mouse 10 pixels down, that is, move the mouse relative to its current position.\n    >>> pyautogui.doubleClick() # Double click the mouse at the\n    >>> pyautogui.moveTo(500, 500, duration=2, tween=pyautogui.easeInOutQuad) # Use tweening/easing function to move mouse over 2 seconds.\n    >>> pyautogui.write('Hello world!', interval=0.25)  # Type with quarter-second pause in between each key.\n    >>> pyautogui.press('esc') # Simulate pressing the Escape key.\n    >>> pyautogui.keyDown('shift')\n    >>> pyautogui.write(['left', 'left', 'left', 'left', 'left', 'left'])\n    >>> pyautogui.keyUp('shift')\n    >>> pyautogui.hotkey('ctrl', 'c')\n```\n\nDisplay Message Boxes\n---------------------\n```python\n    >>> import pyautogui\n    >>> pyautogui.alert('This is an alert box.')\n    'OK'\n    >>> pyautogui.confirm('Shall I proceed?')\n    'Cancel'\n    >>> pyautogui.confirm('Enter option.', buttons=['A', 'B', 'C'])\n    'B'\n    >>> pyautogui.prompt('What is your name?')\n    'Al'\n    >>> pyautogui.password('Enter password (text will be hidden)')\n    'swordfish'\n```\n\nScreenshot Functions\n--------------------\n\n(PyAutoGUI uses Pillow for image-related features.)\n```python\n    >>> import pyautogui\n    >>> im1 = pyautogui.screenshot()\n    >>> im1.save('my_screenshot.png')\n    >>> im2 = pyautogui.screenshot('my_screenshot2.png')\n```\nYou can also locate where an image is on the screen:\n```python\n    >>> import pyautogui\n    >>> button7location = pyautogui.locateOnScreen('button.png') # returns (left, top, width, height) of matching region\n    >>> button7location\n    (1416, 562, 50, 41)\n    >>> buttonx, buttony = pyautogui.center(button7location)\n    >>> buttonx, buttony\n    (1441, 582)\n    >>> pyautogui.click(buttonx, buttony)  # clicks the center of where the button was found\n```\nThe locateCenterOnScreen() function returns the center of this match region:\n```python\n    >>> import pyautogui\n    >>> buttonx, buttony = pyautogui.locateCenterOnScreen('button.png') # returns (x, y) of matching region\n    >>> buttonx, buttony\n    (1441, 582)\n    >>> pyautogui.click(buttonx, buttony)  # clicks the center of where the button was found\n```\n\nHow Does PyAutoGUI Work?\n========================\n\nThe three major operating systems (Windows, macOS, and Linux) each have different ways to programmatically control the mouse and keyboard. This can often involve confusing, obscure, and deeply technical details. The job of PyAutoGUI is to hide all of this complexity behind a simple API.\n\n* On Windows, PyAutoGUI accesses the Windows API (also called the WinAPI or win32 API) through the built-in `ctypes` module. The `nicewin` module at https://github.com/asweigart/nicewin provides a demonstration for how Windows API calls can be made through Python.\n\n* On macOS, PyAutoGUI uses the `rubicon-objc` module to access the Cocoa API.\n\n* On Linux, PyAutoGUI uses the `Xlib` module to access the X11 or X Window System.\n\n\nSupport\n-------\n\nIf you find this project helpful and would like to support its development, [consider donating to its creator on Patreon](https://www.patreon.com/AlSweigart).\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = _build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/PyAutoGUI.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/PyAutoGUI.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/PyAutoGUI\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyAutoGUI\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Configuration file for the Sphinx documentation builder.\n#\n# This file does only contain a selection of the most common options. For a\n# full list see the documentation:\n# http://www.sphinx-doc.org/en/master/config\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\nimport os\nimport sys\nsys.path.insert(0, os.path.abspath('.'))\nsys.path.insert(0, os.path.abspath('../'))\n#sys.path.insert(0, os.path.abspath('../pyautogui'))\n\n\n# -- Project information -----------------------------------------------------\n\nproject = 'PyAutoGUI'\ncopyright = '2019, Al Sweigart'\nauthor = 'Al Sweigart'\n\n# The short X.Y version\nversion = ''\n# The full version, including alpha/beta/rc tags\nrelease = ''\n\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path .\nexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'sphinx_rtd_theme'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n#\n# The default sidebars (for documents that don't match any pattern) are\n# defined by theme itself.  Builtin themes are using these templates by\n# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',\n# 'searchbox.html']``.\n#\n# html_sidebars = {}\n\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'PyAutoGUIdoc'\n\n\n# -- Options for LaTeX output ------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    # 'papersize': 'letterpaper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    # 'pointsize': '10pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'PyAutoGUI.tex', 'PyAutoGUI Documentation',\n     'Al Sweigart', 'manual'),\n]\n\n\n# -- Options for manual page output ------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'pyautogui', 'PyAutoGUI Documentation',\n     [author], 1)\n]\n\n\n# -- Options for Texinfo output ----------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'PyAutoGUI', 'PyAutoGUI Documentation',\n     author, 'PyAutoGUI', 'One line description of project.',\n     'Miscellaneous'),\n]"
  },
  {
    "path": "docs/index.rst",
    "content": ".. PyAutoGUI documentation master file, created by\n   sphinx-quickstart on Sun Jul 20 12:59:43 2014.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to PyAutoGUI's documentation!\n=====================================\n\n\nPyAutoGUI lets your Python scripts control the mouse and keyboard to automate interactions with other applications. The API is designed to be simple. PyAutoGUI works on Windows, macOS, and Linux, and runs on Python 2 and 3.\n\nTo install with pip, run ``pip install pyautogui``. See the :doc:`install` page for more details.\n\nThe source code is available on: https://github.com/asweigart/pyautogui\n\nPyAutoGUI has several features:\n\n* Moving the mouse and clicking in the windows of other applications.\n* Sending keystrokes to applications (for example, to fill out forms).\n* Take screenshots, and given an image (for example, of a button or checkbox), and find it on the screen.\n* Locate an application's window, and move, resize, maximize, minimize, or close it (Windows-only, currently).\n* Display alert and message boxes.\n\nHere's `a YouTube video of a bot automatically playing the game Sushi Go Round <https://www.youtube.com/watch?v=lfk_T6VKhTE>`_. The bot watches the game's application window and searches for images of sushi orders. When it finds one, it clicks the ingredient buttons to make the sushi. It also clicks the phone in the game to order more ingredients as needed. The bot is completely autonomous and can finish all seven days of the game. This is the kind of automation that PyAutoGUI is capable of.\n\nExamples\n========\n\n.. code:: python\n\n    >>> import pyautogui\n\n    >>> screenWidth, screenHeight = pyautogui.size() # Get the size of the primary monitor.\n    >>> screenWidth, screenHeight\n    (2560, 1440)\n\n    >>> currentMouseX, currentMouseY = pyautogui.position() # Get the XY position of the mouse.\n    >>> currentMouseX, currentMouseY\n    (1314, 345)\n\n    >>> pyautogui.moveTo(100, 150) # Move the mouse to XY coordinates.\n\n    >>> pyautogui.click()          # Click the mouse.\n    >>> pyautogui.click(100, 200)  # Move the mouse to XY coordinates and click it.\n    >>> pyautogui.click('button.png') # Find where button.png appears on the screen and click it.\n\n    >>> pyautogui.move(400, 0)      # Move the mouse 400 pixels to the right of its current position.\n    >>> pyautogui.doubleClick()     # Double click the mouse.\n    >>> pyautogui.moveTo(500, 500, duration=2, tween=pyautogui.easeInOutQuad)  # Use tweening/easing function to move mouse over 2 seconds.\n\n    >>> pyautogui.write('Hello world!', interval=0.25)  # type with quarter-second pause in between each key\n    >>> pyautogui.press('esc')     # Press the Esc key. All key names are in pyautogui.KEY_NAMES\n\n    >>> with pyautogui.hold('shift'):  # Press the Shift key down and hold it.\n            pyautogui.press(['left', 'left', 'left', 'left'])  # Press the left arrow key 4 times.\n    >>> # Shift key is released automatically.\n\n    >>> pyautogui.hotkey('ctrl', 'c') # Press the Ctrl-C hotkey combination.\n\n    >>> pyautogui.alert('This is the message to display.') # Make an alert box appear and pause the program until OK is clicked.\n\nThis example drags the mouse in a square spiral shape in MS Paint (or any graphics drawing program):\n\n.. code:: python\n\n    >>> distance = 200\n    >>> while distance > 0:\n            pyautogui.drag(distance, 0, duration=0.5)   # move right\n            distance -= 5\n            pyautogui.drag(0, distance, duration=0.5)   # move down\n            pyautogui.drag(-distance, 0, duration=0.5)  # move left\n            distance -= 5\n            pyautogui.drag(0, -distance, duration=0.5)  # move up\n\n.. image:: square_spiral.png\n\nThe benefit of using PyAutoGUI, as opposed to a script that directly generates the image file, is that you can use the brush tools that MS Paint provides.\n\nFAQ: Frequently Asked Questions\n===============================\n\nSend questions to al@inventwithpython.com\n\n**Q: Can PyAutoGUI work on Android, iOS, or tablet/smartphone apps.**\n\nA: Unfortunately no. PyAutoGUI only runs on Windows, macOS, and Linux.\n\n**Q: Does PyAutoGUI work on multi-monitor setups.**\n\nA: No, right now PyAutoGUI only handles the primary monitor.\n\n**Q: Does PyAutoGUI do OCR?**\n\nA: No, but this is a feature that's on the roadmap.\n\n**Q: Can PyAutoGUI do keylogging, or detect if a key is currently pressed down?**\n\nA: No, PyAutoGUI cannot do this currently.\n\n\nFail-Safes\n==========\n\n.. image:: sorcerers_apprentice_brooms.png\n\nLike the enchanted brooms from the Sorcerer’s Apprentice programmed to keep filling (and then overfilling) the bath with water, a bug in your program could make it go out of control. It's hard to use the mouse to close a program if the mouse cursor is moving around on its own.\n\nAs a safety feature, a fail-safe feature is enabled by default. When a PyAutoGUI function is called, if the mouse is in any of the four corners of the primary monitor, they will raise a ``pyautogui.FailSafeException``. There is a one-tenth second delay after calling every PyAutoGUI functions to give the user time to slam the mouse into a corner to trigger the fail safe.\n\nYou can disable this failsafe by setting ``pyautogui.FAILSAFE = False``. **I HIGHLY RECOMMEND YOU DO NOT DISABLE THE FAILSAFE.**\n\nThe tenth-second delay is set by the ``pyautogui.PAUSE`` setting, which is ``0.1`` by default. You can change this value. There is also a ``pyautogui.DARWIN_CATCH_UP_TIME`` setting which adds an additional delay on macOS after keyboard and mouse events, since the operating system appears to need a delay after PyAutoGUI issues these events. It is set to ``0.01`` by default, adding an additional hundredth-second delay.\n\n\nContents:\n\n.. toctree::\n   :maxdepth: 2\n\n   install.rst\n   quickstart.rst\n   mouse.rst\n   keyboard.rst\n   msgbox.rst\n   screenshot.rst\n   tests.rst\n   roadmap.rst\n\n   source/modules.rst\n\nThis documentation is still a work in progress.\n\n\nIndices and tables\n==================\n\n* :ref:`genindex`\n* :ref:`modindex`\n* :ref:`search`\n\n"
  },
  {
    "path": "docs/install.rst",
    "content": ".. default-role:: code\n\n============\nInstallation\n============\n\nTo install PyAutoGUI, install the `pyautogui` package from PyPI by running `pip install pyautogui` (on Windows) or `pip3 install pyautogui` (on macOS and Linux). (On macOS and Linux, `pip` refers to Python 2's pip tool.)\n\nOS-specific instructions are below.\n\nWindows\n-------\n\nOn Windows, you can use the ``py.exe`` program to run the latest version of Python:\n\n    ``py -m pip install pyautogui``\n\nIf you have multiple versions of Python installed, you can select which one with a command line argument to ``py``. For example, for Python 3.8, run:\n\n    ``py -3.8 -m pip install pyautogui``\n\n(This is the same as running ``pip install pyautogui``.)\n\nmacOS\n-----\n\nOn macOS and Linux, you need to run ``python3``:\n\n    ``python3 -m pip install pyautogui``\n\nIf you are running El Capitan and have problems installing pyobjc try:\n\n    ``MACOSX_DEPLOYMENT_TARGET=10.11 pip install pyobjc``\n\nLinux\n-----\n\nOn macOS and Linux, you need to run ``python3``:\n\n    ``python3 -m pip install pyautogui``\n\nOn Linux, additionally you need to install the ``scrot`` application, as well as Tkinter:\n\n    ``sudo apt-get install scrot``\n\n    ``sudo apt-get install python3-tk``\n\n    ``sudo apt-get install python3-dev``\n\nPyAutoGUI install the modules it depends on, including PyTweening, PyScreeze, PyGetWindow, PymsgBox, and MouseInfo.\n"
  },
  {
    "path": "docs/keyboard.rst",
    "content": ".. default-role:: code\n\n==========================\nKeyboard Control Functions\n==========================\n\nThe write() Function\n========================\n\nThe primary keyboard function is ``write()``. This function will type the characters in the string that is passed. To add a delay interval in between pressing each character key, pass an int or float for the ``interval`` keyword argument.\n\nFor example:\n\n.. code:: python\n\n    >>> pyautogui.write('Hello world!')                 # prints out \"Hello world!\" instantly\n    >>> pyautogui.write('Hello world!', interval=0.25)  # prints out \"Hello world!\" with a quarter second delay after each character\n\nYou can only press single-character keys with ``write()``, so you can't press the Shift or F1 keys, for example.\n\nThe press(), keyDown(), and keyUp() Functions\n=============================================\n\nTo press these keys, call the ``press()`` function and pass it a string from the ``pyautogui.KEYBOARD_KEYS`` such as ``enter``, ``esc``, ``f1``. See `KEYBOARD_KEYS`_.\n\nFor example:\n\n.. code:: python\n\n    >>> pyautogui.press('enter')  # press the Enter key\n    >>> pyautogui.press('f1')     # press the F1 key\n    >>> pyautogui.press('left')   # press the left arrow key\n\nThe ``press()`` function is really just a wrapper for the ``keyDown()`` and ``keyUp()`` functions, which simulate pressing a key down and then releasing it up. These functions can be called by themselves. For example, to press the left arrow key three times while holding down the Shift key, call the following:\n\n.. code:: python\n\n    >>> pyautogui.keyDown('shift')  # hold down the shift key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.keyUp('shift')    # release the shift key\n\nTo press multiple keys similar to what ``write()`` does, pass a list of strings to ``press()``. For example:\n\n.. code:: python\n\n    >>> pyautogui.press(['left', 'left', 'left'])\n\nOr you can set how many presses `left`:\n\n.. code:: python\n\n    >>> pyautogui.press('left', presses=3)\n\nTo add a delay interval in between each press, pass an int or float for the ``interval`` keyword argument.\n\nThe hold() Context Manager\n==========================\n\nTo make holding a key convenient, the ``hold()`` function can be used as a context manager and passed a string from the ``pyautogui.KEYBOARD_KEYS`` such as ``shift``, ``ctrl``, ``alt``, and this key will be held for the duration of the ``with`` context block. See `KEYBOARD_KEYS`_.\n\n.. code:: python\n\n    >>> with pyautogui.hold('shift'):\n            pyautogui.press(['left', 'left', 'left'])\n\n. . .is equivalent to this code:\n\n.. code:: python\n\n    >>> pyautogui.keyDown('shift')  # hold down the shift key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.press('left')     # press the left arrow key\n    >>> pyautogui.keyUp('shift')    # release the shift key\n\nThe hotkey() Function\n=====================\n\nTo make pressing hotkeys or keyboard shortcuts convenient, the ``hotkey()`` can be passed several key strings which will be pressed down in order, and then released in reverse order. This code:\n\n.. code:: python\n\n    >>> pyautogui.hotkey('ctrl', 'shift', 'esc')\n\n. . .is equivalent to this code:\n\n.. code:: python\n\n    >>> pyautogui.keyDown('ctrl')\n    >>> pyautogui.keyDown('shift')\n    >>> pyautogui.keyDown('esc')\n    >>> pyautogui.keyUp('esc')\n    >>> pyautogui.keyUp('shift')\n    >>> pyautogui.keyUp('ctrl')\n\nTo add a delay interval in between each press, pass an int or float for the ``interval`` keyword argument.\n\nKEYBOARD_KEYS\n=============\n\nThe following are the valid strings to pass to the ``press()``, ``keyDown()``, ``keyUp()``, and ``hotkey()`` functions:\n\n.. code:: python\n\n    ['\\t', '\\n', '\\r', ' ', '!', '\"', '#', '$', '%', '&', \"'\", '(',\n    ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7',\n    '8', '9', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\', ']', '^', '_', '`',\n    'a', 'b', 'c', 'd', 'e','f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',\n    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',\n    'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace',\n    'browserback', 'browserfavorites', 'browserforward', 'browserhome',\n    'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear',\n    'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete',\n    'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'f1', 'f10',\n    'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20',\n    'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',\n    'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja',\n    'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail',\n    'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack',\n    'nonconvert', 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6',\n    'num7', 'num8', 'num9', 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn',\n    'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn',\n    'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator',\n    'shift', 'shiftleft', 'shiftright', 'sleep', 'space', 'stop', 'subtract', 'tab',\n    'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen',\n    'command', 'option', 'optionleft', 'optionright']\n\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset BUILDDIR=_build\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .\nset I18NSPHINXOPTS=%SPHINXOPTS% .\nif NOT \"%PAPER%\" == \"\" (\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\n)\n\nif \"%1\" == \"\" goto help\n\nif \"%1\" == \"help\" (\n\t:help\n\techo.Please use `make ^<target^>` where ^<target^> is one of\n\techo.  html       to make standalone HTML files\n\techo.  dirhtml    to make HTML files named index.html in directories\n\techo.  singlehtml to make a single large HTML file\n\techo.  pickle     to make pickle files\n\techo.  json       to make JSON files\n\techo.  htmlhelp   to make HTML files and a HTML help project\n\techo.  qthelp     to make HTML files and a qthelp project\n\techo.  devhelp    to make HTML files and a Devhelp project\n\techo.  epub       to make an epub\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\n\techo.  text       to make text files\n\techo.  man        to make manual pages\n\techo.  texinfo    to make Texinfo files\n\techo.  gettext    to make PO message catalogs\n\techo.  changes    to make an overview over all changed/added/deprecated items\n\techo.  xml        to make Docutils-native XML files\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\n\techo.  linkcheck  to check all external links for integrity\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\n\tgoto end\n)\n\nif \"%1\" == \"clean\" (\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\n\tdel /q /s %BUILDDIR%\\*\n\tgoto end\n)\n\n\n%SPHINXBUILD% 2> nul\nif errorlevel 9009 (\n\techo.\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\n\techo.installed, then set the SPHINXBUILD environment variable to point\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\n\techo.may add the Sphinx directory to PATH.\n\techo.\n\techo.If you don't have Sphinx installed, grab it from\n\techo.http://sphinx-doc.org/\n\texit /b 1\n)\n\nif \"%1\" == \"html\" (\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\n\tgoto end\n)\n\nif \"%1\" == \"dirhtml\" (\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\n\tgoto end\n)\n\nif \"%1\" == \"singlehtml\" (\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\n\tgoto end\n)\n\nif \"%1\" == \"pickle\" (\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can process the pickle files.\n\tgoto end\n)\n\nif \"%1\" == \"json\" (\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can process the JSON files.\n\tgoto end\n)\n\nif \"%1\" == \"htmlhelp\" (\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can run HTML Help Workshop with the ^\n.hhp project file in %BUILDDIR%/htmlhelp.\n\tgoto end\n)\n\nif \"%1\" == \"qthelp\" (\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\n.qhcp project file in %BUILDDIR%/qthelp, like this:\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\PyAutoGUI.qhcp\n\techo.To view the help file:\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\PyAutoGUI.ghc\n\tgoto end\n)\n\nif \"%1\" == \"devhelp\" (\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished.\n\tgoto end\n)\n\nif \"%1\" == \"epub\" (\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\n\tgoto end\n)\n\nif \"%1\" == \"latex\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"latexpdf\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tcd %BUILDDIR%/latex\n\tmake all-pdf\n\tcd %BUILDDIR%/..\n\techo.\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"latexpdfja\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tcd %BUILDDIR%/latex\n\tmake all-pdf-ja\n\tcd %BUILDDIR%/..\n\techo.\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"text\" (\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The text files are in %BUILDDIR%/text.\n\tgoto end\n)\n\nif \"%1\" == \"man\" (\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\n\tgoto end\n)\n\nif \"%1\" == \"texinfo\" (\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\n\tgoto end\n)\n\nif \"%1\" == \"gettext\" (\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\n\tgoto end\n)\n\nif \"%1\" == \"changes\" (\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.The overview file is in %BUILDDIR%/changes.\n\tgoto end\n)\n\nif \"%1\" == \"linkcheck\" (\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Link check complete; look for any errors in the above output ^\nor in %BUILDDIR%/linkcheck/output.txt.\n\tgoto end\n)\n\nif \"%1\" == \"doctest\" (\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Testing of doctests in the sources finished, look at the ^\nresults in %BUILDDIR%/doctest/output.txt.\n\tgoto end\n)\n\nif \"%1\" == \"xml\" (\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\n\tgoto end\n)\n\nif \"%1\" == \"pseudoxml\" (\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\n\tgoto end\n)\n\n:end\n"
  },
  {
    "path": "docs/mouse.rst",
    "content": ".. default-role:: code\n\n=======================\nMouse Control Functions\n=======================\n\nThe Screen and Mouse Position\n=============================\n\nLocations on your screen are referred to by X and Y Cartesian coordinates. The X coordinate starts at 0 on the left side and increases going right. Unlike in mathematics, the Y coordinate starts at 0 on the top and increases going down.\n\n.. code::\n\n    0,0       X increases -->\n    +---------------------------+\n    |                           | Y increases\n    |                           |     |\n    |   1920 x 1080 screen      |     |\n    |                           |     V\n    |                           |\n    |                           |\n    +---------------------------+ 1919, 1079\n\nThe pixel at the top-left corner is at coordinates 0, 0. If your screen's resolution is 1920 x 1080, the pixel in the lower right corner will be 1919, 1079 (since the coordinates begin at 0, not 1).\n\nThe screen resolution size is returned by the ``size()`` function as a tuple of two integers. The current X and Y coordinates of the mouse cursor are returned by the ``position()`` function.\n\nFor example:\n\n.. code:: python\n\n    >>> pyautogui.size()\n    (1920, 1080)\n    >>> pyautogui.position()\n    (187, 567)\n\nHere is a short Python 3 program that will constantly print out the position of the mouse cursor:\n\n.. code:: python\n\n    #! python3\n    import pyautogui, sys\n    print('Press Ctrl-C to quit.')\n    try:\n        while True:\n            x, y = pyautogui.position()\n            positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)\n            print(positionStr, end='')\n            print('\\b' * len(positionStr), end='', flush=True)\n    except KeyboardInterrupt:\n        print('\\n')\n\nHere is the Python 2 version:\n\n.. code:: python\n\n    #! python\n    import pyautogui, sys\n    print('Press Ctrl-C to quit.')\n    try:\n        while True:\n            x, y = pyautogui.position()\n            positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)\n            print positionStr,\n            print '\\b' * (len(positionStr) + 2),\n            sys.stdout.flush()\n    except KeyboardInterrupt:\n        print '\\n'\n\nTo check if XY coordinates are on the screen, pass them (either as two integer arguments or a single tuple/list arguments with two integers) to the ``onScreen()`` function, which will return ``True`` if they are within the screen's boundaries and ``False`` if not. For example:\n\n.. code:: python\n\n    >>> pyautogui.onScreen(0, 0)\n    True\n    >>> pyautogui.onScreen(0, -1)\n    False\n    >>> pyautogui.onScreen(0, 99999999)\n    False\n    >>> pyautogui.size()\n    (1920, 1080)\n    >>> pyautogui.onScreen(1920, 1080)\n    False\n    >>> pyautogui.onScreen(1919, 1079)\n    True\n\nMouse Movement\n==============\n\nThe ``moveTo()`` function will move the mouse cursor to the X and Y integer coordinates you pass it. The ``None`` value can be passed for a coordinate to mean \"the current mouse cursor position\". For example:\n\n.. code:: python\n\n    >>> pyautogui.moveTo(100, 200)   # moves mouse to X of 100, Y of 200.\n    >>> pyautogui.moveTo(None, 500)  # moves mouse to X of 100, Y of 500.\n    >>> pyautogui.moveTo(600, None)  # moves mouse to X of 600, Y of 500.\n\nNormally the mouse cursor will instantly move to the new coordinates. If you want the mouse to gradually move to the new location, pass a third argument for the duration (in seconds) the movement should take. For example:\n\n.. code:: python\n\n    >>> pyautogui.moveTo(100, 200, 2)   # moves mouse to X of 100, Y of 200 over 2 seconds\n\n(If the duration is less than ``pyautogui.MINIMUM_DURATION`` the movement will be instant. By default, ``pyautogui.MINIMUM_DURATION`` is 0.1.)\n\nIf you want to move the mouse cursor over a few pixels *relative* to its current position, use the ``move()`` function. This function has similar parameters as ``moveTo()``. For example:\n\n.. code:: python\n\n    >>> pyautogui.moveTo(100, 200)  # moves mouse to X of 100, Y of 200.\n    >>> pyautogui.move(0, 50)       # move the mouse down 50 pixels.\n    >>> pyautogui.move(-30, 0)      # move the mouse left 30 pixels.\n    >>> pyautogui.move(-30, None)   # move the mouse left 30 pixels.\n\nMouse Drags\n===========\n\nPyAutoGUI's ``dragTo()`` and ``drag()`` functions have similar parameters as the ``moveTo()`` and ``move()`` functions. In addition, they have a ``button`` keyword which can be set to ``'left'``, ``'middle'``, and ``'right'`` for which mouse button to hold down while dragging. For example:\n\n.. code:: python\n\n    >>> pyautogui.dragTo(100, 200, button='left')     # drag mouse to X of 100, Y of 200 while holding down left mouse button\n    >>> pyautogui.dragTo(300, 400, 2, button='left')  # drag mouse to X of 300, Y of 400 over 2 seconds while holding down left mouse button\n    >>> pyautogui.drag(30, 0, 2, button='right')   # drag the mouse right 30 pixels over 2 seconds while holding down the right mouse button\n\n\nTween / Easing Functions\n========================\n\nTweening is an extra feature to make the mouse movements fancy. You can probably skip this section if you don't care about this.\n\nA tween or easing function dictates the progress of the mouse as it moves to its destination. Normally when moving the mouse over a duration of time, the mouse moves directly towards the destination in a straight line at a constant speed. This is known as a *linear tween* or *linear easing* function.\n\nPyAutoGUI has other tweening functions available in the ``pyautogui`` module. The ``pyautogui.easeInQuad`` function can be passed for the 4th argument to ``moveTo()``, ``move()``, ``dragTo()``, and ``drag()`` functions to have the mouse cursor start off moving slowly and then speeding up towards the destination. The total duration is still the same as the argument passed to the function. The ``pyautogui.easeOutQuad`` is the reverse: the mouse cursor starts moving fast but slows down as it approaches the destination. The ``pyautogui.easeOutElastic`` will overshoot the destination and \"rubber band\" back and forth until it settles at the destination.\n\nFor example:\n\n.. code:: python\n\n    >>> pyautogui.moveTo(100, 100, 2, pyautogui.easeInQuad)     # start slow, end fast\n    >>> pyautogui.moveTo(100, 100, 2, pyautogui.easeOutQuad)    # start fast, end slow\n    >>> pyautogui.moveTo(100, 100, 2, pyautogui.easeInOutQuad)  # start and end fast, slow in middle\n    >>> pyautogui.moveTo(100, 100, 2, pyautogui.easeInBounce)   # bounce at the end\n    >>> pyautogui.moveTo(100, 100, 2, pyautogui.easeInElastic)  # rubber band at the end\n\nThese tweening functions are copied from Al Sweigart's PyTweening module: https://pypi.python.org/pypi/PyTweening https://github.com/asweigart/pytweening This module does not have to be installed to use the tweening functions.\n\nIf you want to create your own tweening function, define a function that takes a single float argument between ``0.0`` (representing the start of the mouse travelling) and ``1.0`` (representing the end of the mouse travelling) and returns a float value between ``0.0`` and ``1.0``.\n\nMouse Clicks\n============\n\nThe ``click()`` function simulates a single, left-button mouse click at the mouse's current position. A \"click\" is defined as pushing the button down and then releasing it up. For example:\n\n.. code:: python\n\n    >>> pyautogui.click()  # click the mouse\n\nTo combine a ``moveTo()`` call before the click, pass integers for the ``x`` and ``y`` keyword argument:\n\n.. code:: python\n\n    >>> pyautogui.click(x=100, y=200)  # move to 100, 200, then click the left mouse button.\n\nTo specify a different mouse button to click, pass ``'left'``, ``'middle'``, or  ``'right'`` for the ``button`` keyword argument:\n\n.. code:: python\n\n    >>> pyautogui.click(button='right')  # right-click the mouse\n\nTo do multiple clicks, pass an integer to the ``clicks`` keyword argument. Optionally, you can pass a float or integer to the ``interval`` keyword argument to specify the amount of pause between the clicks in seconds. For example:\n\n.. code:: python\n\n    >>> pyautogui.click(clicks=2)  # double-click the left mouse button\n    >>> pyautogui.click(clicks=2, interval=0.25)  # double-click the left mouse button, but with a quarter second pause in between clicks\n    >>> pyautogui.click(button='right', clicks=3, interval=0.25)  ## triple-click the right mouse button with a quarter second pause in between clicks\n\nAs a convenient shortcut, the ``doubleClick()`` function will perform a double click of the left mouse button. It also has the optional ``x``, ``y``, ``interval``, and ``button`` keyword arguments. For example:\n\n.. code:: python\n\n    >>> pyautogui.doubleClick()  # perform a left-button double click\n\nThere is also a ``tripleClick()`` function with similar optional keyword arguments.\n\nThe ``rightClick()`` function has optional ``x`` and ``y`` keyword arguments.\n\nThe mouseDown() and mouseUp() Functions\n=======================================\n\nMouse clicks and drags are composed of both pressing the mouse button down and releasing it back up. If you want to perform these actions separately, call the ``mouseDown()`` and ``mouseUp()`` functions. They have the same ``x``, ``y``, and ``button``. For example:\n\n.. code:: python\n\n    >>> pyautogui.mouseDown(); pyautogui.mouseUp()  # does the same thing as a left-button mouse click\n    >>> pyautogui.mouseDown(button='right')  # press the right button down\n    >>> pyautogui.mouseUp(button='right', x=100, y=200)  # move the mouse to 100, 200, then release the right button up.\n\n\nMouse Scrolling\n===============\n\nThe mouse scroll wheel can be simulated by calling the ``scroll()`` function and passing an integer number of \"clicks\" to scroll. The amount of scrolling in a \"click\" varies between platforms. Optionally, integers can be passed for the the ``x`` and ``y`` keyword arguments to move the mouse cursor before performing the scroll. For example:\n\n.. code:: python\n\n    >>> pyautogui.scroll(10)   # scroll up 10 \"clicks\"\n    >>> pyautogui.scroll(-10)  # scroll down 10 \"clicks\"\n    >>> pyautogui.scroll(10, x=100, y=100)  # move mouse cursor to 100, 200, then scroll up 10 \"clicks\"\n\nOn OS X and Linux platforms, PyAutoGUI can also perform horizontal scrolling by calling the hscroll() function. For example:\n\n.. code:: python\n\n    >>> pyautogui.hscroll(10)   # scroll right 10 \"clicks\"\n    >>> pyautogui.hscroll(-10)   # scroll left 10 \"clicks\"\n\nThe ``scroll()`` function is a wrapper for ``vscroll()``, which performs vertical scrolling.\n"
  },
  {
    "path": "docs/msgbox.rst",
    "content": ".. default-role:: code\n\n=====================\nMessage Box Functions\n=====================\n\nPyAutoGUI makes use of the message box functions in PyMsgBox to provide a cross-platform, pure Python way to display JavaScript-style message boxes. There are four message box functions provided:\n\nThe alert() Function\n====================\n\n    >>> alert(text='', title='', button='OK')\n\nDisplays a simple message box with text and a single OK button. Returns the text of the button clicked on.\n\nThe confirm() Function\n======================\n\n    >>> confirm(text='', title='', buttons=['OK', 'Cancel'])\n\nDisplays a message box with OK and Cancel buttons. Number and text of buttons can be customized. Returns the text of the button clicked on.\n\nThe prompt() Function\n=====================\n\n    >>> prompt(text='', title='' , default='')\n\nDisplays a message box with text input, and OK & Cancel buttons. Returns the text entered, or None if Cancel was clicked.\n\nThe password() Function\n=======================\n\n    >>> password(text='', title='', default='', mask='*')\n\nDisplays a message box with text input, and OK & Cancel buttons. Typed characters appear as ``*``. Returns the text entered, or None if Cancel was clicked.\n\n"
  },
  {
    "path": "docs/quickstart.rst",
    "content": ".. default-role:: code\n\n===========\nCheat Sheet\n===========\n\nThis is a quickstart reference to using PyAutoGUI. PyAutoGUI is cross-platform GUI automation module that works on Python 2 & 3. You can control the mouse and keyboard as well as perform basic image recognition to automate tasks on your computer.\n\n**All the keyword arguments in the examples on this page are optional.**\n\n    >>> import pyautogui\n\nPyAutoGUI works on Windows/Mac/Linux and on Python 2 & 3. Install from PyPI with `pip install pyautogui`.\n\nGeneral Functions\n-----------------\n\n    >>> pyautogui.position()  # current mouse x and y\n    (968, 56)\n    >>> pyautogui.size()  # current screen resolution width and height\n    (1920, 1080)\n    >>> pyautogui.onScreen(x, y)  # True if x & y are within the screen.\n    True\n\nFail-Safes\n----------\n\nSet up a 2.5 second pause after each PyAutoGUI call:\n\n    >>> import pyautogui\n    >>> pyautogui.PAUSE = 2.5\n\nWhen fail-safe mode is `True`, moving the mouse to the upper-left will raise a `pyautogui.FailSafeException` that can abort your program:\n\n    >>> import pyautogui\n    >>> pyautogui.FAILSAFE = True\n\nMouse Functions\n---------------\n\nXY coordinates have 0, 0 origin at top left corner of the screen. X increases going right, Y increases going down.\n\n    >>> pyautogui.moveTo(x, y, duration=num_seconds)  # move mouse to XY coordinates over num_second seconds\n    >>> pyautogui.moveRel(xOffset, yOffset, duration=num_seconds)  # move mouse relative to its current position\n\nIf `duration` is 0 or unspecified, movement is immediate. Note: dragging on Mac can't be immediate.\n\n    >>> pyautogui.dragTo(x, y, duration=num_seconds)  # drag mouse to XY\n    >>> pyautogui.dragRel(xOffset, yOffset, duration=num_seconds)  # drag mouse relative to its current position\n\nCalling `click()` just clicks the mouse once with the left button at the mouse's current location, but the keyword arguments can change that:\n\n    >>> pyautogui.click(x=moveToX, y=moveToY, clicks=num_of_clicks, interval=secs_between_clicks, button='left')\n\nThe `button` keyword argument can be `'left'`, `'middle'`, or `'right'`.\n\nAll clicks can be done with `click()`, but these functions exist for readability. Keyword args are optional:\n\n    >>> pyautogui.rightClick(x=moveToX, y=moveToY)\n    >>> pyautogui.middleClick(x=moveToX, y=moveToY)\n    >>> pyautogui.doubleClick(x=moveToX, y=moveToY)\n    >>> pyautogui.tripleClick(x=moveToX, y=moveToY)\n\nPositive scrolling will scroll up, negative scrolling will scroll down:\n\n    >>> pyautogui.scroll(amount_to_scroll, x=moveToX, y=moveToY)\n\nIndividual button down and up events can be called separately:\n\n    >>> pyautogui.mouseDown(x=moveToX, y=moveToY, button='left')\n    >>> pyautogui.mouseUp(x=moveToX, y=moveToY, button='left')\n\nKeyboard Functions\n------------------\n\nKey presses go to wherever the keyboard cursor is at function-calling time.\n\n    >>> pyautogui.typewrite('Hello world!\\n', interval=secs_between_keys)  # useful for entering text, newline is Enter\n\nA list of key names can be passed too:\n\n    >>> pyautogui.typewrite(['a', 'b', 'c', 'left', 'backspace', 'enter', 'f1'], interval=secs_between_keys)\n\nThe full list of key names is in `pyautogui.KEYBOARD_KEYS`.\n\nKeyboard hotkeys like Ctrl-S or Ctrl-Shift-1 can be done by passing a list of key names to `hotkey()`:\n\n    >>> pyautogui.hotkey('ctrl', 'c')  # ctrl-c to copy\n    >>> pyautogui.hotkey('ctrl', 'v')  # ctrl-v to paste\n\nIndividual button down and up events can be called separately:\n\n    >>> pyautogui.keyDown(key_name)\n    >>> pyautogui.keyUp(key_name)\n\n\nMessage Box Functions\n---------------------\n\nIf you need to pause the program until the user clicks OK on something, or want to display some information to the user, the message box functions have similar names that JavaScript has:\n\n    >>> pyautogui.alert('This displays some text with an OK button.')\n    >>> pyautogui.confirm('This displays text and has an OK and Cancel button.')\n    'OK'\n    >>> pyautogui.prompt('This lets the user type in a string and press OK.')\n    'This is what I typed in.'\n\nThe `prompt()` function will return `None` if the user clicked Cancel.\n\nScreenshot Functions\n--------------------\n\nPyAutoGUI uses Pillow/PIL for its image-related data.\n\nOn Linux, you must run `sudo apt-get install scrot` to use the screenshot features.\n\n    >>> pyautogui.screenshot()  # returns a Pillow/PIL Image object\n    <PIL.Image.Image image mode=RGB size=1920x1080 at 0x24C3EF0>\n    >>> pyautogui.screenshot('foo.png')  # returns a Pillow/PIL Image object, and saves it to a file\n    <PIL.Image.Image image mode=RGB size=1920x1080 at 0x31AA198>\n\nIf you have an image file of something you want to click on, you can find it on the screen with `locateOnScreen()`.\n\n    >>> pyautogui.locateOnScreen('looksLikeThis.png')  # returns (left, top, width, height) of first place it is found\n    (863, 417, 70, 13)\n\nThe `locateAllOnScreen()` function will return a generator for all the locations it is found on the screen:\n\n    >>> for i in pyautogui.locateAllOnScreen('looksLikeThis.png')\n    ...\n    ...\n    (863, 117, 70, 13)\n    (623, 137, 70, 13)\n    (853, 577, 70, 13)\n    (883, 617, 70, 13)\n    (973, 657, 70, 13)\n    (933, 877, 70, 13)\n\n    >>> list(pyautogui.locateAllOnScreen('looksLikeThis.png'))\n    [(863, 117, 70, 13), (623, 137, 70, 13), (853, 577, 70, 13), (883, 617, 70, 13), (973, 657, 70, 13), (933, 877, 70, 13)]\n\nThe `locateCenterOnScreen()` function just returns the XY coordinates of the middle of where the image is found on the screen:\n\n    >>> pyautogui.locateCenterOnScreen('looksLikeThis.png')  # returns center x and y\n    (898, 423)\n\nThese functions return `None` if the image couldn't be found on the screen.\n\nNote: The locate functions are slow and can take a full second or two.\n\n"
  },
  {
    "path": "docs/roadmap.rst",
    "content": "\n=======\nRoadmap\n=======\n\nPyAutoGUI is planned as a replacement for other Python GUI automation scripts, such as PyUserInput, PyKeyboard, PyMouse, pykey, etc. Eventually it would be great to offer the same type of features that Sikuli_ offers.\n\nFor now, the primary aim for PyAutoGUI is cross-platform mouse and keyboard control and a simple API.\n\nFuture features planned (specific versions not planned yet):\n\n- A tool for determining why an image can't be found in a particular screenshot. (This is a common source of questions for users.)\n- Full compatibility on Raspberry Pis.\n- \"Wave\" function, which is used just to see where the mouse is by shaking the mouse cursor a bit. A small helper function.\n- locateNear() function, which is like the other locate-related screen reading functions except it finds the first instance near an xy point on the screen.\n- Find a list of all windows and their captions.\n- Click coordinates relative to a window, instead of the entire screen.\n- Make it easier to work on systems with multiple monitors.\n- GetKeyState() type of function\n- Ability to set global hotkey on all platforms so that there can be an easy \"kill switch\" for GUI automation programs.\n- Optional nonblocking pyautogui calls.\n- \"strict\" mode for keyboard - passing an invalid keyboard key causes an exception instead of silently skipping it.\n- rename keyboardMapping to KEYBOARD_MAPPING\n- Ability to convert png and other image files into a string that can be copy/pasted directly in the source code, so that they don't have to be shared separately with people's pyautogui scripts.\n- Test to make sure pyautogui works in Windows/mac/linux VMs.\n- A way to compare two images and highlight differences between them (good for pointing out when a UI changes, etc.)\n\nWindow handling features:\n - pyautogui.getWindows()      # returns a dict of window titles mapped to window IDs\n - pyautogui.getWindow(str_title_or_int_id)   # returns a \"Win\" object\n - win.move(x, y)\n - win.resize(width, height)\n - win.maximize()\n - win.minimize()\n - win.restore()\n - win.close()\n - win.position()  # returns (x, y) of top-left corner\n - win.moveRel(x=0, y=0)   # moves relative to the x, y of top-left corner of the window\n - win.clickRel(x=0, y=0, clicks=1, interval=0.0, button='left')  # click relative to the x, y of top-left corner of the window\n - Additions to screenshot functionality so that it can capture specific windows instead of full screen.\n\n.. _Sikuli: http://www.sikuli.org\n"
  },
  {
    "path": "docs/screenshot.rst",
    "content": ".. default-role:: code\n\n====================\nScreenshot Functions\n====================\n\nPyAutoGUI can take screenshots, save them to files, and locate images within the screen. This is useful if you have a small image of, say, a button that needs to be clicked and want to locate it on the screen. These features are provided by the PyScreeze module, which is installed with PyAutoGUI.\n\nScreenshot functionality requires the Pillow module. OS X uses the `screencapture` command, which comes with the operating system. Linux uses the `scrot` command, which can be installed by running `sudo apt-get install scrot`.\n\nThe screenshot() Function\n=========================\n\nCalling `screenshot()` will return an Image object (see the Pillow or PIL module documentation for details). Passing a string of a filename will save the screenshot to a file as well as return it as an Image object.\n\n.. code:: python\n\n    >>> import pyautogui\n    >>> im1 = pyautogui.screenshot()\n    >>> im2 = pyautogui.screenshot('my_screenshot.png')\n\nOn a 1920 x 1080 screen, the `screenshot()` function takes roughly 100 milliseconds - it's not fast but it's not slow.\n\nThere is also an optional `region` keyword argument, if you do not want a screenshot of the entire screen. You can pass a four-integer tuple of the left, top, width, and height of the region to capture:\n\n    >>> import pyautogui\n    >>> im = pyautogui.screenshot(region=(0,0, 300, 400))\n\nThe Locate Functions\n====================\n\nNOTE: As of version 0.9.41, if the locate functions can't find the provided image, they'll raise `ImageNotFoundException` instead of returning `None`.\n\nYou can visually locate something on the screen if you have an image file of it. For example, say the calculator app was running on your computer and looked like this:\n\n.. image:: calculator.png\n\nYou can't call the `moveTo()` and `click()` functions if you don't know the exact screen coordinates of where the calculator buttons are. The calculator can appear in a slightly different place each time it is launched, causing you to re-find the coordinates each time. However, if you have an image of the button, such as the image of the 7 button:\n\n.. image:: calc7key.png\n\n. . . you can call the `locateOnScreen('calc7key.png')` function to get the screen coordinates. The return value is a 4-integer tuple: (left, top, width, height). This tuple can be passed to `center()` to get the X and Y coordinates at the center of this region. If the image can't be found on the screen, `locateOnScreen()` raises `ImageNotFoundException`.\n\n    >>> import pyautogui\n    >>> button7location = pyautogui.locateOnScreen('calc7key.png')\n    >>> button7location\n    Box(left=1416, top=562, width=50, height=41)\n    >>> button7location[0]\n    1416\n    >>> button7location.left\n    1416\n    >>> button7point = pyautogui.center(button7location)\n    >>> button7point\n    Point(x=1441, y=582)\n    >>> button7point[0]\n    1441\n    >>> button7point.x\n    1441\n    >>> button7x, button7y = button7point\n    >>> pyautogui.click(button7x, button7y)  # clicks the center of where the 7 button was found\n    >>> pyautogui.click('calc7key.png') # a shortcut version to click on the center of where the 7 button was found\n\nThe optional `confidence` keyword argument specifies the accuracy with which the function should locate the image on screen. This is helpful in case the function is not able to locate an image due to negligible pixel differences:\n\n    >>> import pyautogui\n    >>> button7location = pyautogui.locateOnScreen('calc7key.png', confidence=0.9)\n    >>> button7location\n    Box(left=1416, top=562, width=50, height=41)\n\n**Note**: You need to have `OpenCV <https://pypi.org/project/opencv-python/>`_ installed for the `confidence` keyword to work.\n\nThe `locateCenterOnScreen()` function combines `locateOnScreen()` and `center()`:\n\n    >>> import pyautogui\n    >>> x, y = pyautogui.locateCenterOnScreen('calc7key.png')\n    >>> pyautogui.click(x, y)\n\nOn a 1920 x 1080 screen, the locate function calls take about 1 or 2 seconds. This may be too slow for action video games, but works for most purposes and applications.\n\nThere are several \"locate\" functions. They all start looking at the top-left corner of the screen (or image) and look to the right and then down. The arguments can either be a\n\n- `locateOnScreen(image, grayscale=False)` - Returns (left, top, width, height) coordinate of first found instance of the `image` on the screen. Raises `ImageNotFoundException` if not found on the screen.\n\n- `locateCenterOnScreen(image, grayscale=False)` - Returns (x, y) coordinates of the center of the first found instance of the `image` on the screen. Raises `ImageNotFoundException` if not found on the screen.\n\n- `locateAllOnScreen(image, grayscale=False)` - Returns a generator that yields (left, top, width, height) tuples for where the image is found on the screen.\n\n- `locate(needleImage, haystackImage, grayscale=False)` - Returns (left, top, width, height) coordinate of first found instance of `needleImage` in `haystackImage`. Raises `ImageNotFoundException` if not found on the screen.\n\n- `locateAll(needleImage, haystackImage, grayscale=False)` - Returns a generator that yields (left, top, width, height) tuples for where `needleImage` is found in `haystackImage`.\n\nThe \"locate all\" functions can be used in for loops or passed to `list()`:\n\n    >>> import pyautogui\n    >>> for pos in pyautogui.locateAllOnScreen('someButton.png')\n    ...   print(pos)\n    ...\n    (1101, 252, 50, 50)\n    (59, 481, 50, 50)\n    (1395, 640, 50, 50)\n    (1838, 676, 50, 50)\n    >>> list(pyautogui.locateAllOnScreen('someButton.png'))\n    [(1101, 252, 50, 50), (59, 481, 50, 50), (1395, 640, 50, 50), (1838, 676, 50, 50)]\n\nThese \"locate\" functions are fairly expensive; they can take a full second to run. The best way to speed them up is to pass a `region` argument (a 4-integer tuple of (left, top, width, height)) to only search a smaller region of the screen instead of the full screen:\n\n    >>> import pyautogui\n    >>> pyautogui.locateOnScreen('someButton.png', region=(0,0, 300, 400))\n\nGrayscale Matching\n------------------\n\nOptionally, you can pass `grayscale=True` to the locate functions to give a slight speedup (about 30%-ish). This desaturates the color from the images and screenshots, speeding up the locating but potentially causing false-positive matches.\n\n    >>> import pyautogui\n    >>> button7location = pyautogui.locateOnScreen('calc7key.png', grayscale=True)\n    >>> button7location\n    (1416, 562, 50, 41)\n\nPixel Matching\n--------------\n\nTo obtain the RGB color of a pixel in a screenshot, use the Image object's `getpixel()` method:\n\n    >>> import pyautogui\n    >>> im = pyautogui.screenshot()\n    >>> im.getpixel((100, 200))\n    (130, 135, 144)\n\nOr as a single function, call the `pixel()` PyAutoGUI function, which is a wrapper for the previous calls:\n\n    >>> import pyautogui\n    >>> pix = pyautogui.pixel(100, 200)\n    >>> pix\n    RGB(red=130, green=135, blue=144)\n    >>> pix[0]\n    130\n    >>> pix.red\n    130\n\nIf you just need to verify that a single pixel matches a given pixel, call the `pixelMatchesColor()` function, passing it the X coordinate, Y coordinate, and RGB tuple of the color it represents:\n\n    >>> import pyautogui\n    >>> pyautogui.pixelMatchesColor(100, 200, (130, 135, 144))\n    True\n    >>> pyautogui.pixelMatchesColor(100, 200, (0, 0, 0))\n    False\n\nThe optional `tolerance` keyword argument specifies how much each of the red, green, and blue values can vary while still matching:\n\n    >>> import pyautogui\n    >>> pyautogui.pixelMatchesColor(100, 200, (130, 135, 144))\n    True\n    >>> pyautogui.pixelMatchesColor(100, 200, (140, 125, 134))\n    False\n    >>> pyautogui.pixelMatchesColor(100, 200, (140, 125, 134), tolerance=10)\n    True\n"
  },
  {
    "path": "docs/simplified-chinese.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# PyAutoGUI——让所有GUI都自动化\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"本教程译自大神[Al Sweigart](http://inventwithpython.com/)的[PyAutoGUI](https://pyautogui.readthedocs.org/)项目，Python自动化工具，更适合处理GUI任务，网页任务推荐：\\n\",\n    \"- [Selenium](https://selenium-python.readthedocs.org/)+Firefox记录（Chromedriver和Phantomjs也很给力，Phantomjs虽然是无头浏览器，但有时定位不准），然后用Python写单元测试\\n\",\n    \"- [request](http://www.python-requests.org/en/latest/)处理get/post请求写一堆代码自动化处理，都在后台运行，不用运行浏览器，非常适合处理表单\\n\",\n    \"\\n\",\n    \"没有[sikuli](http://www.sikuli.org/)功能多，但是Python让生活更简单，[人生苦短，Python当歌](http://cn.pycon.org/2015/)。\\n\",\n    \"\\n\",\n    \"同时推荐一本Python网络数据采集（图灵社区取的名字^_^）的基础书籍[Ryan Mitchell的《Web Scraping with Python》](http://shop.oreilly.com/product/0636920034391.do)，可以和PyAutoGUI结合使用。\\n\",\n    \"\\n\",\n    \"tl;dr\\n\",\n    \"\\n\",\n    \"<!-- TEASER_END -->\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"2015-08-17：输入中文bug没有解决，目前的解决方案是Python 2.X环境下安装[pyperclip](https://github.com/asweigart/pyperclip)和pyautogui，用复制粘贴来实现。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyperclip\\n\",\n    \"import pyautogui\\n\",\n    \"\\n\",\n    \"#  PyAutoGUI中文输入需要用粘贴实现\\n\",\n    \"#  Python 2版本的pyperclip提供中文复制\\n\",\n    \"def paste(foo):\\n\",\n    \"    pyperclip.copy(foo)\\n\",\n    \"    pyautogui.hotkey('ctrl', 'v')\\n\",\n    \"\\n\",\n    \"foo = u'学而时习之'\\n\",\n    \"#  移动到文本框\\n\",\n    \"pyautogui.click(130,30)\\n\",\n    \"paste(foo)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#  1.简介\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##  1.1 目的\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI是一个纯Python的GUI自动化工具，其目的是可以用程序自动控制鼠标和键盘操作，多平台支持（Windows，OS X，Linux）。可以用`pip`安装，Github上有[源代码](https://github.com/asweigart/pyautogui)。\\n\",\n    \"\\n\",\n    \"下面的代码让鼠标移到屏幕中央。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"screenWidth, screenHeight = pyautogui.size()\\n\",\n    \"pyautogui.moveTo(screenWidth / 2, screenHeight / 2)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI可以模拟鼠标的移动、点击、拖拽，键盘按键输入、按住操作，以及鼠标+键盘的热键同时按住等操作，可以说手能动的都可以。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##  1.2 例子\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"screenWidth, screenHeight = pyautogui.size()\\n\",\n    \"currentMouseX, currentMouseY = pyautogui.position()\\n\",\n    \"pyautogui.moveTo(100, 150)\\n\",\n    \"pyautogui.click()\\n\",\n    \"#  鼠标向下移动10像素\\n\",\n    \"pyautogui.moveRel(None, 10)\\n\",\n    \"pyautogui.doubleClick()\\n\",\n    \"#  用缓动/渐变函数让鼠标2秒后移动到(500,500)位置\\n\",\n    \"#  use tweening/easing function to move mouse over 2 seconds.\\n\",\n    \"pyautogui.moveTo(1800, 500, duration=2, tween=pyautogui.easeInOutQuad)\\n\",\n    \"#  在每次输入之间暂停0.25秒\\n\",\n    \"pyautogui.typewrite('Hello world!', interval=0.25)\\n\",\n    \"pyautogui.press('esc')\\n\",\n    \"pyautogui.keyDown('shift')\\n\",\n    \"pyautogui.press(['left', 'left', 'left', 'left', 'left', 'left'])\\n\",\n    \"pyautogui.keyUp('shift')\\n\",\n    \"pyautogui.hotkey('ctrl', 'c')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"distance = 200\\n\",\n    \"while distance > 0:\\n\",\n    \"    pyautogui.dragRel(distance, 0, duration=0.5) # 向右\\n\",\n    \"    distance -= 5\\n\",\n    \"    pyautogui.dragRel(0, distance, duration=0.5) # 向下\\n\",\n    \"    pyautogui.draIn gRel(-distance, 0, duration=0.5) # 向左\\n\",\n    \"    distance -= 5\\n\",\n    \"    pyautogui.dragRel(0, -distance, duration=0.5) # 向上\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1.4 保护措施（Fail-Safes）\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"就像《魔法师的学徒》(Sorcerer’s Apprentice)会担水的扫帚，可以担水，却无力阻止水漫浴室。你的程序也可能会失控（即使是按照你的意思执行的），那时就需要中断。如果鼠标还在自动操作，就很难在程序窗口关闭它。\\n\",\n    \"\\n\",\n    \"为了能够及时中断，PyAutoGUI提供了一个保护措施。当`pyautogui.FAILSAFE = True`时，如果把鼠标光标在屏幕左上角，PyAutoGUI函数就会产生`pyautogui.FailSafeException`异常。如果失控了，需要中断PyAutoGUI函数，就把鼠标光标在屏幕左上角。要禁用这个特性，就把`FAILSAFE`设置成`False`：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"pyautogui.FAILSAFE = False\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"通过把`pyautogui.PAUSE`设置成`float`或`int`时间（秒），可以为所有的PyAutoGUI函数增加延迟。默认延迟时间是0.1秒。在函数循环执行的时候，这样做可以让PyAutoGUI运行的慢一点，非常有用。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"pyautogui.PAUSE = 2.5\\n\",\n    \"pyautogui.moveTo(100,100); pyautogui.click()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"所有的PyAutoGUI函数在延迟完成前都处于阻塞状态（block）。（未来计划增加一个可选的非阻塞模式来调用函数。）\\n\",\n    \"\\n\",\n    \"**建议`PAUSE`和`FAILSAFE`一起使用。**\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 2 安装与依赖\\n\",\n    \"\\n\",\n    \"PyAutoGUI支持Python 2.x和Python 3.x\\n\",\n    \"- Windows：PyAutoGUI没有任何依赖，因为它用Python的`ctypes`模块所以不需要`pywin32`\\n\",\n    \"```\\n\",\n    \"pip3 install pyautogui\\n\",\n    \"```\\n\",\n    \"- OS X：PyAutoGUI需要[PyObjC](http://pythonhosted.org/pyobjc/install.html)运行AppKit和Quartz模块。这个模块在PyPI上的按住顺序是`pyobjc-core`和`pyobjc`\\n\",\n    \"```\\n\",\n    \"sudo pip3 install pyobjc-core\\n\",\n    \"sudo pip3 install pyobjc\\n\",\n    \"sudo pip3 install pyautogui\\n\",\n    \"```\\n\",\n    \"- Linux：PyAutoGUI需要`python-xlib`（Python 2）、`python3-Xlib`（Python 3）\\n\",\n    \"```\\n\",\n    \"sudo pip3 install python3-xlib\\n\",\n    \"sudo apt-get scrot\\n\",\n    \"sudo apt-get install python-tk\\n\",\n    \"sudo apt-get install python3-dev\\n\",\n    \"sudo pip3 install pyautogui```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"## 3.速查表（小抄，Cheat Sheet）\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"### 3.1 常用函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(123, 372)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"#  当前鼠标的坐标\\n\",\n    \"pyautogui.position()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(1920, 1080)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"#  当前屏幕的分辨率（宽度和高度）\\n\",\n    \"pyautogui.size()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"#  (x,y)是否在屏幕上\\n\",\n    \"x, y = 122, 244\\n\",\n    \"pyautogui.onScreen(x, y)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"### 3.2 保护措施\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"PyAutoGUI函数增加延迟为2.5秒：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"pyautogui.PAUSE = 2.5\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"当pyautogui.FAILSAFE = True时，如果把鼠标光标在屏幕左上角，PyAutoGUI函数就会产生pyautogui.FailSafeException异常。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"pyautogui.FAILSAFE = True\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"### 3.3 鼠标函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"坐标系的原点是左上角。X轴（水平）坐标向右增大，Y轴（竖直）坐标向下增大。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"num_seconds = 1.2\\n\",\n    \"#  用num_seconds秒的时间把光标移动到(x, y)位置\\n\",\n    \"pyautogui.moveTo(x, y, duration=num_seconds)\\n\",\n    \"#  用num_seconds秒的时间把光标的X轴（水平）坐标移动xOffset，\\n\",\n    \"#  Y轴（竖直）坐标向下移动yOffset。\\n\",\n    \"xOffset, yOffset = 50, 100\\n\",\n    \"pyautogui.moveRel(xOffset, yOffset, duration=num_seconds)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"`click()`函数就是让鼠标点击，默认是单击左键，参数可以设置：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.click(x=moveToX, y=moveToY, clicks=num_of_clicks, interval=secs_between_clicks, button='left')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"其中，`button`属性可以设置成`left`，`middle`和`right`。\\n\",\n    \"\\n\",\n    \"所有的点击都可以用这个函数，不过下面的函数可读性更好：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.rightClick(x=moveToX, y=moveToY)\\n\",\n    \"pyautogui.middleClick(x=moveToX, y=moveToY)\\n\",\n    \"pyautogui.doubleClick(x=moveToX, y=moveToY)\\n\",\n    \"pyautogui.tripleClick(x=moveToX, y=moveToY)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"`scroll`函数控制鼠标滚轮的滚动，`amount_to_scroll`参数表示滚动的格数。正数则页面向上滚动，负数则向下滚动：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.scroll(clicks=amount_to_scroll, x=moveToX, y=moveToY)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"每个按键按下和松开两个事件可以分开处理：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.mouseDown(x=moveToX, y=moveToY, button='left')\\n\",\n    \"pyautogui.mouseUp(x=moveToX, y=moveToY, button='left')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 3.4 键盘函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"键盘上可以按的键都可以调用：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  每次键入的时间间隔\\n\",\n    \"secs_between_keys = 0.1\\n\",\n    \"pyautogui.typewrite('Hello world!\\\\n', interval=secs_between_keys)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"多个键也可以：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.typewrite(['a', 'b', 'c', 'left', 'backspace', 'enter', 'f1'], interval=secs_between_keys)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"按键名称列表：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"['\\\\t', '\\\\n', '\\\\r', ' ', '!', '\\\"', '#', '$', '%', '&']\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.KEYBOARD_KEYS[:10]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"键盘的一些热键像`Ctrl-S`或`Ctrl-Shift-1`都可以用`hotkey()`函数来实现：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.hotkey('ctrl', 'a') # 全选\\n\",\n    \"pyautogui.hotkey('ctrl', 'c') # 复制\\n\",\n    \"pyautogui.hotkey('ctrl', 'v') # 粘贴\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"每个按键的按下和松开也可以单独调用：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.keyDown(key_name)\\n\",\n    \"pyautogui.keyUp(key_name)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"### 3.5 消息弹窗函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"如果你需要消息弹窗，通过单击OK暂停程序，或者向用户显示一些信息，消息弹窗函数就会有类似JavaScript的功能：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"''\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.alert('这个消息弹窗是文字+OK按钮')\\n\",\n    \"pyautogui.confirm('这个消息弹窗是文字+OK+Cancel按钮')\\n\",\n    \"pyautogui.prompt('这个消息弹窗是让用户输入字符串，单击OK')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"在`prompt()`函数中，如果用户什么都不输入，就会返回`None`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 3.6 截屏函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI用Pillow/PIL库实现图片相关的识别和操作。\\n\",\n    \"\\n\",\n    \"在Linux里面，你必须执行`sudo apt-get install scrot`来使用截屏特性。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  返回一个Pillow/PIL的Image对象\\n\",\n    \"pyautogui.screenshot()\\n\",\n    \"pyautogui.screenshot('foo.png')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"如果你有一个图片文件想在上面做点击操作，你可以用`locateOnScreen()`函数来定位。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(0, 1040, 48, 40)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"#  返回(最左x坐标，最顶y坐标，宽度，高度)\\n\",\n    \"pyautogui.locateOnScreen('pyautogui/looks.png')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`locateAllOnScreen()`函数会寻找所有相似图片，返回一个生成器：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"(0, 1040, 48, 40)\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"for i in pyautogui.locateAllOnScreen('pyautogui/looks.png'):\\n\",\n    \"    print(i)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[(0, 1040, 48, 40)]\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"list(pyautogui.locateAllOnScreen('pyautogui/looks.png'))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`locateCenterOnScreen()`函数会返回图片在屏幕上的中心XY轴坐标值：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(24, 1060)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.locateCenterOnScreen('pyautogui/looks.png')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"如果没找到图片会返回`None`。\\n\",\n    \">定位比较慢，一般得用1~2秒\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 4 常用函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"- `position()`：返回整数元组(x, y)，分别表示鼠标光标所在位置的XY轴坐标\\n\",\n    \"- `size()`：返回显示器的尺寸整数元组(x, y)。未来将加入多屏支持\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 5 鼠标控制函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.1 屏幕与鼠标位置\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"屏幕位置使用X和Y轴的笛卡尔坐标系。原点`(0,0)`在左上角，分别向右、向下增大。\\n\",\n    \"\\n\",\n    \"如果屏幕像素是$1920 \\\\times 1080$，那么右下角的坐标是`(1919, 1079)`。\\n\",\n    \"\\n\",\n    \"分辨率大小可以通过`size()`函数返回整数元组。光标的位置用`position()`返回。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(1920, 1080)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.size()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(272, 688)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.position()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"下面是Python 3版本的光标位置记录程序：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# ! python 3\\n\",\n    \"import pyautogui\\n\",\n    \"print('Press Ctrl-C to quit')\\n\",\n    \"try:\\n\",\n    \"    while True:\\n\",\n    \"        x, y = pyautogui.position()\\n\",\n    \"        positionStr = 'X: {} Y: {}'.format(*[str(x).rjust(4) for x in [x, y]])\\n\",\n    \"        print(positionStr, end='')\\n\",\n    \"        print('\\\\b' * len(positionStr), end='', flush=True)\\n\",\n    \"except KeyboardInterrupt:\\n\",\n    \"    print('\\\\n')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Python 2版本是：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# ! python\\n\",\n    \"import pyautogui, sys\\n\",\n    \"print('Press Ctrl-C to quit.')\\n\",\n    \"try:\\n\",\n    \"    while True:\\n\",\n    \"        x, y = pyautogui.position()\\n\",\n    \"        positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4)\\n\",\n    \"        print positionStr,\\n\",\n    \"        print '\\\\b' * (len(positionStr) + 2),\\n\",\n    \"        sys.stdout.flush()\\n\",\n    \"except KeyboardInterrupt:\\n\",\n    \"    print '\\\\n'\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"要检查XY坐标是否在屏幕上，需要用`onScreen()`函数来检验，如果在屏幕上返回`True`：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"pyautogui.onScreen(0, 0)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.onScreen(0, -1)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.onScreen(0, 2080)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.onScreen(1920, 1080)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.onScreen(1919, 1079)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.2 鼠标行为\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`moveTo()`函数会把鼠标光标移动到指定的XY轴坐标处。如果传入`None`值，则表示使用当前光标的对象轴坐标值。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.moveTo(100, 200)     # 光标移动到(100, 200)位置\\n\",\n    \"pyautogui.moveTo(None, 500)   # 光标移动到(100, 500)位置\\n\",\n    \"pyautogui.moveTo(600, None)   # 光标移动到(600, 500)位置\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"一般鼠标光标都是瞬间移动到指定的位置，如果你想让鼠标移动的慢点，可以设置持续时间：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.moveTo(100, 200, duration=2)     # 用2秒把光标移动到(100, 200)位置\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"默认的持续时间`pyautogui.MINIMUM_DURATION `是0.1秒，如果你设置的时间比默认值还短，那么就会瞬间执行。\\n\",\n    \"\\n\",\n    \"如果你想让光标以当前位置为原点，进行相对移动，就用`pyautogui.moveRel()`函数。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.moveTo(100, 200) #把光标移动到(100, 200)位置\\n\",\n    \"pyautogui.moveRel(0, 50)   #向下移动50\\n\",\n    \"pyautogui.moveRel(30, 0, 2)   #向右移动30\\n\",\n    \"pyautogui.moveRel(30, None)   #向右移动30\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.3 鼠标拖拽\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI的`dragTo()`和`dragRel()`函数与`moveTo()`和`moveRel()`函数类似。另外，他们有一个`button`参数可以设置成`left`，`middle`和`right`三个键。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  按住鼠标左键，把鼠标拖拽到(100, 200)位置\\n\",\n    \"pyautogui.dragTo(100, 200, button='left')\\n\",\n    \"#  按住鼠标左键，用2秒钟把鼠标拖拽到(300, 400)位置\\n\",\n    \"pyautogui.dragTo(300, 400, 2, button='left')\\n\",\n    \"#  按住鼠标右键，用2秒钟把鼠标拖拽到(30,0)位置\\n\",\n    \"pyautogui.dragTo(30, 0, 2, button='right')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.4 缓动/渐变（Tween / Easing）函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"缓动/渐变函数的作用是让光标的移动更炫。如果你不需要用到的话，你可以忽略这些。\\n\",\n    \"\\n\",\n    \"缓动/渐变函数可以改变光标移动过程的速度和方向。通常鼠标是匀速直线运动，这就是线性缓动/渐变函数。PyAutoGUI有30种缓动/渐变函数，可以通过`pyautogui.ease*?`查看。其中，`pyautogui.easeInQuad()`函数可以用于`moveTo()`，`moveRel()`，`dragTo()`和`dragRel()`函数，光标移动呈现先慢后快的效果，整个过程的时间还是和原来一样。而`pyautogui.easeOutQuad`函数的效果相反：光标开始移动很快，然后慢慢减速。`pyautogui.easeOutElastic`是弹簧效果，首先越过终点，然后再反弹回来。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  开始很慢，不断加速\\n\",\n    \"pyautogui.moveTo(100, 100, 2, pyautogui.easeInQuad)\\n\",\n    \"#  开始很快，不断减速\\n\",\n    \"pyautogui.moveTo(100, 100, 2, pyautogui.easeOutQuad)\\n\",\n    \"#  开始和结束都快，中间比较慢\\n\",\n    \"pyautogui.moveTo(100, 100, 2, pyautogui.easeInOutQuad)\\n\",\n    \"#  一步一徘徊前进\\n\",\n    \"pyautogui.moveTo(100, 100, 2, pyautogui.easeInBounce)\\n\",\n    \"#  徘徊幅度更大，甚至超过起点和终点\\n\",\n    \"pyautogui.moveTo(100, 100, 2, pyautogui.easeInElastic)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"这些效果函数是模仿Al Sweigart的[PyTweening](https://github.com/asweigart/pytweening)模块，可以直接使用，不需要额外安装。\\n\",\n    \"\\n\",\n    \"如果你想创建自己的效果，也可以定义一个函数，其参数是(0.0,1.0)，表示起点和终点，返回值是介于[0.0,1.0]之间的数。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.5 鼠标单击\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`click()`函数模拟单击鼠标左键一次的行为。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.click()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"如果单机之前要先移动，可以把目标的XY坐标值传入函数：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  先移动到(100, 200)再单击\\n\",\n    \"pyautogui.click(x=100, y=200, duration=2)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"可以通过`button`参数设置`left`，`middle`和`right`三个键。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.click(button='right')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"要做多次单击可以设置`clicks`参数，还有`interval`参数可以设置每次单击之间的时间间隔。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  双击左键\\n\",\n    \"pyautogui.click(clicks=2)\\n\",\n    \"#  两次单击之间停留0.25秒\\n\",\n    \"pyautogui.click(clicks=2, interval=0.25)\\n\",\n    \"#  三击右键\\n\",\n    \"pyautogui.click(button='right', clicks=2, interval=0.25)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"为了操作方便，PyAutoGUI提供了`doubleClick()`，`tripleClick()`和`rightClick()`来实现双击、三击和右击操作。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.6 鼠标按下和松开函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`mouseDown()`和`mouseUp()`函数可以实现鼠标按下和鼠标松开的操作。两者参数相同，有`x`，`y`和`button`。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  鼠标左键按下再松开\\n\",\n    \"pyautogui.mouseDown(); pyautogui.mouseUp() \\n\",\n    \"#  按下鼠标右键\\n\",\n    \"pyautogui.mouseDown(button='right') \\n\",\n    \"#  移动到(100, 200)位置，然后松开鼠标右键\\n\",\n    \"pyautogui.mouseUp(button='right', x=100, y=200) \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 5.7 滚轮滚动函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"鼠标滚轮滚动可以用`scroll()`函数和`clicks`次数参数来模拟。不同平台上的`clicks`次数不太一样。还有`x`和`y`参数可以在滚动之前定位到(x, y)位置。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  向上滚动10格\\n\",\n    \"pyautogui.scroll(10)\\n\",\n    \"#  向下滚动10格\\n\",\n    \"pyautogui.scroll(-10)\\n\",\n    \"#  移动到(100, 100)位置再向上滚动10格\\n\",\n    \"pyautogui.scroll(10, x=100, y=100)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"在OS X和Linux平台上，PyAutoGUI还可以用`hscroll()`实现水平滚动。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  向右滚动10格\\n\",\n    \"pyautogui.hscroll(10)\\n\",\n    \"#  向左滚动10格\\n\",\n    \"pyautogui.hscroll(-10)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`scroll()`函数是`vscroll()`的一个包装（`wrapper`），执行竖直滚动。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6 键盘控制函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6.1 `typewrite()`输入函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"键盘控制的主要函数就是`typewrite()`。这个函数可以实现字符输入。要在两次输入间增加时间间隔，可以用`interval`参数。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  输入Hello world!\\n\",\n    \"pyautogui.typewrite('Hello world!')\\n\",\n    \"#  每次输入间隔0.25秒，输入Hello world!\\n\",\n    \"pyautogui.typewrite('Hello world!', interval=0.25)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`typewrite()`函数只能用于单个字符键，不能按SHITF和F1这些功能键。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6.2 `press()`，`keyDown()`和`keyUp()`函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"要按那些功能键，可以用`press()`函数把`pyautogui.KEYBOARD_KEYS`里面按键对应的字符串输入进去。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  ENTER键\\n\",\n    \"pyautogui.press('enter')\\n\",\n    \"#  F1键\\n\",\n    \"pyautogui.press('f1')\\n\",\n    \"#  左方向键\\n\",\n    \"pyautogui.press('left')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`press()`函数其实是`keyDown()`和`keyUp()`函数的包装，模拟的按下然后松开两个动作。这两个函数可以单独调用。例如，按下`shift`键的同时按3次左方向键：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"#  按下`shift`键\\n\",\n    \"pyautogui.keyDown('shift')\\n\",\n    \"pyautogui.press('left')\\n\",\n    \"pyautogui.press('left')\\n\",\n    \"pyautogui.press('left')\\n\",\n    \"#  松开`shift`键\\n\",\n    \"pyautogui.keyUp('shift')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"和`typewrite()`函数一样，可以用数组把一组键传入`press()`。例如：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.press(['left', 'left', 'left'])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6.3 `hotkey()`函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"为了更高效的输入热键，PyAutoGUI提供了`hotkey()`函数来绑定若干按键：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.hotkey('ctrl', 'shift', 'ese')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"等价于：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.keyDown('ctrl')\\n\",\n    \"pyautogui.keyDown('shift')\\n\",\n    \"pyautogui.keyDown('esc')\\n\",\n    \"pyautogui.keyUp('esc')\\n\",\n    \"pyautogui.keyUp('shift')\\n\",\n    \"pyautogui.keyUp('ctrl')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 6.4 KEYBOARD_KEYS\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"下面就是`press()`，`keyDown()`，`keyUp()`和`hotkey()`函数可以输入的按键名称：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"scrolled\": false\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"['\\\\t', '\\\\n', '\\\\r', ' ', '!', '\\\"', '#', '$', '%', '&', \\\"'\\\", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', '[', '\\\\\\\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace', 'browserback', 'browserfavorites', 'browserforward', 'browserhome', 'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear', 'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete', 'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'f1', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20', 'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja', 'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail', 'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack', 'nonconvert', 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn', 'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn', 'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator', 'shift', 'shiftleft', 'shiftright', 'sleep', 'stop', 'subtract', 'tab', 'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen', 'command', 'option', 'optionleft', 'optionright']\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(pyautogui.KEYBOARD_KEYS)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 7 消息弹窗函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI通过Tkinter实现了4种纯Python的消息弹窗函数，和JavaScript类似。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 7.1 alert()函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'OK'\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.alert(text='', title='', button='OK')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"显示一个简单的带文字和OK按钮的消息弹窗。用户点击后返回`button`的文字。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##  7.2 The confirm() Function\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'0'\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"#  OK和Cancel按钮的消息弹窗\\n\",\n    \"pyautogui.confirm(text='', title='', buttons=['OK', 'Cancel'])\\n\",\n    \"#  10个按键0-9的消息弹窗\\n\",\n    \"pyautogui.confirm(text='', title='', buttons=range(10))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"显示一个简单的带文字、OK和Cancel按钮的消息弹窗，用户点击后返回被点击button的文字，支持自定义数字、文字的列表。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##  7.3 The prompt() Function\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.prompt(text='', title='' , default='')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"可以输入的消息弹窗，带OK和Cancel按钮。用户点击OK按钮返回输入的文字，点击Cancel按钮返回`None`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##  7.4 The password() Function\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.password(text='', title='', default='', mask='*')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"样式同`prompt()`，用于输入密码，消息用`*`表示。带OK和Cancel按钮。用户点击OK按钮返回输入的文字，点击Cancel按钮返回`None`。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 8 截屏函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"PyAutoGUI可以截屏并保存为图片文件，然后定位这些截屏在屏幕上的位置。与[sikuli](http://www.sikuli.org/)类似，把屏幕上的按键截取下来，然后定位，就可以执行点击等操作了。\\n\",\n    \"\\n\",\n    \"截屏功能需要安装Pillow模块。OS X用`screencapture`命令，是系统自带的。Linux用户用`scrot`命令，可以通过`sudo apt-get install scrot`安装。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 8.1 Ubuntu注意事项\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"由于Ubuntu上安装Pillow时缺少PNG和JPEG依赖，所以安装比较复杂，具体可以看[Ubuntu论坛](http://conda.pydata.org/miniconda.html)。不过用[miniconda](http://conda.pydata.org/miniconda.html)可以解决这些问题，如果Ubuntu或Mint上安装了miniconda，可以直接`conda install pillow`来安装。\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 8.2 `screenshot()`函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`screenshot()`函数会返回`Image`对象（参考[Pillow或PIL模块文档](http://python-pillow.github.io/)），也可以设置文件名：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"im1 = pyautogui.screenshot()\\n\",\n    \"im2 = pyautogui.screenshot('my_screenshot.png')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"在一个$1920 \\\\times 1080$的屏幕上，`screenshot()`函数要消耗100微秒——不快也不慢。\\n\",\n    \"\\n\",\n    \"如果你不需要截取整个屏幕，还有一个可选的`region`参数。你可以把截取区域的左上角XY坐标值和宽度、高度传入截取。\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"im = pyautogui.screenshot(region=(0, 0, 300 ,400))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 8.3 定位函数\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"可以定位截图在屏幕上的坐标位置。比如，你需要在计算器里输入：\\n\",\n    \"![](pyautogui/calc.png)\\n\",\n    \"\\n\",\n    \"如果你不知道按钮的位置，就不能用`moveTo()`定位和`click()`点击。而且每次计算器的位置可能会变化，这时即使有来坐标也不好用了。但是如果你有要点击按钮的截图，比如数字`7`：\\n\",\n    \"![](pyautogui/calc7key.png)\\n\",\n    \"\\n\",\n    \"你可以调用`pyautogui.locateOnScreen('calc7key.png')`函数来获得`7`的屏幕坐标。返回的是一个元组`(top, left, width, height)`。这个元组可以用`pyautogui.center()`函数来获取截图屏幕的中心坐标。如果截图没找到，`pyautogui.locateOnScreen()`函数返回`None`：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(1226, 546, 29, 28)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"button7location = pyautogui.locateOnScreen('pyautogui/calc7key.png')\\n\",\n    \"button7location\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(1240, 560)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"button7x, button7y = pyautogui.center(button7location)\\n\",\n    \"button7x, button7y\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"pyautogui.click(button7x, button7y) \"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`locateCenterOnScreen()`等价于上面的前两布操作，直接获得截屏屏幕中心坐标：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"x, y = pyautogui.locateCenterOnScreen('pyautogui/calc7key.png')\\n\",\n    \"pyautogui.click(x, y)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"在$1920 \\\\times 1080$的屏幕上，定位函数需要1~2秒时间。对视频游戏（LOL、DOTA）来说就太慢了，但是上班干活还是绰绰有余。\\n\",\n    \"\\n\",\n    \"还是几个定位函数。都是从左上角原点开始向右向下搜索截图位置：\\n\",\n    \"\\n\",\n    \"- locateOnScreen(image, grayscale=False)：返回找到的第一个截图`Image`对象在屏幕上的坐标`(left, top, width, height)`，如果没找到返回`None`\\n\",\n    \"- locateCenterOnScreen(image, grayscale=False)：返回找到的第一个截图`Image`对象在屏幕上的中心坐标`(x, y)`，如果没找到返回`None`\\n\",\n    \"- locateAllOnScreen(image, grayscale=False)：返回找到的所有相同截图`Image`对象在屏幕上的坐标`(left, top, width, height)`的生成器\\n\",\n    \"- locate(needleImage, haystackImage, grayscale=False)：返回找到的第一个截图`Image`对象在`haystackImage`里面的坐标`(left, top, width, height)`，如果没找到返回`None`\\n\",\n    \"- locateAll(needleImage, haystackImage, grayscale=False)：返回找到的所有相同截图`Image`对象在`haystackImage`里面的坐标`(left, top, width, height)`的生成器\\n\",\n    \"\\n\",\n    \"两个`locateAll*`函数都可以用`for`循环和`list()`输出：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"(1227, 546, 29, 28)\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"for pos in pyautogui.locateAllOnScreen('pyautogui/calc7key.png'):\\n\",\n    \"    print(pos)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[(1227, 546, 29, 28)]\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"list(pyautogui.locateAllOnScreen('pyautogui/calc7key.png'))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 8.3.1 灰度值匹配\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"可以把`grayscale`参数设置为`True`来加速定位（大约提升30%），默认为`False`。这种去色（desaturate）方法可以加速定位，但是也可能导致假阳性（false-positive）匹配：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(1227, 546, 29, 28)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"button7location = pyautogui.locateOnScreen('pyautogui/calc7key.png', grayscale=True)\\n\",\n    \"button7location\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### 8.3.2 像素匹配\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"要获取截屏某个位置的RGB像素值，可以用`Image`对象的`getpixel()`方法：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(255, 255, 255)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import pyautogui\\n\",\n    \"im = pyautogui.screenshot()\\n\",\n    \"im.getpixel((100, 200))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"也可以用PyAutoGUI的`pixel()`函数，是之前调用的包装：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(255, 255, 255)\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixel(100, 200)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"如果你只是要检验一下指定位置的像素值，可以用`pixelMatchesColor()`函数，把X、Y和RGB元组值穿入即可：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixelMatchesColor(100, 200, (255, 255, 255))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixelMatchesColor(100, 200, (255, 255, 245))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"`tolerance`参数可以指定红、绿、蓝3种颜色误差范围：\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixelMatchesColor(100, 200, (255, 255, 245), tolerance=10)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"True\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixelMatchesColor(100, 200, (248, 250, 245), tolerance=10)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"False\"\n      ]\n     },\n     \"execution_count\": null,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pyautogui.pixelMatchesColor(100, 200, (205, 255, 245), tolerance=10)\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.4.3\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 0\n}\n"
  },
  {
    "path": "docs/source/modules.rst",
    "content": "pyautogui\n=========\n\n.. toctree::\n   :maxdepth: 4\n\n   pyautogui\n"
  },
  {
    "path": "docs/source/pyautogui.rst",
    "content": "pyautogui package\n=================\n\nSubmodules\n----------\n\npyautogui.keynames module\n-------------------------\n\n.. automodule:: pyautogui.keynames\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\n\nModule contents\n---------------\n\n.. automodule:: pyautogui\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "docs/tests.rst",
    "content": ".. default-role:: code\n\n=======\nTesting\n=======\n\nThe unit tests for PyAutoGUI are currently not comprehensive. The tests (in basicTests.py) cover the following:\n\n- onScreen()\n- size()\n- position()\n- moveTo()\n- moveRel()\n- typewrite()\n- PAUSE\n\nPlatforms Tested\n================\n\n- Python 3.4, 3.3, 3.2, 3.1, 2.7, 2.6, 2.5\n- Windows\n- OS X\n- Raspberry Pi\n\n(If you have run the unit tests successfully on other platforms, please tell al@inventwithpython.com.)\n\nPyAutoGUI is not compatible with Python 2.4 or before.\n\nThe keyboard functions do not work on Ubuntu when run in VirtualBox on Windows.\n"
  },
  {
    "path": "pyautogui/__init__.py",
    "content": "# PyAutoGUI lets Python control the mouse and keyboard, and other GUI automation tasks. For Windows, macOS, and Linux,\n# on Python 3 and 2.\n# https://github.com/asweigart/pyautogui\n# Al Sweigart al@inventwithpython.com (Send me feedback & suggestions!)\n\n\n# TODO - the following features are half-implemented right now:\n# snapshot logging\n# non-qwerty keyboard mapping\n# primary secondary mouse button awareness\n\n\nfrom __future__ import absolute_import, division, print_function\n\n\n__version__ = \"0.9.54\"\n\nimport collections\nimport sys\nimport time\nimport datetime\nimport os\nimport platform\nimport re\nimport functools\nfrom contextlib import contextmanager\n\n\nclass PyAutoGUIException(Exception):\n    \"\"\"\n    PyAutoGUI code will raise this exception class for any invalid actions. If PyAutoGUI raises some other exception,\n    you should assume that this is caused by a bug in PyAutoGUI itself. (Including a failure to catch potential\n    exceptions raised by PyAutoGUI.)\n    \"\"\"\n\n    pass\n\n\nclass FailSafeException(PyAutoGUIException):\n    \"\"\"\n    This exception is raised by PyAutoGUI functions when the user puts the mouse cursor into one of the \"failsafe\n    points\" (by default, one of the four corners of the primary monitor). This exception shouldn't be caught; it's\n    meant to provide a way to terminate a misbehaving script.\n    \"\"\"\n\n    pass\n\n\nclass ImageNotFoundException(PyAutoGUIException):\n    \"\"\"\n    This exception is the PyAutoGUI version of PyScreeze's `ImageNotFoundException`, which is raised when a locate*()\n    function call is unable to find an image.\n\n    Ideally, `pyscreeze.ImageNotFoundException` should never be raised by PyAutoGUI.\n    \"\"\"\n\n\nif sys.version_info[0] == 2 or sys.version_info[0:2] in ((3, 1), (3, 2)):\n    # Python 2 and 3.1 and 3.2 uses collections.Sequence\n    from collections import Sequence\nelse:\n    # Python 3.3+ uses collections.abc.Sequence\n    from collections.abc import Sequence\n\n\ntry:\n    from pytweening import (\n        easeInQuad,\n        easeOutQuad,\n        easeInOutQuad,\n        easeInCubic,\n        easeOutCubic,\n        easeInOutCubic,\n        easeInQuart,\n        easeOutQuart,\n        easeInOutQuart,\n        easeInQuint,\n        easeOutQuint,\n        easeInOutQuint,\n        easeInSine,\n        easeOutSine,\n        easeInOutSine,\n        easeInExpo,\n        easeOutExpo,\n        easeInOutExpo,\n        easeInCirc,\n        easeOutCirc,\n        easeInOutCirc,\n        easeInElastic,\n        easeOutElastic,\n        easeInOutElastic,\n        easeInBack,\n        easeOutBack,\n        easeInOutBack,\n        easeInBounce,\n        easeOutBounce,\n        easeInOutBounce,\n    )\n\n    # getLine is not needed.\n    # getPointOnLine has been redefined in this file, to avoid dependency on pytweening.\n    # linear has also been redefined in this file.\nexcept ImportError:\n\n    def _couldNotImportPyTweening(*unused_args, **unused_kwargs):\n        \"\"\"\n        This function raises ``PyAutoGUIException``. It's used for the PyTweening function names if the PyTweening\n        module failed to be imported.\n        \"\"\"\n        raise PyAutoGUIException(\n            \"PyAutoGUI was unable to import pytweening. Please install this module to enable the function you tried to call.\"\n        )\n\n    easeInQuad = _couldNotImportPyTweening\n    easeOutQuad = _couldNotImportPyTweening\n    easeInOutQuad = _couldNotImportPyTweening\n    easeInCubic = _couldNotImportPyTweening\n    easeOutCubic = _couldNotImportPyTweening\n    easeInOutCubic = _couldNotImportPyTweening\n    easeInQuart = _couldNotImportPyTweening\n    easeOutQuart = _couldNotImportPyTweening\n    easeInOutQuart = _couldNotImportPyTweening\n    easeInQuint = _couldNotImportPyTweening\n    easeOutQuint = _couldNotImportPyTweening\n    easeInOutQuint = _couldNotImportPyTweening\n    easeInSine = _couldNotImportPyTweening\n    easeOutSine = _couldNotImportPyTweening\n    easeInOutSine = _couldNotImportPyTweening\n    easeInExpo = _couldNotImportPyTweening\n    easeOutExpo = _couldNotImportPyTweening\n    easeInOutExpo = _couldNotImportPyTweening\n    easeInCirc = _couldNotImportPyTweening\n    easeOutCirc = _couldNotImportPyTweening\n    easeInOutCirc = _couldNotImportPyTweening\n    easeInElastic = _couldNotImportPyTweening\n    easeOutElastic = _couldNotImportPyTweening\n    easeInOutElastic = _couldNotImportPyTweening\n    easeInBack = _couldNotImportPyTweening\n    easeOutBack = _couldNotImportPyTweening\n    easeInOutBack = _couldNotImportPyTweening\n    easeInBounce = _couldNotImportPyTweening\n    easeOutBounce = _couldNotImportPyTweening\n    easeInOutBounce = _couldNotImportPyTweening\n\n\ntry:\n    from pymsgbox import alert, confirm, prompt, password\nexcept ImportError:\n    # If pymsgbox module is not found, those methods will not be available.\n    def _couldNotImportPyMsgBox(*unused_args, **unused_kwargs):\n        \"\"\"\n        This function raises ``PyAutoGUIException``. It's used for the PyMsgBox function names if the PyMsgbox module\n        failed to be imported.\n        \"\"\"\n        raise PyAutoGUIException(\n            \"PyAutoGUI was unable to import pymsgbox. Please install this module to enable the function you tried to call.\"\n        )\n\n    alert = confirm = prompt = password = _couldNotImportPyMsgBox\n\n\ndef raisePyAutoGUIImageNotFoundException(wrappedFunction):\n    \"\"\"\n    A decorator that wraps PyScreeze locate*() functions so that the PyAutoGUI user sees them raise PyAutoGUI's\n    ImageNotFoundException rather than PyScreeze's ImageNotFoundException. This is because PyScreeze should be\n    invisible to PyAutoGUI users.\n    \"\"\"\n\n    @functools.wraps(wrappedFunction)\n    def wrapper(*args, **kwargs):\n        try:\n            return wrappedFunction(*args, **kwargs)\n        except pyscreeze.ImageNotFoundException:\n            raise ImageNotFoundException  # Raise PyAutoGUI's ImageNotFoundException.\n\n    return wrapper\n\n\ntry:\n    import pyscreeze\n    from pyscreeze import center, pixel, pixelMatchesColor, screenshot\n\n    # Change the locate*() functions so that they raise PyAutoGUI's ImageNotFoundException instead.\n    @raisePyAutoGUIImageNotFoundException\n    def locate(*args, **kwargs):\n        return pyscreeze.locate(*args, **kwargs)\n\n    locate.__doc__ = pyscreeze.locate.__doc__\n\n    @raisePyAutoGUIImageNotFoundException\n    def locateAll(*args, **kwargs):\n        return pyscreeze.locateAll(*args, **kwargs)\n\n    locateAll.__doc__ = pyscreeze.locateAll.__doc__\n\n    @raisePyAutoGUIImageNotFoundException\n    def locateAllOnScreen(*args, **kwargs):\n        return pyscreeze.locateAllOnScreen(*args, **kwargs)\n\n    locateAllOnScreen.__doc__ = pyscreeze.locateAllOnScreen.__doc__\n\n    @raisePyAutoGUIImageNotFoundException\n    def locateCenterOnScreen(*args, **kwargs):\n        return pyscreeze.locateCenterOnScreen(*args, **kwargs)\n\n    locateCenterOnScreen.__doc__ = pyscreeze.locateCenterOnScreen.__doc__\n\n    @raisePyAutoGUIImageNotFoundException\n    def locateOnScreen(*args, **kwargs):\n        return pyscreeze.locateOnScreen(*args, **kwargs)\n\n    locateOnScreen.__doc__ = pyscreeze.locateOnScreen.__doc__\n\n    @raisePyAutoGUIImageNotFoundException\n    def locateOnWindow(*args, **kwargs):\n        return pyscreeze.locateOnWindow(*args, **kwargs)\n\n    locateOnWindow.__doc__ = pyscreeze.locateOnWindow.__doc__\n\n\nexcept ImportError:\n    # If pyscreeze module is not found, screenshot-related features will simply not work.\n    def _couldNotImportPyScreeze(*unused_args, **unsed_kwargs):\n        \"\"\"\n        This function raises ``PyAutoGUIException``. It's used for the PyScreeze function names if the PyScreeze module\n        failed to be imported.\n        \"\"\"\n        raise PyAutoGUIException(\n            \"PyAutoGUI was unable to import pyscreeze. (This is likely because you're running a version of Python that Pillow (which pyscreeze depends on) doesn't support currently.) Please install this module to enable the function you tried to call.\"\n        )\n\n    center = _couldNotImportPyScreeze\n    #grab = _couldNotImportPyScreeze  # grab() was removed, use screenshot() instead\n    locate = _couldNotImportPyScreeze\n    locateAll = _couldNotImportPyScreeze\n    locateAllOnScreen = _couldNotImportPyScreeze\n    locateCenterOnScreen = _couldNotImportPyScreeze\n    locateOnScreen = _couldNotImportPyScreeze\n    locateOnWindow = _couldNotImportPyScreeze\n    pixel = _couldNotImportPyScreeze\n    pixelMatchesColor = _couldNotImportPyScreeze\n    screenshot = _couldNotImportPyScreeze\n\n\ntry:\n    import mouseinfo\n\n    def mouseInfo():\n        \"\"\"\n        Launches the MouseInfo app. This application provides mouse coordinate information which can be useful when\n        planning GUI automation tasks. This function blocks until the application is closed.\n        \"\"\"\n        mouseinfo.MouseInfoWindow()\n\nexcept ImportError:\n\n    def mouseInfo():\n        \"\"\"\n        This function raises PyAutoGUIException. It's used for the MouseInfo function names if the MouseInfo module\n        failed to be imported.\n        \"\"\"\n        raise PyAutoGUIException(\n            \"PyAutoGUI was unable to import mouseinfo. Please install this module to enable the function you tried to call.\"\n        )\n\n\ndef useImageNotFoundException(value=None):\n    \"\"\"\n    When called with no arguments, PyAutoGUI will raise ImageNotFoundException when the PyScreeze locate*() functions\n    can't find the image it was told to locate. The default behavior is to return None. Call this function with no\n    arguments (or with True as the argument) to have exceptions raised, which is a better practice.\n\n    You can also disable raising exceptions by passing False for the argument.\n    \"\"\"\n    if value is None:\n        value = True\n    # TODO - this will cause a NameError if PyScreeze couldn't be imported:\n    try:\n        pyscreeze.USE_IMAGE_NOT_FOUND_EXCEPTION = value\n    except NameError:\n        raise PyAutoGUIException(\"useImageNotFoundException() ws called but pyscreeze isn't installed.\")\n\n\nif sys.platform == \"win32\":  # PyGetWindow currently only supports Windows.\n    try:\n        from pygetwindow import (\n            Window,\n            getActiveWindow,\n            getActiveWindowTitle,\n            getWindowsAt,\n            getWindowsWithTitle,\n            getAllWindows,\n            getAllTitles,\n        )\n    except ImportError:\n        # If pygetwindow module is not found, those methods will not be available.\n        def _couldNotImportPyGetWindow(*unused_args, **unused_kwargs):\n            \"\"\"\n            This function raises PyAutoGUIException. It's used for the PyGetWindow function names if the PyGetWindow\n            module failed to be imported.\n            \"\"\"\n            raise PyAutoGUIException(\n                \"PyAutoGUI was unable to import pygetwindow. Please install this module to enable the function you tried to call.\"\n            )\n\n        Window = _couldNotImportPyGetWindow\n        getActiveWindow = _couldNotImportPyGetWindow\n        getActiveWindowTitle = _couldNotImportPyGetWindow\n        getWindowsAt = _couldNotImportPyGetWindow\n        getWindowsWithTitle = _couldNotImportPyGetWindow\n        getAllWindows = _couldNotImportPyGetWindow\n        getAllTitles = _couldNotImportPyGetWindow\n\nKEY_NAMES = [\n    \"\\t\",\n    \"\\n\",\n    \"\\r\",\n    \" \",\n    \"!\",\n    '\"',\n    \"#\",\n    \"$\",\n    \"%\",\n    \"&\",\n    \"'\",\n    \"(\",\n    \")\",\n    \"*\",\n    \"+\",\n    \",\",\n    \"-\",\n    \".\",\n    \"/\",\n    \"0\",\n    \"1\",\n    \"2\",\n    \"3\",\n    \"4\",\n    \"5\",\n    \"6\",\n    \"7\",\n    \"8\",\n    \"9\",\n    \":\",\n    \";\",\n    \"<\",\n    \"=\",\n    \">\",\n    \"?\",\n    \"@\",\n    \"[\",\n    \"\\\\\",\n    \"]\",\n    \"^\",\n    \"_\",\n    \"`\",\n    \"a\",\n    \"b\",\n    \"c\",\n    \"d\",\n    \"e\",\n    \"f\",\n    \"g\",\n    \"h\",\n    \"i\",\n    \"j\",\n    \"k\",\n    \"l\",\n    \"m\",\n    \"n\",\n    \"o\",\n    \"p\",\n    \"q\",\n    \"r\",\n    \"s\",\n    \"t\",\n    \"u\",\n    \"v\",\n    \"w\",\n    \"x\",\n    \"y\",\n    \"z\",\n    \"{\",\n    \"|\",\n    \"}\",\n    \"~\",\n    \"accept\",\n    \"add\",\n    \"alt\",\n    \"altleft\",\n    \"altright\",\n    \"apps\",\n    \"backspace\",\n    \"browserback\",\n    \"browserfavorites\",\n    \"browserforward\",\n    \"browserhome\",\n    \"browserrefresh\",\n    \"browsersearch\",\n    \"browserstop\",\n    \"capslock\",\n    \"clear\",\n    \"convert\",\n    \"ctrl\",\n    \"ctrlleft\",\n    \"ctrlright\",\n    \"decimal\",\n    \"del\",\n    \"delete\",\n    \"divide\",\n    \"down\",\n    \"end\",\n    \"enter\",\n    \"esc\",\n    \"escape\",\n    \"execute\",\n    \"f1\",\n    \"f10\",\n    \"f11\",\n    \"f12\",\n    \"f13\",\n    \"f14\",\n    \"f15\",\n    \"f16\",\n    \"f17\",\n    \"f18\",\n    \"f19\",\n    \"f2\",\n    \"f20\",\n    \"f21\",\n    \"f22\",\n    \"f23\",\n    \"f24\",\n    \"f3\",\n    \"f4\",\n    \"f5\",\n    \"f6\",\n    \"f7\",\n    \"f8\",\n    \"f9\",\n    \"final\",\n    \"fn\",\n    \"hanguel\",\n    \"hangul\",\n    \"hanja\",\n    \"help\",\n    \"home\",\n    \"insert\",\n    \"junja\",\n    \"kana\",\n    \"kanji\",\n    \"launchapp1\",\n    \"launchapp2\",\n    \"launchmail\",\n    \"launchmediaselect\",\n    \"left\",\n    \"modechange\",\n    \"multiply\",\n    \"nexttrack\",\n    \"nonconvert\",\n    \"num0\",\n    \"num1\",\n    \"num2\",\n    \"num3\",\n    \"num4\",\n    \"num5\",\n    \"num6\",\n    \"num7\",\n    \"num8\",\n    \"num9\",\n    \"numlock\",\n    \"pagedown\",\n    \"pageup\",\n    \"pause\",\n    \"pgdn\",\n    \"pgup\",\n    \"playpause\",\n    \"prevtrack\",\n    \"print\",\n    \"printscreen\",\n    \"prntscrn\",\n    \"prtsc\",\n    \"prtscr\",\n    \"return\",\n    \"right\",\n    \"scrolllock\",\n    \"select\",\n    \"separator\",\n    \"shift\",\n    \"shiftleft\",\n    \"shiftright\",\n    \"sleep\",\n    \"space\",\n    \"stop\",\n    \"subtract\",\n    \"tab\",\n    \"up\",\n    \"volumedown\",\n    \"volumemute\",\n    \"volumeup\",\n    \"win\",\n    \"winleft\",\n    \"winright\",\n    \"yen\",\n    \"command\",\n    \"option\",\n    \"optionleft\",\n    \"optionright\",\n]\nKEYBOARD_KEYS = KEY_NAMES  # keeping old KEYBOARD_KEYS for backwards compatibility\n\n# Constants for the mouse button names:\nLEFT = \"left\"\nMIDDLE = \"middle\"\nRIGHT = \"right\"\nPRIMARY = \"primary\"\nSECONDARY = \"secondary\"\n\n# Different keyboard mappings:\n# TODO - finish this feature.\n# NOTE: Eventually, I'd like to come up with a better system than this. For now, this seems like it works.\nQWERTY = r\"\"\"`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?\"\"\"\nQWERTZ = r\"\"\"=1234567890/0qwertzuiop89-asdfghjkl,\\yxcvbnm,.7+!@#$%^&*()?)QWERTZUIOP*(_ASDFGHJKL<|YXCVBNM<>&\"\"\"\n\n\ndef isShiftCharacter(character):\n    \"\"\"\n    Returns True if the ``character`` is a keyboard key that would require the shift key to be held down, such as\n    uppercase letters or the symbols on the keyboard's number row.\n    \"\"\"\n    # NOTE TODO - This will be different for non-qwerty keyboards.\n    return character.isupper() or character in set('~!@#$%^&*()_+{}|:\"<>?')\n\n\n# The platformModule is where we reference the platform-specific functions.\nif sys.platform.startswith(\"java\"):\n    # from . import _pyautogui_java as platformModule\n    raise NotImplementedError(\"Jython is not yet supported by PyAutoGUI.\")\nelif sys.platform == \"darwin\":\n    from . import _pyautogui_osx as platformModule\nelif sys.platform == \"win32\":\n    from . import _pyautogui_win as platformModule\nelif platform.system() == \"Linux\":\n    from . import _pyautogui_x11 as platformModule\nelse:\n    raise NotImplementedError(\"Your platform (%s) is not supported by PyAutoGUI.\" % (platform.system()))\n\n# TODO: Having module-wide user-writable global variables is bad. It makes\n# restructuring the code very difficult. For instance, what if we decide to\n# move the mouse-related functions to a separate file (a submodule)? How that\n# file will access this module vars? It will probably lead to a circular\n# import.\n\n# In seconds. Any duration less than this is rounded to 0.0 to instantly move\n# the mouse.\nMINIMUM_DURATION = 0.1\n# If sleep_amount is less than MINIMUM_DURATION, time.sleep() will be a no-op and the mouse cursor moves there instantly.\n# TODO: This value should vary with the platform. http://stackoverflow.com/q/1133857\nMINIMUM_SLEEP = 0.05\n\n# The number of seconds to pause after EVERY public function call. Useful for debugging:\nPAUSE = 0.1  # Tenth-second pause by default.\n\n# Interface need some catch up time on darwin (macOS) systems. Possible values probably differ based on your system performance.\n# This value affects mouse moveTo, dragTo and key event duration.\n# TODO: Find a dynamic way to let the system catch up instead of blocking with a magic number.\nDARWIN_CATCH_UP_TIME = 0.01\n\n# If the mouse is over a coordinate in FAILSAFE_POINTS and FAILSAFE is True, the FailSafeException is raised.\n# The rest of the points are added to the FAILSAFE_POINTS list at the bottom of this file, after size() has been defined.\n# The points are for the corners of the screen, but note that these points don't automatically change if the screen resolution changes.\nFAILSAFE = True\nFAILSAFE_POINTS = [(0, 0)]\n\nLOG_SCREENSHOTS = False  # If True, save screenshots for clicks and key presses.\n\n# If not None, PyAutoGUI deletes old screenshots when this limit has been reached:\nLOG_SCREENSHOTS_LIMIT = 10\nG_LOG_SCREENSHOTS_FILENAMES = []  # TODO - make this a deque\n\nPoint = collections.namedtuple(\"Point\", \"x y\")\nSize = collections.namedtuple(\"Size\", \"width height\")\n\n\ndef _genericPyAutoGUIChecks(wrappedFunction):\n    \"\"\"\n    A decorator that calls failSafeCheck() before the decorated function and\n    _handlePause() after it.\n    \"\"\"\n\n    @functools.wraps(wrappedFunction)\n    def wrapper(*args, **kwargs):\n        failSafeCheck()\n        returnVal = wrappedFunction(*args, **kwargs)\n        _handlePause(kwargs.get(\"_pause\", True))\n        return returnVal\n\n    return wrapper\n\n\n# General Functions\n# =================\n\n\ndef getPointOnLine(x1, y1, x2, y2, n):\n    \"\"\"\n    Returns an (x, y) tuple of the point that has progressed a proportion ``n`` along the line defined by the two\n    ``x1``, ``y1`` and ``x2``, ``y2`` coordinates.\n\n    This function was copied from pytweening module, so that it can be called even if PyTweening is not installed.\n    \"\"\"\n    x = ((x2 - x1) * n) + x1\n    y = ((y2 - y1) * n) + y1\n    return (x, y)\n\n\ndef linear(n):\n    \"\"\"\n    Returns ``n``, where ``n`` is the float argument between ``0.0`` and ``1.0``. This function is for the default\n    linear tween for mouse moving functions.\n\n    This function was copied from PyTweening module, so that it can be called even if PyTweening is not installed.\n    \"\"\"\n\n    # We use this function instead of pytweening.linear for the default tween function just in case pytweening couldn't be imported.\n    if not 0.0 <= n <= 1.0:\n        raise PyAutoGUIException(\"Argument must be between 0.0 and 1.0.\")\n    return n\n\n\ndef _handlePause(_pause):\n    \"\"\"\n    A helper function for performing a pause at the end of a PyAutoGUI function based on some settings.\n\n    If ``_pause`` is ``True``, then sleep for ``PAUSE`` seconds (the global pause setting).\n    \"\"\"\n    if _pause:\n        assert isinstance(PAUSE, int) or isinstance(PAUSE, float)\n        time.sleep(PAUSE)\n\n\ndef _normalizeXYArgs(firstArg, secondArg):\n    \"\"\"\n    Returns a ``Point`` object based on ``firstArg`` and ``secondArg``, which are the first two arguments passed to\n    several PyAutoGUI functions. If ``firstArg`` and ``secondArg`` are both ``None``, returns the current mouse cursor\n    position.\n\n    ``firstArg`` and ``secondArg`` can be integers, a sequence of integers, or a string representing an image filename\n    to find on the screen (and return the center coordinates of).\n    \"\"\"\n    if firstArg is None and secondArg is None:\n        return position()\n\n    elif firstArg is None and secondArg is not None:\n        return Point(int(position()[0]), int(secondArg))\n\n    elif secondArg is None and firstArg is not None and not isinstance(firstArg, Sequence):\n        return Point(int(firstArg), int(position()[1]))\n\n    elif isinstance(firstArg, str):\n        # If x is a string, we assume it's an image filename to locate on the screen:\n        try:\n            location = locateOnScreen(firstArg)\n            # The following code only runs if pyscreeze.USE_IMAGE_NOT_FOUND_EXCEPTION is not set to True, meaning that\n            # locateOnScreen() returns None if the image can't be found.\n            if location is not None:\n                return center(location)\n            else:\n                return None\n        except pyscreeze.ImageNotFoundException:\n            raise ImageNotFoundException\n\n        return center(locateOnScreen(firstArg))\n\n    elif isinstance(firstArg, Sequence):\n        if len(firstArg) == 2:\n            # firstArg is a two-integer tuple: (x, y)\n            if secondArg is None:\n                return Point(int(firstArg[0]), int(firstArg[1]))\n            else:\n                raise PyAutoGUIException(\n                    \"When passing a sequence for firstArg, secondArg must not be passed (received {0}).\".format(\n                        repr(secondArg)\n                    )\n                )\n        elif len(firstArg) == 4:\n            # firstArg is a four-integer tuple, (left, top, width, height), we should return the center point\n            if secondArg is None:\n                return center(firstArg)\n            else:\n                raise PyAutoGUIException(\n                    \"When passing a sequence for firstArg, secondArg must not be passed and default to None (received {0}).\".format(\n                        repr(secondArg)\n                    )\n                )\n        else:\n            raise PyAutoGUIException(\n                \"The supplied sequence must have exactly 2 or exactly 4 elements ({0} were received).\".format(\n                    len(firstArg)\n                )\n            )\n    else:\n        return Point(int(firstArg), int(secondArg))  # firstArg and secondArg are just x and y number values\n\n\ndef _logScreenshot(logScreenshot, funcName, funcArgs, folder=\".\"):\n    \"\"\"\n    A helper function that creates a screenshot to act as a logging mechanism. When a PyAutoGUI function is called,\n    this function is also called to capture the state of the screen when that function was called.\n\n    If ``logScreenshot`` is ``False`` (or None and the ``LOG_SCREENSHOTS`` constant is ``False``), no screenshot is taken.\n\n    The ``funcName`` argument is a string of the calling function's name. It's used in the screenshot's filename.\n\n    The ``funcArgs`` argument is a string describing the arguments passed to the calling function. It's limited to\n    twelve characters to keep it short.\n\n    The ``folder`` argument is the folder to place the screenshot file in, and defaults to the current working directory.\n    \"\"\"\n    if not logScreenshot:\n        return  # Don't take a screenshot.\n    if logScreenshot is None and LOG_SCREENSHOTS is False:\n        return  # Don't take a screenshot.\n\n    # Ensure that the \"specifics\" string isn't too long for the filename:\n    if len(funcArgs) > 12:\n        funcArgs = funcArgs[:12] + \"...\"\n\n    now = datetime.datetime.now()\n    filename = \"%s-%s-%s_%s-%s-%s-%s_%s_%s.png\" % (\n        now.year,\n        str(now.month).rjust(2, \"0\"),\n        str(now.day).rjust(2, \"0\"),\n        now.hour,\n        now.minute,\n        now.second,\n        str(now.microsecond)[:3],\n        funcName,\n        funcArgs,\n    )\n    filepath = os.path.join(folder, filename)\n\n    # Delete the oldest screenshot if we've reached the maximum:\n    if (LOG_SCREENSHOTS_LIMIT is not None) and (len(G_LOG_SCREENSHOTS_FILENAMES) >= LOG_SCREENSHOTS_LIMIT):\n        os.unlink(os.path.join(folder, G_LOG_SCREENSHOTS_FILENAMES[0]))\n        del G_LOG_SCREENSHOTS_FILENAMES[0]\n\n    screenshot(filepath)\n    G_LOG_SCREENSHOTS_FILENAMES.append(filename)\n\n\ndef position(x=None, y=None):\n    \"\"\"\n    Returns the current xy coordinates of the mouse cursor as a two-integer tuple.\n\n    Args:\n      x (int, None, optional) - If not None, this argument overrides the x in\n        the return value.\n      y (int, None, optional) - If not None, this argument overrides the y in\n        the return value.\n\n    Returns:\n      (x, y) tuple of the current xy coordinates of the mouse cursor.\n\n    NOTE: The position() function doesn't check for failsafe.\n    \"\"\"\n    posx, posy = platformModule._position()\n    posx = int(posx)\n    posy = int(posy)\n    if x is not None:  # If set, the x parameter overrides the return value.\n        posx = int(x)\n    if y is not None:  # If set, the y parameter overrides the return value.\n        posy = int(y)\n    return Point(posx, posy)\n\n\ndef size():\n    \"\"\"Returns the width and height of the screen as a two-integer tuple.\n\n    Returns:\n      (width, height) tuple of the screen size, in pixels.\n    \"\"\"\n    return Size(*platformModule._size())\n\n\nresolution = size  # resolution() is an alias for size()\n\n\ndef onScreen(x, y=None):\n    \"\"\"Returns whether the given xy coordinates are on the primary screen or not.\n\n    Note that this function doesn't work for secondary screens.\n\n    Args:\n      Either the arguments are two separate values, first arg for x and second\n        for y, or there is a single argument of a sequence with two values, the\n        first x and the second y.\n        Example: onScreen(x, y) or onScreen([x, y])\n\n    Returns:\n      bool: True if the xy coordinates are on the screen at its current\n        resolution, otherwise False.\n    \"\"\"\n    x, y = _normalizeXYArgs(x, y)\n    x = int(x)\n    y = int(y)\n\n    width, height = platformModule._size()\n    return 0 <= x < width and 0 <= y < height\n\n\n# Mouse Functions\n# ===============\n\n\"\"\"\nNOTE: Although \"mouse1\" and \"mouse2\" buttons usually refer to the left and\nright mouse buttons respectively, in PyAutoGUI 1, 2, and 3 refer to the left,\nmiddle, and right buttons, respectively. This is because Xlib interprets\nbutton 2 as the middle button and button 3 as the right button, so we hold\nthat for Windows and macOS as well (since those operating systems don't use\nbutton numbers but rather just \"left\" or \"right\").\n\"\"\"\n\n\ndef _normalizeButton(button):\n    \"\"\"\n    The left, middle, and right mouse buttons are button numbers 1, 2, and 3 respectively. This is the numbering that\n    Xlib on Linux uses (while Windows and macOS don't care about numbers; they just use \"left\" and \"right\").\n\n    This function takes one of ``LEFT``, ``MIDDLE``, ``RIGHT``, ``PRIMARY``, ``SECONDARY``, ``1``, ``2``, ``3``, ``4``,\n    ``5``, ``6``, or ``7`` for the button argument and returns either ``LEFT``, ``MIDDLE``, ``RIGHT``, ``4``, ``5``,\n    ``6``, or ``7``. The ``PRIMARY``, ``SECONDARY``, ``1``, ``2``, and ``3`` values are never returned.\n\n    The ``'left'`` and ``'right'`` mouse buttons will always refer to the physical left and right\n    buttons on the mouse. The same applies for buttons 1 and 3.\n\n    However, if ``button`` is ``'primary'`` or ``'secondary'``, then we must check if\n    the mouse buttons have been \"swapped\" (for left-handed users) by the operating system's mouse\n    settings.\n\n    If the buttons are swapped, the primary button is the right mouse button and the secondary button is the left mouse\n    button. If not swapped, the primary and secondary buttons are the left and right buttons, respectively.\n\n    NOTE: Swap detection has not been implemented yet.\n    \"\"\"\n    # TODO - The swap detection hasn't been done yet. For Windows, see https://stackoverflow.com/questions/45627956/check-if-mouse-buttons-are-swapped-or-not-in-c\n    # TODO - We should check the OS settings to see if it's a left-hand setup, where button 1 would be \"right\".\n\n    # Check that `button` has a valid value:\n    button = button.lower()\n    if platform.system() == \"Linux\":\n        # Check for valid button arg on Linux:\n        if button not in (LEFT, MIDDLE, RIGHT, PRIMARY, SECONDARY, 1, 2, 3, 4, 5, 6, 7):\n            raise PyAutoGUIException(\n                \"button argument must be one of ('left', 'middle', 'right', 'primary', 'secondary', 1, 2, 3, 4, 5, 6, 7)\"\n            )\n    else:\n        # Check for valid button arg on Windows and macOS:\n        if button not in (LEFT, MIDDLE, RIGHT, PRIMARY, SECONDARY, 1, 2, 3):\n            raise PyAutoGUIException(\n                \"button argument must be one of ('left', 'middle', 'right', 'primary', 'secondary', 1, 2, 3)\"\n            )\n\n    # TODO - Check if the primary/secondary mouse buttons have been swapped:\n    if button in (PRIMARY, SECONDARY):\n        swapped = platformModule._mouse_is_swapped()\n        if swapped:\n            if button == PRIMARY:\n                return RIGHT\n            elif button == SECONDARY:\n                return LEFT\n        else:\n            if button == PRIMARY:\n                return LEFT\n            elif button == SECONDARY:\n                return RIGHT\n\n    # Return a mouse button integer value, not a string like 'left':\n    return {LEFT: LEFT, MIDDLE: MIDDLE, RIGHT: RIGHT, 1: LEFT, 2: MIDDLE, 3: RIGHT, 4: 4, 5: 5, 6: 6, 7: 7}[button]\n\n\n@_genericPyAutoGUIChecks\ndef mouseDown(x=None, y=None, button=PRIMARY, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs pressing a mouse button down (but not up).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        mouse down happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        mouse down happens. None by default.\n      button (str, int, optional): The mouse button pressed down. TODO\n\n    Returns:\n      None\n\n    Raises:\n      PyAutoGUIException: If button is not one of 'left', 'middle', 'right', 1, 2, or 3\n    \"\"\"\n    button = _normalizeButton(button)\n    x, y = _normalizeXYArgs(x, y)\n\n    _mouseMoveDrag(\"move\", x, y, 0, 0, duration=0, tween=None)\n\n    _logScreenshot(logScreenshot, \"mouseDown\", \"%s,%s\" % (x, y), folder=\".\")\n    platformModule._mouseDown(x, y, button)\n\n\n@_genericPyAutoGUIChecks\ndef mouseUp(x=None, y=None, button=PRIMARY, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs releasing a mouse button up (but not down beforehand).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        mouse up happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        mouse up happens. None by default.\n      button (str, int, optional): The mouse button released. TODO\n\n    Returns:\n      None\n\n    Raises:\n      PyAutoGUIException: If button is not one of 'left', 'middle', 'right', 1, 2, or 3\n    \"\"\"\n    button = _normalizeButton(button)\n    x, y = _normalizeXYArgs(x, y)\n\n    _mouseMoveDrag(\"move\", x, y, 0, 0, duration=0, tween=None)\n\n    _logScreenshot(logScreenshot, \"mouseUp\", \"%s,%s\" % (x, y), folder=\".\")\n    platformModule._mouseUp(x, y, button)\n\n\n@_genericPyAutoGUIChecks\ndef click(\n    x=None, y=None, clicks=1, interval=0.0, button=PRIMARY, duration=0.0, tween=linear, logScreenshot=None, _pause=True\n):\n    \"\"\"\n    Performs pressing a mouse button down and then immediately releasing it. Returns ``None``.\n\n    When no arguments are passed, the primary mouse button is clicked at the mouse cursor's current location.\n\n    If integers for ``x`` and ``y`` are passed, the click will happen at that XY coordinate. If ``x`` is a string, the\n    string is an image filename that PyAutoGUI will attempt to locate on the screen and click the center of. If ``x``\n    is a sequence of two coordinates, those coordinates will be used for the XY coordinate to click on.\n\n    The ``clicks`` argument is an int of how many clicks to make, and defaults to ``1``.\n\n    The ``interval`` argument is an int or float of how many seconds to wait in between each click, if ``clicks`` is\n    greater than ``1``. It defaults to ``0.0`` for no pause in between clicks.\n\n    The ``button`` argument is one of the constants ``LEFT``, ``MIDDLE``, ``RIGHT``, ``PRIMARY``, or ``SECONDARY``.\n    It defaults to ``PRIMARY`` (which is the left mouse button, unless the operating system has been set for\n    left-handed users.)\n\n    If ``x`` and ``y`` are specified, and the click is not happening at the mouse cursor's current location, then\n    the ``duration`` argument is an int or float of how many seconds it should take to move the mouse to the XY\n    coordinates. It defaults to ``0`` for an instant move.\n\n    If ``x`` and ``y`` are specified and ``duration`` is not ``0``, the ``tween`` argument is a tweening function\n    that specifies the movement pattern of the mouse cursor as it moves to the XY coordinates. The default is a\n    simple linear tween. See the PyTweening module documentation for more details.\n\n    The ``pause`` parameter is deprecated. Call the ``pyautogui.sleep()`` function to implement a pause.\n\n    Raises:\n      PyAutoGUIException: If button is not one of 'left', 'middle', 'right', 1, 2, 3\n    \"\"\"\n    # TODO: I'm leaving buttons 4, 5, 6, and 7 undocumented for now. I need to understand how they work.\n    button = _normalizeButton(button)\n    x, y = _normalizeXYArgs(x, y)\n\n    # Move the mouse cursor to the x, y coordinate:\n    _mouseMoveDrag(\"move\", x, y, 0, 0, duration, tween)\n\n    _logScreenshot(logScreenshot, \"click\", \"%s,%s,%s,%s\" % (button, clicks, x, y), folder=\".\")\n\n    if sys.platform == 'darwin':\n        for i in range(clicks):\n            failSafeCheck()\n            if button in (LEFT, MIDDLE, RIGHT):\n                platformModule._multiClick(x, y, button, 1, interval)\n    else:\n        for i in range(clicks):\n            failSafeCheck()\n            if button in (LEFT, MIDDLE, RIGHT):\n                platformModule._click(x, y, button)\n\n            time.sleep(interval)\n\n\n@_genericPyAutoGUIChecks\ndef leftClick(x=None, y=None, interval=0.0, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs a left mouse button click.\n\n    This is a wrapper function for click('left', x, y).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n      interval (float, optional): The number of seconds in between each click,\n        if the number of clicks is greater than 1. 0.0 by default, for no\n        pause in between clicks.\n\n    Returns:\n      None\n    \"\"\"\n\n    # TODO - Do we need the decorator for this function? Should click() handle this? (Also applies to other alias functions.)\n    click(x, y, 1, interval, LEFT, duration, tween, logScreenshot, _pause=_pause)\n\n\n@_genericPyAutoGUIChecks\ndef rightClick(x=None, y=None, interval=0.0, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs a right mouse button click.\n\n    This is a wrapper function for click('right', x, y).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n      interval (float, optional): The number of seconds in between each click,\n        if the number of clicks is greater than 1. 0.0 by default, for no\n        pause in between clicks.\n\n    Returns:\n      None\n    \"\"\"\n    click(x, y, 1, interval, RIGHT, duration, tween, logScreenshot, _pause=_pause)\n\n\n@_genericPyAutoGUIChecks\ndef middleClick(x=None, y=None, interval=0.0, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs a middle mouse button click.\n\n    This is a wrapper function for click('middle', x, y).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n\n    Returns:\n      None\n    \"\"\"\n    click(x, y, 1, interval, MIDDLE, duration, tween, logScreenshot, _pause=_pause)\n\n\n@_genericPyAutoGUIChecks\ndef doubleClick(x=None, y=None, interval=0.0, button=LEFT, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs a double click.\n\n    This is a wrapper function for click('left', x, y, 2, interval).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n      interval (float, optional): The number of seconds in between each click,\n        if the number of clicks is greater than 1. 0.0 by default, for no\n        pause in between clicks.\n      button (str, int, optional): The mouse button released. TODO\n\n    Returns:\n      None\n\n    Raises:\n      PyAutoGUIException: If button is not one of 'left', 'middle', 'right', 1, 2, 3, 4,\n        5, 6, or 7\n    \"\"\"\n\n    # Multiple clicks work different in OSX\n    if sys.platform == \"darwin\":\n        x, y = _normalizeXYArgs(x, y)\n        _mouseMoveDrag(\"move\", x, y, 0, 0, duration=0, tween=None)\n        x, y = platformModule._position()\n        platformModule._multiClick(x, y, button, 2)\n        _logScreenshot(logScreenshot, 'click', '%s,%s,%s,2' % (x, y, button), folder='.')\n    else:\n        # Click for Windows or Linux:\n        click(x, y, 2, interval, button, duration, tween, logScreenshot, _pause=False)\n\n\n@_genericPyAutoGUIChecks\ndef tripleClick(x=None, y=None, interval=0.0, button=LEFT, duration=0.0, tween=linear, logScreenshot=None, _pause=True):\n    \"\"\"Performs a triple click.\n\n    This is a wrapper function for click('left', x, y, 3, interval).\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n      interval (float, optional): The number of seconds in between each click,\n        if the number of clicks is greater than 1. 0.0 by default, for no\n        pause in between clicks.\n      button (str, int, optional): The mouse button released. TODO\n\n    Returns:\n      None\n\n    Raises:\n      PyAutoGUIException: If button is not one of 'left', 'middle', 'right', 1, 2, 3, 4,\n        5, 6, or 7\n    \"\"\"\n    # Multiple clicks work different in OSX\n    if sys.platform == \"darwin\":\n        x, y = _normalizeXYArgs(x, y)\n        _mouseMoveDrag(\"move\", x, y, 0, 0, duration=0, tween=None)\n        x, y = platformModule._position()\n        _logScreenshot(logScreenshot, \"click\", \"%s,%s,%s,3\" % (x, y, button), folder=\".\")\n        platformModule._multiClick(x, y, button, 3)\n    else:\n        # Click for Windows or Linux:\n        click(x, y, 3, interval, button, duration, tween, logScreenshot, _pause=False)\n\n\n@_genericPyAutoGUIChecks\ndef scroll(clicks, x=None, y=None, logScreenshot=None, _pause=True):\n    \"\"\"Performs a scroll of the mouse scroll wheel.\n\n    Whether this is a vertical or horizontal scroll depends on the underlying\n    operating system.\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      clicks (int, float): The amount of scrolling to perform.\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n\n    Returns:\n      None\n    \"\"\"\n    if type(x) in (tuple, list):\n        x, y = x[0], x[1]\n    x, y = position(x, y)\n\n    _logScreenshot(logScreenshot, \"scroll\", \"%s,%s,%s\" % (clicks, x, y), folder=\".\")\n    platformModule._scroll(clicks, x, y)\n\n\n@_genericPyAutoGUIChecks\ndef hscroll(clicks, x=None, y=None, logScreenshot=None, _pause=True):\n    \"\"\"Performs an explicitly horizontal scroll of the mouse scroll wheel,\n    if this is supported by the operating system. (Currently just Linux.)\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      clicks (int, float): The amount of scrolling to perform.\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n\n    Returns:\n      None\n    \"\"\"\n    if type(x) in (tuple, list):\n        x, y = x[0], x[1]\n    x, y = position(x, y)\n\n    _logScreenshot(logScreenshot, \"hscroll\", \"%s,%s,%s\" % (clicks, x, y), folder=\".\")\n    platformModule._hscroll(clicks, x, y)\n\n\n@_genericPyAutoGUIChecks\ndef vscroll(clicks, x=None, y=None, logScreenshot=None, _pause=True):\n    \"\"\"Performs an explicitly vertical scroll of the mouse scroll wheel,\n    if this is supported by the operating system. (Currently just Linux.)\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      clicks (int, float): The amount of scrolling to perform.\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n\n    Returns:\n      None\n    \"\"\"\n    if type(x) in (tuple, list):\n        x, y = x[0], x[1]\n    x, y = position(x, y)\n\n    _logScreenshot(logScreenshot, \"vscroll\", \"%s,%s,%s\" % (clicks, x, y), folder=\".\")\n    platformModule._vscroll(clicks, x, y)\n\n\n@_genericPyAutoGUIChecks\ndef moveTo(x=None, y=None, duration=0.0, tween=linear, logScreenshot=False, _pause=True):\n    \"\"\"Moves the mouse cursor to a point on the screen.\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): The x position on the screen where the\n        click happens. None by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): The y position on the screen where the\n        click happens. None by default.\n      duration (float, optional): The amount of time it takes to move the mouse\n        cursor to the xy coordinates. If 0, then the mouse cursor is moved\n        instantaneously. 0.0 by default.\n      tween (func, optional): The tweening function used if the duration is not\n        0. A linear tween is used by default.\n\n    Returns:\n      None\n    \"\"\"\n    x, y = _normalizeXYArgs(x, y)\n\n    _logScreenshot(logScreenshot, \"moveTo\", \"%s,%s\" % (x, y), folder=\".\")\n    _mouseMoveDrag(\"move\", x, y, 0, 0, duration, tween)\n\n\n@_genericPyAutoGUIChecks\ndef moveRel(xOffset=None, yOffset=None, duration=0.0, tween=linear, logScreenshot=False, _pause=True):\n    \"\"\"Moves the mouse cursor to a point on the screen, relative to its current\n    position.\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): How far left (for negative values) or\n        right (for positive values) to move the cursor. 0 by default. If tuple, this is used for x and y.\n      y (int, float, None, optional): How far up (for negative values) or\n        down (for positive values) to move the cursor. 0 by default.\n      duration (float, optional): The amount of time it takes to move the mouse\n        cursor to the new xy coordinates. If 0, then the mouse cursor is moved\n        instantaneously. 0.0 by default.\n      tween (func, optional): The tweening function used if the duration is not\n        0. A linear tween is used by default.\n\n    Returns:\n      None\n    \"\"\"\n    xOffset, yOffset = _normalizeXYArgs(xOffset, yOffset)\n\n    _logScreenshot(logScreenshot, \"moveRel\", \"%s,%s\" % (xOffset, yOffset), folder=\".\")\n    _mouseMoveDrag(\"move\", None, None, xOffset, yOffset, duration, tween)\n\n\nmove = moveRel  # For PyAutoGUI 1.0, move() replaces moveRel().\n\n\n@_genericPyAutoGUIChecks\ndef dragTo(\n    x=None, y=None, duration=0.0, tween=linear, button=PRIMARY, logScreenshot=None, _pause=True, mouseDownUp=True\n):\n    \"\"\"Performs a mouse drag (mouse movement while a button is held down) to a\n    point on the screen.\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): How far left (for negative values) or\n        right (for positive values) to move the cursor. 0 by default. If tuple, this is used for x and y.\n        If x is a str, it's considered a filename of an image to find on\n        the screen with locateOnScreen() and click the center of.\n      y (int, float, None, optional): How far up (for negative values) or\n        down (for positive values) to move the cursor. 0 by default.\n      duration (float, optional): The amount of time it takes to move the mouse\n        cursor to the new xy coordinates. If 0, then the mouse cursor is moved\n        instantaneously. 0.0 by default.\n      tween (func, optional): The tweening function used if the duration is not\n        0. A linear tween is used by default.\n      button (str, int, optional): The mouse button released. TODO\n      mouseDownUp (True, False): When true, the mouseUp/Down actions are not performed.\n        Which allows dragging over multiple (small) actions. 'True' by default.\n\n    Returns:\n      None\n    \"\"\"\n    x, y = _normalizeXYArgs(x, y)\n\n    _logScreenshot(logScreenshot, \"dragTo\", \"%s,%s\" % (x, y), folder=\".\")\n    if mouseDownUp:\n        mouseDown(button=button, logScreenshot=False, _pause=False)\n    _mouseMoveDrag(\"drag\", x, y, 0, 0, duration, tween, button)\n    if mouseDownUp:\n        mouseUp(button=button, logScreenshot=False, _pause=False)\n\n\n@_genericPyAutoGUIChecks\ndef dragRel(\n    xOffset=0, yOffset=0, duration=0.0, tween=linear, button=PRIMARY, logScreenshot=None, _pause=True, mouseDownUp=True\n):\n    \"\"\"Performs a mouse drag (mouse movement while a button is held down) to a\n    point on the screen, relative to its current position.\n\n    The x and y parameters detail where the mouse event happens. If None, the\n    current mouse position is used. If a float value, it is rounded down. If\n    outside the boundaries of the screen, the event happens at edge of the\n    screen.\n\n    Args:\n      x (int, float, None, tuple, optional): How far left (for negative values) or\n        right (for positive values) to move the cursor. 0 by default. If tuple, this is used for xOffset and yOffset.\n      y (int, float, None, optional): How far up (for negative values) or\n        down (for positive values) to move the cursor. 0 by default.\n      duration (float, optional): The amount of time it takes to move the mouse\n        cursor to the new xy coordinates. If 0, then the mouse cursor is moved\n        instantaneously. 0.0 by default.\n      tween (func, optional): The tweening function used if the duration is not\n        0. A linear tween is used by default.\n      button (str, int, optional): The mouse button released. TODO\n      mouseDownUp (True, False): When true, the mouseUp/Down actions are not performed.\n        Which allows dragging over multiple (small) actions. 'True' by default.\n\n    Returns:\n      None\n    \"\"\"\n    if xOffset is None:\n        xOffset = 0\n    if yOffset is None:\n        yOffset = 0\n\n    if type(xOffset) in (tuple, list):\n        xOffset, yOffset = xOffset[0], xOffset[1]\n\n    if xOffset == 0 and yOffset == 0:\n        return  # no-op case\n\n    mousex, mousey = platformModule._position()\n    _logScreenshot(logScreenshot, \"dragRel\", \"%s,%s\" % (xOffset, yOffset), folder=\".\")\n    if mouseDownUp:\n        mouseDown(button=button, logScreenshot=False, _pause=False)\n    _mouseMoveDrag(\"drag\", mousex, mousey, xOffset, yOffset, duration, tween, button)\n    if mouseDownUp:\n        mouseUp(button=button, logScreenshot=False, _pause=False)\n\n\ndrag = dragRel  # For PyAutoGUI 1.0, we want drag() to replace dragRel().\n\n\ndef _mouseMoveDrag(moveOrDrag, x, y, xOffset, yOffset, duration, tween=linear, button=None):\n    \"\"\"Handles the actual move or drag event, since different platforms\n    implement them differently.\n\n    On Windows & Linux, a drag is a normal mouse move while a mouse button is\n    held down. On OS X, a distinct \"drag\" event must be used instead.\n\n    The code for moving and dragging the mouse is similar, so this function\n    handles both. Users should call the moveTo() or dragTo() functions instead\n    of calling _mouseMoveDrag().\n\n    Args:\n      moveOrDrag (str): Either 'move' or 'drag', for the type of action this is.\n      x (int, float, None, optional): How far left (for negative values) or\n        right (for positive values) to move the cursor. 0 by default.\n      y (int, float, None, optional): How far up (for negative values) or\n        down (for positive values) to move the cursor. 0 by default.\n      xOffset (int, float, None, optional): How far left (for negative values) or\n        right (for positive values) to move the cursor. 0 by default.\n      yOffset (int, float, None, optional): How far up (for negative values) or\n        down (for positive values) to move the cursor. 0 by default.\n      duration (float, optional): The amount of time it takes to move the mouse\n        cursor to the new xy coordinates. If 0, then the mouse cursor is moved\n        instantaneously. 0.0 by default.\n      tween (func, optional): The tweening function used if the duration is not\n        0. A linear tween is used by default.\n      button (str, int, optional): The mouse button released. TODO\n\n    Returns:\n      None\n    \"\"\"\n\n    # The move and drag code is similar, but OS X requires a special drag event instead of just a move event when dragging.\n    # See https://stackoverflow.com/a/2696107/1893164\n    assert moveOrDrag in (\"move\", \"drag\"), \"moveOrDrag must be in ('move', 'drag'), not %s\" % (moveOrDrag)\n\n    if sys.platform != \"darwin\":\n        moveOrDrag = \"move\"  # Only OS X needs the drag event specifically.\n\n    xOffset = int(xOffset) if xOffset is not None else 0\n    yOffset = int(yOffset) if yOffset is not None else 0\n\n    if x is None and y is None and xOffset == 0 and yOffset == 0:\n        return  # Special case for no mouse movement at all.\n\n    startx, starty = position()\n\n    x = int(x) if x is not None else startx\n    y = int(y) if y is not None else starty\n\n    # x, y, xOffset, yOffset are now int.\n    x += xOffset\n    y += yOffset\n\n    width, height = size()\n\n    # Make sure x and y are within the screen bounds.\n    # x = max(0, min(x, width - 1))\n    # y = max(0, min(y, height - 1))\n\n    # If the duration is small enough, just move the cursor there instantly.\n    steps = [(x, y)]\n\n    if duration > MINIMUM_DURATION:\n        # Non-instant moving/dragging involves tweening:\n        num_steps = max(width, height)\n        sleep_amount = duration / num_steps\n        if sleep_amount < MINIMUM_SLEEP:\n            num_steps = int(duration / MINIMUM_SLEEP)\n            sleep_amount = duration / num_steps\n\n        steps = [getPointOnLine(startx, starty, x, y, tween(n / num_steps)) for n in range(num_steps)]\n        # Making sure the last position is the actual destination.\n        steps.append((x, y))\n\n    for tweenX, tweenY in steps:\n        if len(steps) > 1:\n            # A single step does not require tweening.\n            time.sleep(sleep_amount)\n\n        tweenX = int(round(tweenX))\n        tweenY = int(round(tweenY))\n\n        # Do a fail-safe check to see if the user moved the mouse to a fail-safe position, but not if the mouse cursor\n        # moved there as a result of this function. (Just because tweenX and tweenY aren't in a fail-safe position\n        # doesn't mean the user couldn't have moved the mouse cursor to a fail-safe position.)\n        if (tweenX, tweenY) not in FAILSAFE_POINTS:\n            failSafeCheck()\n\n        if moveOrDrag == \"move\":\n            platformModule._moveTo(tweenX, tweenY)\n        elif moveOrDrag == \"drag\":\n            platformModule._dragTo(tweenX, tweenY, button)\n        else:\n            raise NotImplementedError(\"Unknown value of moveOrDrag: {0}\".format(moveOrDrag))\n\n    if (tweenX, tweenY) not in FAILSAFE_POINTS:\n        failSafeCheck()\n\n\n# Keyboard Functions\n# ==================\n\n\ndef isValidKey(key):\n    \"\"\"Returns a Boolean value if the given key is a valid value to pass to\n    PyAutoGUI's keyboard-related functions for the current platform.\n\n    This function is here because passing an invalid value to the PyAutoGUI\n    keyboard functions currently is a no-op that does not raise an exception.\n\n    Some keys are only valid on some platforms. For example, while 'esc' is\n    valid for the Escape key on all platforms, 'browserback' is only used on\n    Windows operating systems.\n\n    Args:\n      key (str): The key value.\n\n    Returns:\n      bool: True if key is a valid value, False if not.\n    \"\"\"\n    return platformModule.keyboardMapping.get(key, None) is not None\n\n\n@_genericPyAutoGUIChecks\ndef keyDown(key, logScreenshot=None, _pause=True):\n    \"\"\"Performs a keyboard key press without the release. This will put that\n    key in a held down state.\n\n    NOTE: For some reason, this does not seem to cause key repeats like would\n    happen if a keyboard key was held down on a text field.\n\n    Args:\n      key (str): The key to be pressed down. The valid names are listed in\n      KEYBOARD_KEYS.\n\n    Returns:\n      None\n    \"\"\"\n    if len(key) > 1:\n        key = key.lower()\n\n    _logScreenshot(logScreenshot, \"keyDown\", key, folder=\".\")\n    platformModule._keyDown(key)\n\n\n@_genericPyAutoGUIChecks\ndef keyUp(key, logScreenshot=None, _pause=True):\n    \"\"\"Performs a keyboard key release (without the press down beforehand).\n\n    Args:\n      key (str): The key to be released up. The valid names are listed in\n      KEYBOARD_KEYS.\n\n    Returns:\n      None\n    \"\"\"\n    if len(key) > 1:\n        key = key.lower()\n\n    _logScreenshot(logScreenshot, \"keyUp\", key, folder=\".\")\n    platformModule._keyUp(key)\n\n\n@_genericPyAutoGUIChecks\ndef press(keys, presses=1, interval=0.0, logScreenshot=None, _pause=True):\n    \"\"\"Performs a keyboard key press down, followed by a release.\n\n    Args:\n      key (str, list): The key to be pressed. The valid names are listed in\n      KEYBOARD_KEYS. Can also be a list of such strings.\n      presses (integer, optional): The number of press repetitions.\n      1 by default, for just one press.\n      interval (float, optional): How many seconds between each press.\n      0.0 by default, for no pause between presses.\n      pause (float, optional): How many seconds in the end of function process.\n      None by default, for no pause in the end of function process.\n    Returns:\n      None\n    \"\"\"\n    if type(keys) == str:\n        if len(keys) > 1:\n            keys = keys.lower()\n        keys = [keys]  # If keys is 'enter', convert it to ['enter'].\n    else:\n        lowerKeys = []\n        for s in keys:\n            if len(s) > 1:\n                lowerKeys.append(s.lower())\n            else:\n                lowerKeys.append(s)\n        keys = lowerKeys\n    interval = float(interval)\n    _logScreenshot(logScreenshot, \"press\", \",\".join(keys), folder=\".\")\n    for i in range(presses):\n        for k in keys:\n            failSafeCheck()\n            platformModule._keyDown(k)\n            platformModule._keyUp(k)\n        time.sleep(interval)\n\n\n@contextmanager\n@_genericPyAutoGUIChecks\ndef hold(keys, logScreenshot=None, _pause=True):\n    \"\"\"Context manager that performs a keyboard key press down upon entry,\n    followed by a release upon exit.\n\n    Args:\n      key (str, list): The key to be pressed. The valid names are listed in\n      KEYBOARD_KEYS. Can also be a list of such strings.\n      pause (float, optional): How many seconds in the end of function process.\n      None by default, for no pause in the end of function process.\n    Returns:\n      None\n    \"\"\"\n    if type(keys) == str:\n        if len(keys) > 1:\n            keys = keys.lower()\n        keys = [keys]  # If keys is 'enter', convert it to ['enter'].\n    else:\n        lowerKeys = []\n        for s in keys:\n            if len(s) > 1:\n                lowerKeys.append(s.lower())\n            else:\n                lowerKeys.append(s)\n        keys = lowerKeys\n    _logScreenshot(logScreenshot, \"press\", \",\".join(keys), folder=\".\")\n    for k in keys:\n        failSafeCheck()\n        platformModule._keyDown(k)\n    try:\n        yield\n    finally:\n        for k in keys:\n            failSafeCheck()\n            platformModule._keyUp(k)\n\n\n@_genericPyAutoGUIChecks\ndef typewrite(message, interval=0.0, logScreenshot=None, _pause=True):\n    \"\"\"Performs a keyboard key press down, followed by a release, for each of\n    the characters in message.\n\n    The message argument can also be list of strings, in which case any valid\n    keyboard name can be used.\n\n    Since this performs a sequence of keyboard presses and does not hold down\n    keys, it cannot be used to perform keyboard shortcuts. Use the hotkey()\n    function for that.\n\n    Args:\n      message (str, list): If a string, then the characters to be pressed. If a\n        list, then the key names of the keys to press in order. The valid names\n        are listed in KEYBOARD_KEYS.\n      interval (float, optional): The number of seconds in between each press.\n        0.0 by default, for no pause in between presses.\n\n    Returns:\n      None\n    \"\"\"\n    interval = float(interval)  # TODO - this should be taken out.\n\n    _logScreenshot(logScreenshot, \"write\", message, folder=\".\")\n    for c in message:\n        if len(c) > 1:\n            c = c.lower()\n        press(c, _pause=False)\n        time.sleep(interval)\n        failSafeCheck()\n\n\nwrite = typewrite  # In PyAutoGUI 1.0, write() replaces typewrite().\n\n\n@_genericPyAutoGUIChecks\ndef hotkey(*args, **kwargs):\n    \"\"\"Performs key down presses on the arguments passed in order, then performs\n    key releases in reverse order.\n\n    The effect is that calling hotkey('ctrl', 'shift', 'c') would perform a\n    \"Ctrl-Shift-C\" hotkey/keyboard shortcut press.\n\n    Args:\n      key(s) (str): The series of keys to press, in order. This can also be a\n        list of key strings to press.\n      interval (float, optional): The number of seconds in between each press.\n        0.0 by default, for no pause in between presses.\n\n    Returns:\n      None\n    \"\"\"\n    interval = float(kwargs.get(\"interval\", 0.0))  # TODO - this should be taken out.\n\n    if len(args) and isinstance(args[0], Sequence) and not isinstance(args[0], str):\n        # Let the user pass a list of strings\n        args = tuple(args[0])\n\n    _logScreenshot(kwargs.get(\"logScreenshot\"), \"hotkey\", \",\".join(args), folder=\".\")\n    for c in args:\n        if len(c) > 1:\n            c = c.lower()\n        platformModule._keyDown(c)\n        time.sleep(interval)\n    for c in reversed(args):\n        if len(c) > 1:\n            c = c.lower()\n        platformModule._keyUp(c)\n        time.sleep(interval)\n\n\nshortcut = hotkey  # shortcut() is an alias for htotkey()\n\n\ndef failSafeCheck():\n    if FAILSAFE and tuple(position()) in FAILSAFE_POINTS:\n        raise FailSafeException(\n            \"PyAutoGUI fail-safe triggered from mouse moving to a corner of the screen. To disable this fail-safe, set pyautogui.FAILSAFE to False. DISABLING FAIL-SAFE IS NOT RECOMMENDED.\"\n        )\n\n\ndef displayMousePosition(xOffset=0, yOffset=0):\n    \"\"\"This function is meant to be run from the command line. It will\n    automatically display the location and RGB of the mouse cursor.\"\"\"\n    try:\n        runningIDLE = sys.stdin.__module__.startswith(\"idlelib\")\n    except AttributeError:\n        runningIDLE = False\n\n    print(\"Press Ctrl-C to quit.\")\n    if xOffset != 0 or yOffset != 0:\n        print(\"xOffset: %s yOffset: %s\" % (xOffset, yOffset))\n    try:\n        while True:\n            # Get and print the mouse coordinates.\n            x, y = position()\n            positionStr = \"X: \" + str(x - xOffset).rjust(4) + \" Y: \" + str(y - yOffset).rjust(4)\n            if not onScreen(x - xOffset, y - yOffset) or sys.platform == \"darwin\":\n                # Pixel color can only be found for the primary monitor, and also not on mac due to the screenshot having the mouse cursor in the way.\n                pixelColor = (\"NaN\", \"NaN\", \"NaN\")\n            else:\n                pixelColor = pyscreeze.screenshot().getpixel(\n                    (x, y)\n                )  # NOTE: On Windows & Linux, getpixel() returns a 3-integer tuple, but on macOS it returns a 4-integer tuple.\n            positionStr += \" RGB: (\" + str(pixelColor[0]).rjust(3)\n            positionStr += \", \" + str(pixelColor[1]).rjust(3)\n            positionStr += \", \" + str(pixelColor[2]).rjust(3) + \")\"\n            sys.stdout.write(positionStr)\n            if not runningIDLE:\n                # If this is a terminal, than we can erase the text by printing \\b backspaces.\n                sys.stdout.write(\"\\b\" * len(positionStr))\n            else:\n                # If this isn't a terminal (i.e. IDLE) then we can only append more text. Print a newline instead and pause a second (so we don't send too much output).\n                sys.stdout.write(\"\\n\")\n                time.sleep(1)\n            sys.stdout.flush()\n    except KeyboardInterrupt:\n        sys.stdout.write(\"\\n\")\n        sys.stdout.flush()\n\n\ndef _snapshot(tag, folder=None, region=None, radius=None):\n    # TODO feature not finished\n    if region is not None and radius is not None:\n        raise Exception(\"Either region or radius arguments (or neither) can be passed to snapshot, but not both\")\n\n    if radius is not None:\n        x, y = platformModule._position()\n\n    if folder is None:\n        folder = os.getcwd()\n\n    now = datetime.datetime.now()\n    filename = \"%s-%s-%s_%s-%s-%s-%s_%s.png\" % (\n        now.year,\n        str(now.month).rjust(2, \"0\"),\n        str(now.day).rjust(2, \"0\"),\n        now.hour,\n        now.minute,\n        now.second,\n        str(now.microsecond)[:3],\n        tag,\n    )\n    filepath = os.path.join(folder, filename)\n    screenshot(filepath)\n\n\ndef sleep(seconds):\n    time.sleep(seconds)\n\n\ndef countdown(seconds):\n    for i in range(seconds, 0, -1):\n        print(str(i), end=\" \", flush=True)\n        time.sleep(1)\n    print()\n\n\ndef _getNumberToken(commandStr):\n    \"\"\"Gets the number token at the start of commandStr.\n\n    Given '5hello' returns '5'\n    Given '  5hello' returns '  5'\n    Given '-42hello' returns '-42'\n    Given '+42hello' returns '+42'\n    Given '3.14hello' returns '3.14'\n\n    Raises an exception if it can't tokenize a number.\n    \"\"\"\n    pattern = re.compile(r\"^(\\s*(\\+|\\-)?\\d+(\\.\\d+)?)\")\n    mo = pattern.search(commandStr)\n    if mo is None:\n        raise PyAutoGUIException(\"Invalid command at index 0: a number was expected\")\n\n    return mo.group(1)\n\n\ndef _getQuotedStringToken(commandStr):\n    \"\"\"Gets the quoted string token at the start of commandStr.\n    The quoted string must use single quotes.\n\n    Given \"'hello'world\" returns \"'hello'\"\n    Given \"  'hello'world\" returns \"  'hello'\"\n\n    Raises an exception if it can't tokenize a quoted string.\n    \"\"\"\n    pattern = re.compile(r\"^((\\s*)('(.*?)'))\")\n    mo = pattern.search(commandStr)\n    if mo is None:\n        raise PyAutoGUIException(\"Invalid command at index 0: a quoted string was expected\")\n\n    return mo.group(1)\n\n\ndef _getParensCommandStrToken(commandStr):\n    \"\"\"Gets the command string token at the start of commandStr. It will also\n    be enclosed with parentheses.\n\n    Given \"(ccc)world\" returns \"(ccc)\"\n    Given \"  (ccc)world\" returns \"  (ccc)\"\n    Given \"(ccf10(r))world\" returns \"(ccf10(r))\"\n\n    Raises an exception if it can't tokenize a quoted string.\n    \"\"\"\n\n    # Check to make sure at least one open parenthesis exists:\n    pattern = re.compile(r\"^\\s*\\(\")\n    mo = pattern.search(commandStr)\n    if mo is None:\n        raise PyAutoGUIException(\"Invalid command at index 0: No open parenthesis found.\")\n\n    # Check to make sure the parentheses are balanced:\n    i = 0\n    openParensCount = 0\n    while i < len(commandStr):\n        if commandStr[i] == \"(\":\n            openParensCount += 1\n        elif commandStr[i] == \")\":\n            openParensCount -= 1\n            if openParensCount == 0:\n                i += 1  # Remember to increment i past the ) before breaking.\n                break\n            elif openParensCount == -1:\n                raise PyAutoGUIException(\"Invalid command at index 0: No open parenthesis for this close parenthesis.\")\n        i += 1\n    if openParensCount > 0:\n        raise PyAutoGUIException(\"Invalid command at index 0: Not enough close parentheses.\")\n\n    return commandStr[0:i]\n\n\ndef _getCommaToken(commandStr):\n    \"\"\"Gets the comma token at the start of commandStr.\n\n    Given ',' returns ','\n    Given '  ,', returns '  ,'\n\n    Raises an exception if a comma isn't found.\n    \"\"\"\n    pattern = re.compile(r\"^((\\s*),)\")\n    mo = pattern.search(commandStr)\n    if mo is None:\n        raise PyAutoGUIException(\"Invalid command at index 0: a comma was expected\")\n\n    return mo.group(1)\n\n\ndef _tokenizeCommandStr(commandStr):\n    \"\"\"Tokenizes commandStr into a list of commands and their arguments for\n    the run() function. Returns the list.\"\"\"\n\n    commandPattern = re.compile(r\"^(su|sd|ss|c|l|m|r|g|d|k|w|h|f|s|a|p)\")\n\n    # Tokenize the command string.\n    commandList = []\n    i = 0  # Points to the current index in commandStr that is being tokenized.\n    while i < len(commandStr):\n        if commandStr[i] in (\" \", \"\\t\", \"\\n\", \"\\r\"):\n            # Skip over whitespace:\n            i += 1\n            continue\n\n        mo = commandPattern.match(commandStr[i:])\n        if mo is None:\n            raise PyAutoGUIException(\"Invalid command at index %s: %s is not a valid command\" % (i, commandStr[i]))\n\n        individualCommand = mo.group(1)\n        commandList.append(individualCommand)\n        i += len(individualCommand)\n\n        # Handle the no argument commands (c, l, m, r, su, sd, ss):\n        if individualCommand in (\"c\", \"l\", \"m\", \"r\", \"su\", \"sd\", \"ss\"):\n            pass  # This just exists so these commands are covered by one of these cases.\n\n        # Handle the arguments of the mouse (g)o and mouse (d)rag commands:\n        elif individualCommand in (\"g\", \"d\"):\n            try:\n                x = _getNumberToken(commandStr[i:])\n                i += len(x)  # Increment past the x number.\n\n                comma = _getCommaToken(commandStr[i:])\n                i += len(comma)  # Increment past the comma (and any whitespace).\n\n                y = _getNumberToken(commandStr[i:])\n                i += len(y)  # Increment past the y number.\n\n            except PyAutoGUIException as excObj:\n                # Exception message starts with something like \"Invalid command at index 0:\"\n                # Change the index number and reraise it.\n                indexPart, colon, message = str(excObj).partition(\":\")\n\n                indexNum = indexPart[len(\"Invalid command at index \") :]\n                newIndexNum = int(indexNum) + i\n                raise PyAutoGUIException(\"Invalid command at index %s:%s\" % (newIndexNum, message))\n\n            # Make sure either both x and y have +/- or neither of them do:\n            if x.lstrip()[0].isdecimal() and not y.lstrip()[0].isdecimal():\n                raise PyAutoGUIException(\"Invalid command at index %s: Y has a +/- but X does not.\" % (i - len(y)))\n            if not x.lstrip()[0].isdecimal() and y.lstrip()[0].isdecimal():\n                raise PyAutoGUIException(\n                    \"Invalid command at index %s: Y does not have a +/- but X does.\" % (i - len(y))\n                )\n\n            # Get rid of any whitespace at the front:\n            commandList.append(x.lstrip())\n            commandList.append(y.lstrip())\n\n        # Handle the arguments of the (s)leep and (p)ause commands:\n        elif individualCommand in (\"s\", \"p\"):\n            try:\n                num = _getNumberToken(commandStr[i:])\n                i += len(num)  # Increment past the number.\n\n                # TODO - raise an exception if a + or - is in the number.\n\n            except PyAutoGUIException as excObj:\n                # Exception message starts with something like \"Invalid command at index 0:\"\n                # Change the index number and reraise it.\n                indexPart, colon, message = str(excObj).partition(\":\")\n\n                indexNum = indexPart[len(\"Invalid command at index \") :]\n                newIndexNum = int(indexNum) + i\n                raise PyAutoGUIException(\"Invalid command at index %s:%s\" % (newIndexNum, message))\n\n            # Get rid of any whitespace at the front:\n            commandList.append(num.lstrip())\n\n        # Handle the arguments of the (k)ey press, (w)rite, (h)otkeys, and (a)lert commands:\n        elif individualCommand in (\"k\", \"w\", \"h\", \"a\"):\n            try:\n                quotedString = _getQuotedStringToken(commandStr[i:])\n                i += len(quotedString)  # Increment past the quoted string.\n            except PyAutoGUIException as excObj:\n                # Exception message starts with something like \"Invalid command at index 0:\"\n                # Change the index number and reraise it.\n                indexPart, colon, message = str(excObj).partition(\":\")\n\n                indexNum = indexPart[len(\"Invalid command at index \") :]\n                newIndexNum = int(indexNum) + i\n                raise PyAutoGUIException(\"Invalid command at index %s:%s\" % (newIndexNum, message))\n\n            # Get rid of any whitespace at the front and the quotes:\n            commandList.append(quotedString[1:-1].lstrip())\n\n        # Handle the arguments of the (f)or loop command:\n        elif individualCommand == \"f\":\n            try:\n                numberOfLoops = _getNumberToken(commandStr[i:])\n                i += len(numberOfLoops)  # Increment past the number of loops.\n\n                subCommandStr = _getParensCommandStrToken(commandStr[i:])\n                i += len(subCommandStr)  # Increment past the sub-command string.\n\n            except PyAutoGUIException as excObj:\n                # Exception message starts with something like \"Invalid command at index 0:\"\n                # Change the index number and reraise it.\n                indexPart, colon, message = str(excObj).partition(\":\")\n\n                indexNum = indexPart[len(\"Invalid command at index \") :]\n                newIndexNum = int(indexNum) + i\n                raise PyAutoGUIException(\"Invalid command at index %s:%s\" % (newIndexNum, message))\n\n            # Get rid of any whitespace at the front:\n            commandList.append(numberOfLoops.lstrip())\n\n            # Get rid of any whitespace at the front and the quotes:\n            subCommandStr = subCommandStr.lstrip()[1:-1]\n            # Recursively call this function and append the list it returns:\n            commandList.append(_tokenizeCommandStr(subCommandStr))\n\n    return commandList\n\n\ndef _runCommandList(commandList, _ssCount):\n    global PAUSE\n    i = 0\n    while i < len(commandList):\n        command = commandList[i]\n\n        if command == \"c\":\n            click(button=PRIMARY)\n        elif command == \"l\":\n            click(button=LEFT)\n        elif command == \"m\":\n            click(button=MIDDLE)\n        elif command == \"r\":\n            click(button=RIGHT)\n        elif command == \"su\":\n            scroll(1)  # scroll up\n        elif command == \"sd\":\n            scroll(-1)  # scroll down\n        elif command == \"ss\":\n            screenshot(\"screenshot%s.png\" % (_ssCount[0]))\n            _ssCount[0] += 1\n        elif command == \"s\":\n            sleep(float(commandList[i + 1]))\n            i += 1\n        elif command == \"p\":\n            PAUSE = float(commandList[i + 1])\n            i += 1\n        elif command == \"g\":\n            if commandList[i + 1][0] in (\"+\", \"-\") and commandList[i + 2][0] in (\"+\", \"-\"):\n                move(int(commandList[i + 1]), int(commandList[i + 2]))\n            else:\n                moveTo(int(commandList[i + 1]), int(commandList[i + 2]))\n            i += 2\n        elif command == \"d\":\n            if commandList[i + 1][0] in (\"+\", \"-\") and commandList[i + 2][0] in (\"+\", \"-\"):\n                drag(int(commandList[i + 1]), int(commandList[i + 2]))\n            else:\n                dragTo(int(commandList[i + 1]), int(commandList[i + 2]))\n            i += 2\n        elif command == \"k\":\n            press(commandList[i + 1])\n            i += 1\n        elif command == \"w\":\n            write(commandList[i + 1])\n            i += 1\n        elif command == \"h\":\n            hotkey(*commandList[i + 1].replace(\" \", \"\").split(\",\"))\n            i += 1\n        elif command == \"a\":\n            alert(commandList[i + 1])\n            i += 1\n        elif command == \"f\":\n            for j in range(int(commandList[i + 1])):\n                _runCommandList(commandList[i + 2], _ssCount)\n            i += 2\n        i += 1\n\n\ndef run(commandStr, _ssCount=None):\n    \"\"\"Run a series of PyAutoGUI function calls according to a mini-language\n    made for this function. The `commandStr` is composed of character\n    commands that represent PyAutoGUI function calls.\n\n    For example, `run('ccg-20,+0c')` clicks the mouse twice, then makes\n    the mouse cursor go 20 pixels to the left, then click again.\n\n    Whitespace between commands and arguments is ignored. Command characters\n    must be lowercase. Quotes must be single quotes.\n\n    For example, the previous call could also be written as `run('c c g -20, +0 c')`.\n\n    The character commands and their equivalents are here:\n\n    `c` => `click(button=PRIMARY)`\n    `l` => `click(button=LEFT)`\n    `m` => `click(button=MIDDLE)`\n    `r` => `click(button=RIGHT)`\n    `su` => `scroll(1) # scroll up`\n    `sd` => `scroll(-1) # scroll down`\n    `ss` => `screenshot('screenshot1.png') # filename number increases on its own`\n\n    `gX,Y` => `moveTo(X, Y)`\n    `g+X,-Y` => `move(X, Y) # The + or - prefix is the difference between move() and moveTo()`\n    `dX,Y` => `dragTo(X, Y)`\n    `d+X,-Y` => `drag(X, Y) # The + or - prefix is the difference between drag() and dragTo()`\n\n    `k'key'` => `press('key')`\n    `w'text'` => `write('text')`\n    `h'key,key,key'` => `hotkey(*'key,key,key'.replace(' ', '').split(','))`\n    `a'hello'` => `alert('hello')`\n\n    `sN` => `sleep(N) # N can be an int or float`\n    `pN` => `PAUSE = N # N can be an int or float`\n\n    `fN(commands)` => for i in range(N): run(commands)\n\n    Note that any changes to `PAUSE` with the `p` command will be undone when\n    this function returns. The original `PAUSE` setting will be reset.\n\n    TODO - This function is under development.\n    \"\"\"\n\n    # run(\"ccc\")  straight forward\n    # run(\"susu\") if 's' then peek at the next character\n    global PAUSE\n\n    if _ssCount is None:\n        _ssCount = [\n            0\n        ]  # Setting this to a mutable list so that the callers can read the changed value. TODO improve this comment\n\n    commandList = _tokenizeCommandStr(commandStr)\n\n    # Carry out each command.\n    originalPAUSE = PAUSE\n    _runCommandList(commandList, _ssCount)\n    PAUSE = originalPAUSE\n\n\ndef printInfo(dontPrint=False):\n    msg = '''\n         Platform: {}\n   Python Version: {}\nPyAutoGUI Version: {}\n       Executable: {}\n       Resolution: {}\n        Timestamp: {}'''.format(\n        *getInfo()\n    )\n    if not dontPrint:\n        print(msg)\n    return msg\n\n\ndef getInfo():\n    return (sys.platform, sys.version, __version__, sys.executable, size(), datetime.datetime.now())\n\n\n# Add the bottom left, top right, and bottom right corners to FAILSAFE_POINTS.\n_right, _bottom = size()\nFAILSAFE_POINTS.extend([(0, _bottom - 1), (_right - 1, 0), (_right - 1, _bottom - 1)])\n"
  },
  {
    "path": "pyautogui/__main__.py",
    "content": "from . import displayMousePosition\ndisplayMousePosition()"
  },
  {
    "path": "pyautogui/_pyautogui_java.py",
    "content": ""
  },
  {
    "path": "pyautogui/_pyautogui_osx.py",
    "content": "import time\nimport sys\n\ntry:\n    import Quartz\nexcept:\n    assert False, \"You must first install pyobjc-core and pyobjc: https://pyautogui.readthedocs.io/en/latest/install.html\"\nimport AppKit\n\nimport pyautogui\nfrom pyautogui import LEFT, MIDDLE, RIGHT\n\nif sys.platform !=  'darwin':\n    raise Exception('The pyautogui_osx module should only be loaded on an OS X system.')\n\n\n\n\"\"\" Taken from events.h\n/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h\n\nThe *KB dictionaries in pyautogui map a string that can be passed to keyDown(),\nkeyUp(), or press() into the code used for the OS-specific keyboard function.\n\nThey should always be lowercase, and the same keys should be used across all OSes.\"\"\"\nkeyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])\nkeyboardMapping.update({\n    'a': 0x00, # kVK_ANSI_A\n    's': 0x01, # kVK_ANSI_S\n    'd': 0x02, # kVK_ANSI_D\n    'f': 0x03, # kVK_ANSI_F\n    'h': 0x04, # kVK_ANSI_H\n    'g': 0x05, # kVK_ANSI_G\n    'z': 0x06, # kVK_ANSI_Z\n    'x': 0x07, # kVK_ANSI_X\n    'c': 0x08, # kVK_ANSI_C\n    'v': 0x09, # kVK_ANSI_V\n    'b': 0x0b, # kVK_ANSI_B\n    'q': 0x0c, # kVK_ANSI_Q\n    'w': 0x0d, # kVK_ANSI_W\n    'e': 0x0e, # kVK_ANSI_E\n    'r': 0x0f, # kVK_ANSI_R\n    'y': 0x10, # kVK_ANSI_Y\n    't': 0x11, # kVK_ANSI_T\n    '1': 0x12, # kVK_ANSI_1\n    '!': 0x12, # kVK_ANSI_1\n    '2': 0x13, # kVK_ANSI_2\n    '@': 0x13, # kVK_ANSI_2\n    '3': 0x14, # kVK_ANSI_3\n    '#': 0x14, # kVK_ANSI_3\n    '4': 0x15, # kVK_ANSI_4\n    '$': 0x15, # kVK_ANSI_4\n    '6': 0x16, # kVK_ANSI_6\n    '^': 0x16, # kVK_ANSI_6\n    '5': 0x17, # kVK_ANSI_5\n    '%': 0x17, # kVK_ANSI_5\n    '=': 0x18, # kVK_ANSI_Equal\n    '+': 0x18, # kVK_ANSI_Equal\n    '9': 0x19, # kVK_ANSI_9\n    '(': 0x19, # kVK_ANSI_9\n    '7': 0x1a, # kVK_ANSI_7\n    '&': 0x1a, # kVK_ANSI_7\n    '-': 0x1b, # kVK_ANSI_Minus\n    '_': 0x1b, # kVK_ANSI_Minus\n    '8': 0x1c, # kVK_ANSI_8\n    '*': 0x1c, # kVK_ANSI_8\n    '0': 0x1d, # kVK_ANSI_0\n    ')': 0x1d, # kVK_ANSI_0\n    ']': 0x1e, # kVK_ANSI_RightBracket\n    '}': 0x1e, # kVK_ANSI_RightBracket\n    'o': 0x1f, # kVK_ANSI_O\n    'u': 0x20, # kVK_ANSI_U\n    '[': 0x21, # kVK_ANSI_LeftBracket\n    '{': 0x21, # kVK_ANSI_LeftBracket\n    'i': 0x22, # kVK_ANSI_I\n    'p': 0x23, # kVK_ANSI_P\n    'l': 0x25, # kVK_ANSI_L\n    'j': 0x26, # kVK_ANSI_J\n    \"'\": 0x27, # kVK_ANSI_Quote\n    '\"': 0x27, # kVK_ANSI_Quote\n    'k': 0x28, # kVK_ANSI_K\n    ';': 0x29, # kVK_ANSI_Semicolon\n    ':': 0x29, # kVK_ANSI_Semicolon\n    '\\\\': 0x2a, # kVK_ANSI_Backslash\n    '|': 0x2a, # kVK_ANSI_Backslash\n    ',': 0x2b, # kVK_ANSI_Comma\n    '<': 0x2b, # kVK_ANSI_Comma\n    '/': 0x2c, # kVK_ANSI_Slash\n    '?': 0x2c, # kVK_ANSI_Slash\n    'n': 0x2d, # kVK_ANSI_N\n    'm': 0x2e, # kVK_ANSI_M\n    '.': 0x2f, # kVK_ANSI_Period\n    '>': 0x2f, # kVK_ANSI_Period\n    '`': 0x32, # kVK_ANSI_Grave\n    '~': 0x32, # kVK_ANSI_Grave\n    ' ': 0x31, # kVK_Space\n    'space': 0x31,\n    '\\r': 0x24, # kVK_Return\n    '\\n': 0x24, # kVK_Return\n    'enter': 0x24, # kVK_Return\n    'return': 0x24, # kVK_Return\n    '\\t': 0x30, # kVK_Tab\n    'tab': 0x30, # kVK_Tab\n    'backspace': 0x33, # kVK_Delete, which is \"Backspace\" on OS X.\n    '\\b': 0x33, # kVK_Delete, which is \"Backspace\" on OS X.\n    'esc': 0x35, # kVK_Escape\n    'escape': 0x35, # kVK_Escape\n    'command': 0x37, # kVK_Command\n    'shift': 0x38, # kVK_Shift\n    'shiftleft': 0x38, # kVK_Shift\n    'capslock': 0x39, # kVK_CapsLock\n    'option': 0x3a, # kVK_Option\n    'optionleft': 0x3a, # kVK_Option\n    'alt': 0x3a, # kVK_Option\n    'altleft': 0x3a, # kVK_Option\n    'ctrl': 0x3b, # kVK_Control\n    'ctrlleft': 0x3b, # kVK_Control\n    'shiftright': 0x3c, # kVK_RightShift\n    'optionright': 0x3d, # kVK_RightOption\n    'ctrlright': 0x3e, # kVK_RightControl\n    'fn': 0x3f, # kVK_Function\n    'f17': 0x40, # kVK_F17\n    'volumeup': 0x48, # kVK_VolumeUp\n    'volumedown': 0x49, # kVK_VolumeDown\n    'volumemute': 0x4a, # kVK_Mute\n    'f18': 0x4f, # kVK_F18\n    'f19': 0x50, # kVK_F19\n    'f20': 0x5a, # kVK_F20\n    'f5': 0x60, # kVK_F5\n    'f6': 0x61, # kVK_F6\n    'f7': 0x62, # kVK_F7\n    'f3': 0x63, # kVK_F3\n    'f8': 0x64, # kVK_F8\n    'f9': 0x65, # kVK_F9\n    'f11': 0x67, # kVK_F11\n    'f13': 0x69, # kVK_F13\n    'f16': 0x6a, # kVK_F16\n    'f14': 0x6b, # kVK_F14\n    'f10': 0x6d, # kVK_F10\n    'f12': 0x6f, # kVK_F12\n    'f15': 0x71, # kVK_F15\n    'help': 0x72, # kVK_Help\n    'home': 0x73, # kVK_Home\n    'pageup': 0x74, # kVK_PageUp\n    'pgup': 0x74, # kVK_PageUp\n    'del': 0x75, # kVK_ForwardDelete\n    'delete': 0x75, # kVK_ForwardDelete\n    'f4': 0x76, # kVK_F4\n    'end': 0x77, # kVK_End\n    'f2': 0x78, # kVK_F2\n    'pagedown': 0x79, # kVK_PageDown\n    'pgdn': 0x79, # kVK_PageDown\n    'f1': 0x7a, # kVK_F1\n    'left': 0x7b, # kVK_LeftArrow\n    'right': 0x7c, # kVK_RightArrow\n    'down': 0x7d, # kVK_DownArrow\n    'up': 0x7e, # kVK_UpArrow\n    'yen': 0x5d, # kVK_JIS_Yen\n    #'underscore' : 0x5e, # kVK_JIS_Underscore (only applies to Japanese keyboards)\n    #'comma': 0x5f, # kVK_JIS_KeypadComma (only applies to Japanese keyboards)\n    'eisu': 0x66, # kVK_JIS_Eisu\n    'kana': 0x68, # kVK_JIS_Kana\n})\n\n\"\"\"\n# TODO - additional key codes to add\n  kVK_ANSI_KeypadDecimal        = 0x41,\n  kVK_ANSI_KeypadMultiply       = 0x43,\n  kVK_ANSI_KeypadPlus           = 0x45,\n  kVK_ANSI_KeypadClear          = 0x47,\n  kVK_ANSI_KeypadDivide         = 0x4B,\n  kVK_ANSI_KeypadEnter          = 0x4C,\n  kVK_ANSI_KeypadMinus          = 0x4E,\n  kVK_ANSI_KeypadEquals         = 0x51,\n  kVK_ANSI_Keypad0              = 0x52,\n  kVK_ANSI_Keypad1              = 0x53,\n  kVK_ANSI_Keypad2              = 0x54,\n  kVK_ANSI_Keypad3              = 0x55,\n  kVK_ANSI_Keypad4              = 0x56,\n  kVK_ANSI_Keypad5              = 0x57,\n  kVK_ANSI_Keypad6              = 0x58,\n  kVK_ANSI_Keypad7              = 0x59,\n  kVK_ANSI_Keypad8              = 0x5B,\n  kVK_ANSI_Keypad9              = 0x5C,\n\"\"\"\n\n# add mappings for uppercase letters\nfor c in 'abcdefghijklmnopqrstuvwxyz':\n    keyboardMapping[c.upper()] = keyboardMapping[c]\n\n# Taken from ev_keymap.h\n# http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-86.1/IOHIDSystem/IOKit/hidsystem/ev_keymap.h\nspecial_key_translate_table = {\n    'KEYTYPE_SOUND_UP': 0,\n    'KEYTYPE_SOUND_DOWN': 1,\n    'KEYTYPE_BRIGHTNESS_UP': 2,\n    'KEYTYPE_BRIGHTNESS_DOWN': 3,\n    'KEYTYPE_CAPS_LOCK': 4,\n    'KEYTYPE_HELP': 5,\n    'POWER_KEY': 6,\n    'KEYTYPE_MUTE': 7,\n    'UP_ARROW_KEY': 8,\n    'DOWN_ARROW_KEY': 9,\n    'KEYTYPE_NUM_LOCK': 10,\n    'KEYTYPE_CONTRAST_UP': 11,\n    'KEYTYPE_CONTRAST_DOWN': 12,\n    'KEYTYPE_LAUNCH_PANEL': 13,\n    'KEYTYPE_EJECT': 14,\n    'KEYTYPE_VIDMIRROR': 15,\n    'KEYTYPE_PLAY': 16,\n    'KEYTYPE_NEXT': 17,\n    'KEYTYPE_PREVIOUS': 18,\n    'KEYTYPE_FAST': 19,\n    'KEYTYPE_REWIND': 20,\n    'KEYTYPE_ILLUMINATION_UP': 21,\n    'KEYTYPE_ILLUMINATION_DOWN': 22,\n    'KEYTYPE_ILLUMINATION_TOGGLE': 23\n}\n\ndef _keyDown(key):\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    if key in special_key_translate_table:\n        _specialKeyEvent(key, 'down')\n    else:\n        _normalKeyEvent(key, 'down')\n\ndef _keyUp(key):\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    if key in special_key_translate_table:\n        _specialKeyEvent(key, 'up')\n    else:\n        _normalKeyEvent(key, 'up')\n\n\ndef _normalKeyEvent(key, upDown):\n    assert upDown in ('up', 'down'), \"upDown argument must be 'up' or 'down'\"\n\n    try:\n        if pyautogui.isShiftCharacter(key):\n            key_code = keyboardMapping[key.lower()]\n\n            event = Quartz.CGEventCreateKeyboardEvent(None,\n                        keyboardMapping['shift'], upDown == 'down')\n            Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)\n            # Tiny sleep to let OS X catch up on us pressing shift\n            time.sleep(pyautogui.DARWIN_CATCH_UP_TIME)\n\n        else:\n            key_code = keyboardMapping[key]\n\n        event = Quartz.CGEventCreateKeyboardEvent(None, key_code, upDown == 'down')\n        Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)\n        time.sleep(pyautogui.DARWIN_CATCH_UP_TIME)\n\n    # TODO - wait, is the shift key's keyup not done?\n    # TODO - get rid of this try-except.\n\n    except KeyError:\n        raise RuntimeError(\"Key %s not implemented.\" % (key))\n\ndef _specialKeyEvent(key, upDown):\n    \"\"\" Helper method for special keys.\n\n    Source: http://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac\n    \"\"\"\n    assert upDown in ('up', 'down'), \"upDown argument must be 'up' or 'down'\"\n\n    key_code = special_key_translate_table[key]\n\n    ev = AppKit.NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(\n            Quartz.NSSystemDefined, # type\n            (0,0), # location\n            0xa00 if upDown == 'down' else 0xb00, # flags\n            0, # timestamp\n            0, # window\n            0, # ctx\n            8, # subtype\n            (key_code << 16) | ((0xa if upDown == 'down' else 0xb) << 8), # data1\n            -1 # data2\n        )\n\n    Quartz.CGEventPost(0, ev.CGEvent())\n\n\n\n\n\n\n\n\n\ndef _position():\n    loc = AppKit.NSEvent.mouseLocation()\n    return int(loc.x), int(Quartz.CGDisplayPixelsHigh(0) - loc.y)\n\n\ndef _size():\n    return Quartz.CGDisplayPixelsWide(Quartz.CGMainDisplayID()), Quartz.CGDisplayPixelsHigh(Quartz.CGMainDisplayID())\n\n\n\ndef _scroll(clicks, x=None, y=None):\n    _vscroll(clicks, x, y)\n\n\n\"\"\"\nAccording to https://developer.apple.com/library/mac/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/Quartz.CGEventCreateScrollWheelEvent\n\"Scrolling movement is generally represented by small signed integer values, typically in a range from -10 to +10. Large values may have unexpected results, depending on the application that processes the event.\"\nThe scrolling functions will create multiple events that scroll 10 each, and then scroll the remainder.\n\"\"\"\n\ndef _vscroll(clicks, x=None, y=None):\n    _moveTo(x, y)\n    clicks = int(clicks)\n    for _ in range(abs(clicks) // 10):\n        scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n            None, # no source\n            Quartz.kCGScrollEventUnitLine, # units\n            1, # wheelCount (number of dimensions)\n            10 if clicks >= 0 else -10) # vertical movement\n        Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\n\n    scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n        None, # no source\n        Quartz.kCGScrollEventUnitLine, # units\n        1, # wheelCount (number of dimensions)\n        clicks % 10 if clicks >= 0 else -1 * (-clicks % 10)) # vertical movement\n    Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\n\n\ndef _hscroll(clicks, x=None, y=None):\n    _moveTo(x, y)\n    clicks = int(clicks)\n    for _ in range(abs(clicks) // 10):\n        scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n            None, # no source\n            Quartz.kCGScrollEventUnitLine, # units\n            2, # wheelCount (number of dimensions)\n            0, # vertical movement\n            10 if clicks >= 0 else -10) # horizontal movement\n        Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\n\n    scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n        None, # no source\n        Quartz.kCGScrollEventUnitLine, # units\n        2, # wheelCount (number of dimensions)\n        0, # vertical movement\n        (clicks % 10) if clicks >= 0 else (-1 * clicks % 10)) # horizontal movement\n    Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\n\n\ndef _mouseDown(x, y, button):\n    if button == LEFT:\n        _sendMouseEvent(Quartz.kCGEventLeftMouseDown, x, y, Quartz.kCGMouseButtonLeft)\n    elif button == MIDDLE:\n        _sendMouseEvent(Quartz.kCGEventOtherMouseDown, x, y, Quartz.kCGMouseButtonCenter)\n    elif button == RIGHT:\n        _sendMouseEvent(Quartz.kCGEventRightMouseDown, x, y, Quartz.kCGMouseButtonRight)\n    else:\n        assert False, \"button argument not in ('left', 'middle', 'right')\"\n\n\ndef _mouseUp(x, y, button):\n    if button == LEFT:\n        _sendMouseEvent(Quartz.kCGEventLeftMouseUp, x, y, Quartz.kCGMouseButtonLeft)\n    elif button == MIDDLE:\n        _sendMouseEvent(Quartz.kCGEventOtherMouseUp, x, y, Quartz.kCGMouseButtonCenter)\n    elif button == RIGHT:\n        _sendMouseEvent(Quartz.kCGEventRightMouseUp, x, y, Quartz.kCGMouseButtonRight)\n    else:\n        assert False, \"button argument not in ('left', 'middle', 'right')\"\n\n\ndef _click(x, y, button):\n    if button == LEFT:\n        _sendMouseEvent(Quartz.kCGEventLeftMouseDown, x, y, Quartz.kCGMouseButtonLeft)\n        _sendMouseEvent(Quartz.kCGEventLeftMouseUp, x, y, Quartz.kCGMouseButtonLeft)\n    elif button == MIDDLE:\n        _sendMouseEvent(Quartz.kCGEventOtherMouseDown, x, y, Quartz.kCGMouseButtonCenter)\n        _sendMouseEvent(Quartz.kCGEventOtherMouseUp, x, y, Quartz.kCGMouseButtonCenter)\n    elif button == RIGHT:\n        _sendMouseEvent(Quartz.kCGEventRightMouseDown, x, y, Quartz.kCGMouseButtonRight)\n        _sendMouseEvent(Quartz.kCGEventRightMouseUp, x, y, Quartz.kCGMouseButtonRight)\n    else:\n        assert False, \"button argument not in ('left', 'middle', 'right')\"\n\n\n_mouse_is_swapped_setting = None\n\n\ndef _mouse_is_swapped():\n    # TODO - for performance reasons, we only check the swapped mouse button\n    # setting from the OS once at start up, rather than every mouse click.\n    # This may change in the future.\n    global _mouse_is_swapped_setting\n    if _mouse_is_swapped_setting is None:\n        _mouse_is_swapped_setting = False # TODO - for now, we can't detect this setting\n    return _mouse_is_swapped_setting\n\n\ndef _multiClick(x, y, button, num, interval=0.0):\n    btn    = None\n    down   = None\n    up     = None\n\n    if button == LEFT:\n        btn  = Quartz.kCGMouseButtonLeft\n        down = Quartz.kCGEventLeftMouseDown\n        up   = Quartz.kCGEventLeftMouseUp\n    elif button == MIDDLE:\n        btn  = Quartz.kCGMouseButtonCenter\n        down = Quartz.kCGEventOtherMouseDown\n        up   = Quartz.kCGEventOtherMouseUp\n    elif button == RIGHT:\n        btn  = Quartz.kCGMouseButtonRight\n        down = Quartz.kCGEventRightMouseDown\n        up   = Quartz.kCGEventRightMouseUp\n    else:\n        assert False, \"button argument not in ('left', 'middle', 'right')\"\n        return\n\n    for i in range(num):\n        _click(x, y, button)\n        time.sleep(interval)\n\n\ndef _sendMouseEvent(ev, x, y, button):\n    mouseEvent = Quartz.CGEventCreateMouseEvent(None, ev, (x, y), button)\n    Quartz.CGEventPost(Quartz.kCGHIDEventTap, mouseEvent)\n\n\ndef _dragTo(x, y, button):\n    if button == LEFT:\n        _sendMouseEvent(Quartz.kCGEventLeftMouseDragged , x, y, Quartz.kCGMouseButtonLeft)\n    elif button == MIDDLE:\n        _sendMouseEvent(Quartz.kCGEventOtherMouseDragged , x, y, Quartz.kCGMouseButtonCenter)\n    elif button == RIGHT:\n        _sendMouseEvent(Quartz.kCGEventRightMouseDragged , x, y, Quartz.kCGMouseButtonRight)\n    else:\n        assert False, \"button argument not in ('left', 'middle', 'right')\"\n    time.sleep(pyautogui.DARWIN_CATCH_UP_TIME) # needed to allow OS time to catch up.\n\ndef _moveTo(x, y):\n    _sendMouseEvent(Quartz.kCGEventMouseMoved, x, y, 0)\n    time.sleep(pyautogui.DARWIN_CATCH_UP_TIME) # needed to allow OS time to catch up.\n"
  },
  {
    "path": "pyautogui/_pyautogui_win.py",
    "content": "# Windows implementation of PyAutoGUI functions.\n# BSD license\n# Al Sweigart al@inventwithpython.com\n\nimport ctypes\nimport ctypes.wintypes\nimport pyautogui\nfrom pyautogui import LEFT, MIDDLE, RIGHT\n\nimport sys\nif sys.platform !=  'win32':\n    raise Exception('The pyautogui_win module should only be loaded on a Windows system.')\n\n\n# Fixes the scaling issues where PyAutoGUI was reporting the wrong resolution:\ntry:\n   ctypes.windll.user32.SetProcessDPIAware()\nexcept AttributeError:\n    pass # Windows XP doesn't support this, so just do nothing.\n\n\n\"\"\"\nA lot of this code is probably repeated from win32 extensions module, but I didn't want to have that dependency.\n\nNote: According to http://msdn.microsoft.com/en-us/library/windows/desktop/ms646260(v=vs.85).aspx\nthe ctypes.windll.user32.mouse_event() function has been superseded by SendInput.\n\nSendInput() is documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx\n\nUPDATE: SendInput() doesn't seem to be working for me. I've switched back to mouse_event().\"\"\"\n\n\n# Event codes to be passed to the mouse_event() win32 function.\n# Documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx\nMOUSEEVENTF_MOVE = 0x0001\nMOUSEEVENTF_LEFTDOWN = 0x0002\nMOUSEEVENTF_LEFTUP = 0x0004\nMOUSEEVENTF_LEFTCLICK = MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP\nMOUSEEVENTF_RIGHTDOWN = 0x0008\nMOUSEEVENTF_RIGHTUP = 0x0010\nMOUSEEVENTF_RIGHTCLICK = MOUSEEVENTF_RIGHTDOWN + MOUSEEVENTF_RIGHTUP\nMOUSEEVENTF_MIDDLEDOWN = 0x0020\nMOUSEEVENTF_MIDDLEUP = 0x0040\nMOUSEEVENTF_MIDDLECLICK = MOUSEEVENTF_MIDDLEDOWN + MOUSEEVENTF_MIDDLEUP\n\nMOUSEEVENTF_ABSOLUTE = 0x8000\nMOUSEEVENTF_WHEEL = 0x0800\nMOUSEEVENTF_HWHEEL = 0x01000\n\n# Documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx\nKEYEVENTF_KEYDOWN = 0x0000 # Technically this constant doesn't exist in the MS documentation. It's the lack of KEYEVENTF_KEYUP that means pressing the key down.\nKEYEVENTF_KEYUP = 0x0002\n\n# Documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx\nINPUT_MOUSE = 0\nINPUT_KEYBOARD = 1\n\n\n# These ctypes structures are for Win32 INPUT, MOUSEINPUT, KEYBDINPUT, and HARDWAREINPUT structures,\n# used by SendInput and documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx\n# Thanks to BSH for this StackOverflow answer: https://stackoverflow.com/questions/18566289/how-would-you-recreate-this-windows-api-structure-with-ctypes\nclass MOUSEINPUT(ctypes.Structure):\n    _fields_ = [\n        ('dx', ctypes.wintypes.LONG),\n        ('dy', ctypes.wintypes.LONG),\n        ('mouseData', ctypes.wintypes.DWORD),\n        ('dwFlags', ctypes.wintypes.DWORD),\n        ('time', ctypes.wintypes.DWORD),\n        ('dwExtraInfo', ctypes.POINTER(ctypes.wintypes.ULONG)),\n    ]\n\nclass KEYBDINPUT(ctypes.Structure):\n    _fields_ = [\n        ('wVk', ctypes.wintypes.WORD),\n        ('wScan', ctypes.wintypes.WORD),\n        ('dwFlags', ctypes.wintypes.DWORD),\n        ('time', ctypes.wintypes.DWORD),\n        ('dwExtraInfo', ctypes.POINTER(ctypes.wintypes.ULONG)),\n    ]\n\nclass HARDWAREINPUT(ctypes.Structure):\n    _fields_ = [\n        ('uMsg', ctypes.wintypes.DWORD),\n        ('wParamL', ctypes.wintypes.WORD),\n        ('wParamH', ctypes.wintypes.DWORD)\n    ]\n\nclass INPUT(ctypes.Structure):\n    class _I(ctypes.Union):\n        _fields_ = [\n            ('mi', MOUSEINPUT),\n            ('ki', KEYBDINPUT),\n            ('hi', HARDWAREINPUT),\n        ]\n\n    _anonymous_ = ('i', )\n    _fields_ = [\n        ('type', ctypes.wintypes.DWORD),\n        ('i', _I),\n    ]\n# End of the SendInput win32 data structures.\n\n\n\n\"\"\" Keyboard key mapping for pyautogui:\nDocumented at http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx\n\nThe *KB dictionaries in pyautogui map a string that can be passed to keyDown(),\nkeyUp(), or press() into the code used for the OS-specific keyboard function.\n\nThey should always be lowercase, and the same keys should be used across all OSes.\"\"\"\nkeyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])\nkeyboardMapping.update({\n    'backspace': 0x08, # VK_BACK\n    '\\b': 0x08, # VK_BACK\n    'super': 0x5B, #VK_LWIN\n    'tab': 0x09, # VK_TAB\n    '\\t': 0x09, # VK_TAB\n    'clear': 0x0c, # VK_CLEAR\n    'enter': 0x0d, # VK_RETURN\n    '\\n': 0x0d, # VK_RETURN\n    'return': 0x0d, # VK_RETURN\n    'shift': 0x10, # VK_SHIFT\n    'ctrl': 0x11, # VK_CONTROL\n    'alt': 0x12, # VK_MENU\n    'pause': 0x13, # VK_PAUSE\n    'capslock': 0x14, # VK_CAPITAL\n    'kana': 0x15, # VK_KANA\n    'hanguel': 0x15, # VK_HANGUEL\n    'hangul': 0x15, # VK_HANGUL\n    'junja': 0x17, # VK_JUNJA\n    'final': 0x18, # VK_FINAL\n    'hanja': 0x19, # VK_HANJA\n    'kanji': 0x19, # VK_KANJI\n    'esc': 0x1b, # VK_ESCAPE\n    'escape': 0x1b, # VK_ESCAPE\n    'convert': 0x1c, # VK_CONVERT\n    'nonconvert': 0x1d, # VK_NONCONVERT\n    'accept': 0x1e, # VK_ACCEPT\n    'modechange': 0x1f, # VK_MODECHANGE\n    ' ': 0x20, # VK_SPACE\n    'space': 0x20, # VK_SPACE\n    'pgup': 0x21, # VK_PRIOR\n    'pgdn': 0x22, # VK_NEXT\n    'pageup': 0x21, # VK_PRIOR\n    'pagedown': 0x22, # VK_NEXT\n    'end': 0x23, # VK_END\n    'home': 0x24, # VK_HOME\n    'left': 0x25, # VK_LEFT\n    'up': 0x26, # VK_UP\n    'right': 0x27, # VK_RIGHT\n    'down': 0x28, # VK_DOWN\n    'select': 0x29, # VK_SELECT\n    'print': 0x2a, # VK_PRINT\n    'execute': 0x2b, # VK_EXECUTE\n    'prtsc': 0x2c, # VK_SNAPSHOT\n    'prtscr': 0x2c, # VK_SNAPSHOT\n    'prntscrn': 0x2c, # VK_SNAPSHOT\n    'printscreen': 0x2c, # VK_SNAPSHOT\n    'insert': 0x2d, # VK_INSERT\n    'del': 0x2e, # VK_DELETE\n    'delete': 0x2e, # VK_DELETE\n    'help': 0x2f, # VK_HELP\n    'win': 0x5b, # VK_LWIN\n    'winleft': 0x5b, # VK_LWIN\n    'winright': 0x5c, # VK_RWIN\n    'apps': 0x5d, # VK_APPS\n    'sleep': 0x5f, # VK_SLEEP\n    'num0': 0x60, # VK_NUMPAD0\n    'num1': 0x61, # VK_NUMPAD1\n    'num2': 0x62, # VK_NUMPAD2\n    'num3': 0x63, # VK_NUMPAD3\n    'num4': 0x64, # VK_NUMPAD4\n    'num5': 0x65, # VK_NUMPAD5\n    'num6': 0x66, # VK_NUMPAD6\n    'num7': 0x67, # VK_NUMPAD7\n    'num8': 0x68, # VK_NUMPAD8\n    'num9': 0x69, # VK_NUMPAD9\n    'multiply': 0x6a, # VK_MULTIPLY  ??? Is this the numpad *?\n    'add': 0x6b, # VK_ADD  ??? Is this the numpad +?\n    'separator': 0x6c, # VK_SEPARATOR  ??? Is this the numpad enter?\n    'subtract': 0x6d, # VK_SUBTRACT  ??? Is this the numpad -?\n    'decimal': 0x6e, # VK_DECIMAL\n    'divide': 0x6f, # VK_DIVIDE\n    'f1': 0x70, # VK_F1\n    'f2': 0x71, # VK_F2\n    'f3': 0x72, # VK_F3\n    'f4': 0x73, # VK_F4\n    'f5': 0x74, # VK_F5\n    'f6': 0x75, # VK_F6\n    'f7': 0x76, # VK_F7\n    'f8': 0x77, # VK_F8\n    'f9': 0x78, # VK_F9\n    'f10': 0x79, # VK_F10\n    'f11': 0x7a, # VK_F11\n    'f12': 0x7b, # VK_F12\n    'f13': 0x7c, # VK_F13\n    'f14': 0x7d, # VK_F14\n    'f15': 0x7e, # VK_F15\n    'f16': 0x7f, # VK_F16\n    'f17': 0x80, # VK_F17\n    'f18': 0x81, # VK_F18\n    'f19': 0x82, # VK_F19\n    'f20': 0x83, # VK_F20\n    'f21': 0x84, # VK_F21\n    'f22': 0x85, # VK_F22\n    'f23': 0x86, # VK_F23\n    'f24': 0x87, # VK_F24\n    'numlock': 0x90, # VK_NUMLOCK\n    'scrolllock': 0x91, # VK_SCROLL\n    'shiftleft': 0xa0, # VK_LSHIFT\n    'shiftright': 0xa1, # VK_RSHIFT\n    'ctrlleft': 0xa2, # VK_LCONTROL\n    'ctrlright': 0xa3, # VK_RCONTROL\n    'altleft': 0xa4, # VK_LMENU\n    'altright': 0xa5, # VK_RMENU\n    'browserback': 0xa6, # VK_BROWSER_BACK\n    'browserforward': 0xa7, # VK_BROWSER_FORWARD\n    'browserrefresh': 0xa8, # VK_BROWSER_REFRESH\n    'browserstop': 0xa9, # VK_BROWSER_STOP\n    'browsersearch': 0xaa, # VK_BROWSER_SEARCH\n    'browserfavorites': 0xab, # VK_BROWSER_FAVORITES\n    'browserhome': 0xac, # VK_BROWSER_HOME\n    'volumemute': 0xad, # VK_VOLUME_MUTE\n    'volumedown': 0xae, # VK_VOLUME_DOWN\n    'volumeup': 0xaf, # VK_VOLUME_UP\n    'nexttrack': 0xb0, # VK_MEDIA_NEXT_TRACK\n    'prevtrack': 0xb1, # VK_MEDIA_PREV_TRACK\n    'stop': 0xb2, # VK_MEDIA_STOP\n    'playpause': 0xb3, # VK_MEDIA_PLAY_PAUSE\n    'launchmail': 0xb4, # VK_LAUNCH_MAIL\n    'launchmediaselect': 0xb5, # VK_LAUNCH_MEDIA_SELECT\n    'launchapp1': 0xb6, # VK_LAUNCH_APP1\n    'launchapp2': 0xb7, # VK_LAUNCH_APP2\n    })\n\n    # There are other virtual key constants that are not used here because the printable ascii keys are\n    # handled in the following `for` loop.\n    # The virtual key constants that aren't used are:\n    # VK_OEM_1, VK_OEM_PLUS, VK_OEM_COMMA, VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_2, VK_OEM_3, VK_OEM_4,\n    # VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_8, VK_PACKET, VK_ATTN, VK_CRSEL, VK_EXSEL, VK_EREOF,\n    # VK_PLAY, VK_ZOOM, VK_NONAME, VK_PA1, VK_OEM_CLEAR\n\n# Populate the basic printable ascii characters.\n# https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscana\nfor c in range(32, 128):\n    keyboardMapping[chr(c)] = ctypes.windll.user32.VkKeyScanA(ctypes.wintypes.WCHAR(chr(c)))\n\n\ndef _keyDown(key):\n    \"\"\"Performs a keyboard key press without the release. This will put that\n    key in a held down state.\n\n    NOTE: For some reason, this does not seem to cause key repeats like would\n    happen if a keyboard key was held down on a text field.\n\n    Args:\n      key (str): The key to be pressed down. The valid names are listed in\n      pyautogui.KEY_NAMES.\n\n    Returns:\n      None\n    \"\"\"\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    needsShift = pyautogui.isShiftCharacter(key)\n\n    \"\"\"\n    # OLD CODE: The new code relies on having all keys be loaded in keyboardMapping from the start.\n    if key in keyboardMapping.keys():\n        vkCode = keyboardMapping[key]\n    elif len(key) == 1:\n        # note: I could use this case to update keyboardMapping to cache the VkKeyScan results, but I've decided not to just to make any possible bugs easier to reproduce.\n        vkCode = ctypes.windll.user32.VkKeyScanW(ctypes.wintypes.WCHAR(key))\n        if vkCode == -1:\n            raise ValueError('There is no VK code for key \"%s\"' % (key))\n        if vkCode > 0x100: # the vk code will be > 0x100 if it needs shift\n            vkCode -= 0x100\n            needsShift = True\n    \"\"\"\n    mods, vkCode = divmod(keyboardMapping[key], 0x100)\n\n    for apply_mod, vk_mod in [(mods & 4, 0x12), (mods & 2, 0x11),\n        (mods & 1 or needsShift, 0x10)]: #HANKAKU not supported! mods & 8\n        if apply_mod:\n            ctypes.windll.user32.keybd_event(vk_mod, 0, KEYEVENTF_KEYDOWN, 0) #\n    ctypes.windll.user32.keybd_event(vkCode, 0, KEYEVENTF_KEYDOWN, 0)\n    for apply_mod, vk_mod in [(mods & 1 or needsShift, 0x10), (mods & 2, 0x11),\n        (mods & 4, 0x12)]: #HANKAKU not supported! mods & 8\n        if apply_mod:\n            ctypes.windll.user32.keybd_event(vk_mod, 0, KEYEVENTF_KEYUP, 0) #\n\n\ndef _keyUp(key):\n    \"\"\"Performs a keyboard key release (without the press down beforehand).\n\n    Args:\n      key (str): The key to be released up. The valid names are listed in\n      pyautogui.KEY_NAMES.\n\n    Returns:\n      None\n    \"\"\"\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    needsShift = pyautogui.isShiftCharacter(key)\n    \"\"\"\n    # OLD CODE: The new code relies on having all keys be loaded in keyboardMapping from the start.\n    if key in keyboardMapping.keys():\n        vkCode = keyboardMapping[key]\n    elif len(key) == 1:\n        # note: I could use this case to update keyboardMapping to cache the VkKeyScan results, but I've decided not to just to make any possible bugs easier to reproduce.\n        vkCode = ctypes.windll.user32.VkKeyScanW(ctypes.wintypes.WCHAR(key))\n        if vkCode == -1:\n            raise ValueError('There is no VK code for key \"%s\"' % (key))\n        if vkCode > 0x100: # the vk code will be > 0x100 if it needs shift\n            vkCode -= 0x100\n            needsShift = True\n    \"\"\"\n    mods, vkCode = divmod(keyboardMapping[key], 0x100)\n\n    for apply_mod, vk_mod in [(mods & 4, 0x12), (mods & 2, 0x11),\n        (mods & 1 or needsShift, 0x10)]: #HANKAKU not supported! mods & 8\n        if apply_mod:\n            ctypes.windll.user32.keybd_event(vk_mod, 0, 0, 0) #\n    ctypes.windll.user32.keybd_event(vkCode, 0, KEYEVENTF_KEYUP, 0)\n    for apply_mod, vk_mod in [(mods & 1 or needsShift, 0x10), (mods & 2, 0x11),\n        (mods & 4, 0x12)]: #HANKAKU not supported! mods & 8\n        if apply_mod:\n            ctypes.windll.user32.keybd_event(vk_mod, 0, KEYEVENTF_KEYUP, 0) #\n\n\ndef _position():\n    \"\"\"Returns the current xy coordinates of the mouse cursor as a two-integer\n    tuple by calling the GetCursorPos() win32 function.\n\n    Returns:\n      (x, y) tuple of the current xy coordinates of the mouse cursor.\n    \"\"\"\n\n    cursor = ctypes.wintypes.POINT()\n    ctypes.windll.user32.GetCursorPos(ctypes.byref(cursor))\n    return (cursor.x, cursor.y)\n\n\ndef _size():\n    \"\"\"Returns the width and height of the screen as a two-integer tuple.\n\n    Returns:\n      (width, height) tuple of the screen size, in pixels.\n    \"\"\"\n    return (ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1))\n\n\ndef _moveTo(x, y):\n    \"\"\"Send the mouse move event to Windows by calling SetCursorPos() win32\n    function.\n\n    Args:\n      button (str): The mouse button, either 'left', 'middle', or 'right'\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n\n    Returns:\n      None\n    \"\"\"\n    ctypes.windll.user32.SetCursorPos(x, y)\n    # This was a possible solution to issue #314 https://github.com/asweigart/pyautogui/issues/314\n    # but I'd like to hang on to SetCursorPos because mouse_event() has been superseded.\n    #_sendMouseEvent(MOUSEEVENTF_MOVE + MOUSEEVENTF_ABSOLUTE, x, y)\n\n\ndef _mouseDown(x, y, button):\n    \"\"\"Send the mouse down event to Windows by calling the mouse_event() win32\n    function.\n\n    Args:\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n      button (str): The mouse button, either 'left', 'middle', or 'right'\n\n    Returns:\n      None\n    \"\"\"\n    if button not in (LEFT, MIDDLE, RIGHT):\n        raise ValueError('button arg to _click() must be one of \"left\", \"middle\", or \"right\", not %s' % button)\n\n    if button == LEFT:\n        EV = MOUSEEVENTF_LEFTDOWN\n    elif button == MIDDLE:\n        EV = MOUSEEVENTF_MIDDLEDOWN\n    elif button == RIGHT:\n        EV = MOUSEEVENTF_RIGHTDOWN\n\n    try:\n        _sendMouseEvent(EV, x, y)\n    except (PermissionError, OSError):\n        # TODO: We need to figure out how to prevent these errors, see https://github.com/asweigart/pyautogui/issues/60\n        pass\n\n\ndef _mouseUp(x, y, button):\n    \"\"\"Send the mouse up event to Windows by calling the mouse_event() win32\n    function.\n\n    Args:\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n      button (str): The mouse button, either 'left', 'middle', or 'right'\n\n    Returns:\n      None\n    \"\"\"\n    if button not in (LEFT, MIDDLE, RIGHT):\n        raise ValueError('button arg to _click() must be one of \"left\", \"middle\", or \"right\", not %s' % button)\n\n    if button == LEFT:\n        EV = MOUSEEVENTF_LEFTUP\n    elif button == MIDDLE:\n        EV = MOUSEEVENTF_MIDDLEUP\n    elif button == RIGHT:\n        EV = MOUSEEVENTF_RIGHTUP\n\n    try:\n        _sendMouseEvent(EV, x, y)\n    except (PermissionError, OSError): # TODO: We need to figure out how to prevent these errors, see https://github.com/asweigart/pyautogui/issues/60\n        pass\n\n\ndef _click(x, y, button):\n    \"\"\"Send the mouse click event to Windows by calling the mouse_event() win32\n    function.\n\n    Args:\n      button (str): The mouse button, either 'left', 'middle', or 'right'\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n\n    Returns:\n      None\n    \"\"\"\n    if button not in (LEFT, MIDDLE, RIGHT):\n        raise ValueError('button arg to _click() must be one of \"left\", \"middle\", or \"right\", not %s' % button)\n\n    if button == LEFT:\n        EV = MOUSEEVENTF_LEFTCLICK\n    elif button == MIDDLE:\n        EV = MOUSEEVENTF_MIDDLECLICK\n    elif button ==RIGHT:\n        EV = MOUSEEVENTF_RIGHTCLICK\n\n    try:\n        _sendMouseEvent(EV, x, y)\n    except (PermissionError, OSError):\n        # TODO: We need to figure out how to prevent these errors, see https://github.com/asweigart/pyautogui/issues/60\n        pass\n\n\ndef _mouse_is_swapped():\n    # TODO - measure the performance of checking this setting for each click.\n    # 23 is SM_SWAPBUTTON: \"Nonzero if the meanings of the left and right mouse buttons are swapped; otherwise, 0.\"\n    return ctypes.windll.user32.GetSystemMetrics(23) != 0\n\ndef _sendMouseEvent(ev, x, y, dwData=0):\n    \"\"\"The helper function that actually makes the call to the mouse_event()\n    win32 function.\n\n    Args:\n      ev (int): The win32 code for the mouse event. Use one of the MOUSEEVENTF_*\n      constants for this argument.\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n      dwData (int): The argument for mouse_event()'s dwData parameter. So far\n        this is only used by mouse scrolling.\n\n    Returns:\n      None\n    \"\"\"\n    assert x != None and y != None, 'x and y cannot be set to None'\n    # TODO: ARG! For some reason, SendInput isn't working for mouse events. I'm switching to using the older mouse_event win32 function.\n    #mouseStruct = MOUSEINPUT()\n    #mouseStruct.dx = x\n    #mouseStruct.dy = y\n    #mouseStruct.mouseData = ev\n    #mouseStruct.time = 0\n    #mouseStruct.dwExtraInfo = ctypes.pointer(ctypes.c_ulong(0)) # according to https://stackoverflow.com/questions/13564851/generate-keyboard-events I can just set this. I don't really care about this value.\n    #inputStruct = INPUT()\n    #inputStruct.mi = mouseStruct\n    #inputStruct.type = INPUT_MOUSE\n    #ctypes.windll.user32.SendInput(1, ctypes.pointer(inputStruct), ctypes.sizeof(inputStruct))\n\n    # TODO Note: We need to handle additional buttons, which I believe is documented here:\n    # https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-mouse_event\n\n    width, height = _size()\n    convertedX = 65536 * x // width + 1\n    convertedY = 65536 * y // height + 1\n    ctypes.windll.user32.mouse_event(ev, ctypes.c_long(convertedX), ctypes.c_long(convertedY), dwData, 0)\n\n    # TODO: Too many false positives with this code: See: https://github.com/asweigart/pyautogui/issues/108\n    #if ctypes.windll.kernel32.GetLastError() != 0:\n    #    raise ctypes.WinError()\n\n\ndef _scroll(clicks, x=None, y=None):\n    \"\"\"Send the mouse vertical scroll event to Windows by calling the\n    mouse_event() win32 function.\n\n    Args:\n      clicks (int): The amount of scrolling to do. A positive value is the mouse\n      wheel moving forward (scrolling up), a negative value is backwards (down).\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n\n    Returns:\n      None\n    \"\"\"\n    startx, starty = _position()\n    width, height = _size()\n\n    if x is None:\n        x = startx\n    else:\n        if x < 0:\n            x = 0\n        elif x >= width:\n            x = width - 1\n    if y is None:\n        y = starty\n    else:\n        if y < 0:\n            y = 0\n        elif y >= height:\n            y = height - 1\n\n    try:\n        _sendMouseEvent(MOUSEEVENTF_WHEEL, x, y, dwData=clicks)\n    except (PermissionError, OSError): # TODO: We need to figure out how to prevent these errors, see https://github.com/asweigart/pyautogui/issues/60\n            pass\n\n\ndef _hscroll(clicks, x, y):\n    \"\"\"Send the mouse horizontal scroll event to Windows by calling the\n    mouse_event() win32 function.\n\n    Args:\n      clicks (int): The amount of scrolling to do. A positive value is the mouse\n      wheel moving right, a negative value is moving left.\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n\n    Returns:\n      None\n    \"\"\"\n    return _scroll(clicks, x, y)\n\n\ndef _vscroll(clicks, x, y):\n    \"\"\"A wrapper for _scroll(), which does vertical scrolling.\n\n    Args:\n      clicks (int): The amount of scrolling to do. A positive value is the mouse\n      wheel moving forward (scrolling up), a negative value is backwards (down).\n      x (int): The x position of the mouse event.\n      y (int): The y position of the mouse event.\n\n    Returns:\n      None\n    \"\"\"\n    return _scroll(clicks, x, y)\n\n"
  },
  {
    "path": "pyautogui/_pyautogui_x11.py",
    "content": "# NOTE - It is a known issue that the keyboard-related functions don't work on Ubuntu VMs in Virtualbox.\n\nimport pyautogui\nimport sys\nimport os\nimport subprocess\nfrom pyautogui import LEFT, MIDDLE, RIGHT\n\nfrom Xlib.display import Display\nfrom Xlib import X\nfrom Xlib.ext.xtest import fake_input\nimport Xlib.XK\n\nBUTTON_NAME_MAPPING = {LEFT: 1, MIDDLE: 2, RIGHT: 3, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}\n\n\nif sys.platform in ('java', 'darwin', 'win32'):\n    raise Exception('The pyautogui_x11 module should only be loaded on a Unix system that supports X11.')\n\n#from pyautogui import *\n\n\"\"\"\nMuch of this code is based on information gleaned from Paul Barton's PyKeyboard in PyUserInput from 2013, itself derived from Akkana Peck's pykey in 2008 ( http://www.shallowsky.com/software/crikey/pykey-0.1 ), itself derived from her \"Crikey\" lib.\n\"\"\"\n\ndef _position():\n    \"\"\"Returns the current xy coordinates of the mouse cursor as a two-integer\n    tuple.\n\n    Returns:\n      (x, y) tuple of the current xy coordinates of the mouse cursor.\n    \"\"\"\n    coord = _display.screen().root.query_pointer()._data\n    return coord[\"root_x\"], coord[\"root_y\"]\n\n\ndef _size():\n    return _display.screen().width_in_pixels, _display.screen().height_in_pixels\n\n\n\ndef _vscroll(clicks, x=None, y=None):\n    clicks = int(clicks)\n    if clicks == 0:\n        return\n    elif clicks > 0:\n        button = 4 # scroll up\n    else:\n        button = 5 # scroll down\n\n    for i in range(abs(clicks)):\n        _click(x, y, button=button)\n\n\ndef _hscroll(clicks, x=None, y=None):\n    clicks = int(clicks)\n    if clicks == 0:\n        return\n    elif clicks > 0:\n        button = 7 # scroll right\n    else:\n        button = 6 # scroll left\n\n    for i in range(abs(clicks)):\n        _click(x, y, button=button)\n\n\ndef _scroll(clicks, x=None, y=None):\n    return _vscroll(clicks, x, y)\n\n\ndef _click(x, y, button):\n    assert button in BUTTON_NAME_MAPPING.keys(), \"button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)\"\n    button = BUTTON_NAME_MAPPING[button]\n\n    _mouseDown(x, y, button)\n    _mouseUp(x, y, button)\n\n\n_mouse_is_swapped_setting = None\n\n\ndef _mouse_is_swapped():\n    # TODO - for performance reasons, we only check the swapped mouse button\n    # setting from the OS once at start up, rather than every mouse click.\n    # Testing shows this takes about 0.02 seconds on my machine in a vm.\n    # This may change in the future.\n    global _mouse_is_swapped_setting\n    if _mouse_is_swapped_setting is None:\n        try:\n            proc = subprocess.Popen(['dconf', 'read', '/org/gnome/desktop/peripherals/mouse/left-handed'], stdout=subprocess.PIPE)\n            stdout_bytes, stderr_bytes = proc.communicate()\n            _mouse_is_swapped_setting = stdout_bytes.decode('utf-8') == 'true\\n'\n        except FileNotFoundError:\n            # The user is not running Gnome (the default window manager on Ubuntu) so just assume it's not swapped.\n            _mouse_is_swapped_setting = False\n    return _mouse_is_swapped_setting\n\n\ndef _moveTo(x, y):\n    fake_input(_display, X.MotionNotify, x=x, y=y)\n    _display.sync()\n\n\ndef _mouseDown(x, y, button):\n    _moveTo(x, y)\n    assert button in BUTTON_NAME_MAPPING.keys(), \"button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)\"\n    button = BUTTON_NAME_MAPPING[button]\n    fake_input(_display, X.ButtonPress, button)\n    _display.sync()\n\n\ndef _mouseUp(x, y, button):\n    _moveTo(x, y)\n    assert button in BUTTON_NAME_MAPPING.keys(), \"button argument not in ('left', 'middle', 'right', 4, 5, 6, 7)\"\n    button = BUTTON_NAME_MAPPING[button]\n    fake_input(_display, X.ButtonRelease, button)\n    _display.sync()\n\n\ndef _keyDown(key):\n    \"\"\"Performs a keyboard key press without the release. This will put that\n    key in a held down state.\n\n    NOTE: For some reason, this does not seem to cause key repeats like would\n    happen if a keyboard key was held down on a text field.\n\n    Args:\n      key (str): The key to be pressed down. The valid names are listed in\n      pyautogui.KEY_NAMES.\n\n    Returns:\n      None\n    \"\"\"\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    if type(key) == int:\n        fake_input(_display, X.KeyPress, key)\n        _display.sync()\n        return\n\n    needsShift = pyautogui.isShiftCharacter(key)\n    if needsShift:\n        fake_input(_display, X.KeyPress, keyboardMapping['shift'])\n\n    fake_input(_display, X.KeyPress, keyboardMapping[key])\n\n    if needsShift:\n        fake_input(_display, X.KeyRelease, keyboardMapping['shift'])\n    _display.sync()\n\n\ndef _keyUp(key):\n    \"\"\"Performs a keyboard key release (without the press down beforehand).\n\n    Args:\n      key (str): The key to be released up. The valid names are listed in\n      pyautogui.KEY_NAMES.\n\n    Returns:\n      None\n    \"\"\"\n\n    \"\"\"\n    Release a given character key. Also works with character keycodes as\n    integers, but not keysyms.\n    \"\"\"\n    if key not in keyboardMapping or keyboardMapping[key] is None:\n        return\n\n    if type(key) == int:\n        keycode = key\n    else:\n        keycode = keyboardMapping[key]\n\n    fake_input(_display, X.KeyRelease, keycode)\n    _display.sync()\n\n\n# Taken from PyKeyboard's ctor function.\n_display = Display(os.environ['DISPLAY'])\n\n\n\"\"\" Information for keyboardMapping derived from PyKeyboard's special_key_assignment() function.\n\nThe *KB dictionaries in pyautogui map a string that can be passed to keyDown(),\nkeyUp(), or press() into the code used for the OS-specific keyboard function.\n\nThey should always be lowercase, and the same keys should be used across all OSes.\"\"\"\nkeyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])\nkeyboardMapping.update({\n    'backspace':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),\n    '\\b':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),\n    'tab':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),\n    'enter':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),\n    'return':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),\n    'shift':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),\n    'ctrl':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),\n    'alt':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),\n    'pause':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Pause')),\n    'capslock':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Caps_Lock')),\n    'esc':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),\n    'escape':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),\n    'pgup':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),\n    'pgdn':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),\n    'pageup':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),\n    'pagedown':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),\n    'end':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('End')),\n    'home':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Home')),\n    'left':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Left')),\n    'up':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Up')),\n    'right':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Right')),\n    'down':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Down')),\n    'select':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Select')),\n    'print':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),\n    'execute':           _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Execute')),\n    'prtsc':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),\n    'prtscr':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),\n    'prntscrn':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),\n    'printscreen':       _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),\n    'insert':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Insert')),\n    'del':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),\n    'delete':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),\n    'help':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Help')),\n    'win':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),\n    'winleft':           _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),\n    'winright':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_R')),\n    'apps':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Menu')),\n    'num0':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_0')),\n    'num1':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_1')),\n    'num2':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_2')),\n    'num3':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_3')),\n    'num4':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_4')),\n    'num5':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_5')),\n    'num6':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_6')),\n    'num7':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_7')),\n    'num8':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_8')),\n    'num9':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_9')),\n    'multiply':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Multiply')),\n    'add':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Add')),\n    'separator':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Separator')),\n    'subtract':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Subtract')),\n    'decimal':           _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Decimal')),\n    'divide':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Divide')),\n    'f1':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F1')),\n    'f2':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F2')),\n    'f3':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F3')),\n    'f4':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F4')),\n    'f5':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F5')),\n    'f6':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F6')),\n    'f7':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F7')),\n    'f8':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F8')),\n    'f9':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F9')),\n    'f10':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F10')),\n    'f11':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F11')),\n    'f12':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F12')),\n    'f13':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F13')),\n    'f14':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F14')),\n    'f15':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F15')),\n    'f16':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F16')),\n    'f17':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F17')),\n    'f18':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F18')),\n    'f19':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F19')),\n    'f20':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F20')),\n    'f21':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F21')),\n    'f22':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F22')),\n    'f23':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F23')),\n    'f24':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('F24')),\n    'numlock':           _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Num_Lock')),\n    'scrolllock':        _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Scroll_Lock')),\n    'shiftleft':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),\n    'shiftright':        _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_R')),\n    'ctrlleft':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),\n    'ctrlright':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_R')),\n    'altleft':           _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),\n    'altright':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_R')),\n    # These are added because unlike a-zA-Z0-9, the single characters do not have a\n    ' ': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),\n    'space': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),\n    '\\t': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),\n    '\\n': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),  # for some reason this needs to be cr, not lf\n    '\\r': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),\n    '\\e': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),\n    '!': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('exclam')),\n    '#': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('numbersign')),\n    '%': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('percent')),\n    '$': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('dollar')),\n    '&': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('ampersand')),\n    '\"': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('quotedbl')),\n    \"'\": _display.keysym_to_keycode(Xlib.XK.string_to_keysym('apostrophe')),\n    '(': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenleft')),\n    ')': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenright')),\n    '*': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asterisk')),\n    '=': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('equal')),\n    '+': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('plus')),\n    ',': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('comma')),\n    '-': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('minus')),\n    '.': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('period')),\n    '/': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('slash')),\n    ':': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('colon')),\n    ';': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('semicolon')),\n    '<': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('less')),\n    '>': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('greater')),\n    '?': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('question')),\n    '@': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('at')),\n    '[': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketleft')),\n    ']': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketright')),\n    '\\\\': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('backslash')),\n    '^': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciicircum')),\n    '_': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('underscore')),\n    '`': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('grave')),\n    '{': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceleft')),\n    '|': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('bar')),\n    '}': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceright')),\n    '~': _display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciitilde')),\n})\n\n# Trading memory for time\" populate winKB so we don't have to call VkKeyScanA each time.\nfor c in \"\"\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\"\"\":\n    keyboardMapping[c] = _display.keysym_to_keycode(Xlib.XK.string_to_keysym(c))\n"
  },
  {
    "path": "setup.py",
    "content": "import io\nimport os\nimport re\nfrom setuptools import setup\n\nscriptFolder = os.path.dirname(os.path.realpath(__file__))\nos.chdir(scriptFolder)\n\n# Find version info from module (without importing the module):\nwith open('pyautogui/__init__.py', 'r') as fd:\n    version = re.search(r'^__version__\\s*=\\s*[\\'\"]([^\\'\"]*)[\\'\"]',\n                        fd.read(), re.MULTILINE).group(1)\n\n# Use the README.md content for the long description:\nwith io.open(\"README.md\", encoding=\"utf-8\") as fileObj:\n    long_description = fileObj.read()\n\nsetup(\n    name='PyAutoGUI',\n    version=version,\n    url='https://github.com/asweigart/pyautogui',\n    author='Al Sweigart',\n    author_email='al@inventwithpython.com',\n    description=('PyAutoGUI lets Python control the mouse and keyboard, and other GUI automation tasks. For Windows, macOS, and Linux, on Python 3 and 2.'),\n    long_description=long_description,\n    long_description_content_type=\"text/markdown\",\n    license='BSD',\n    packages=['pyautogui'],\n    test_suite='tests',\n    install_requires=['pyobjc-core;platform_system==\"Darwin\"',\n                      'pyobjc-framework-quartz;platform_system==\"Darwin\"',\n                      'python3-Xlib;platform_system==\"Linux\" and python_version>=\"3.0\"',\n                      'python-xlib;platform_system==\"Linux\" and python_version<\"3.0\"',\n                      'pymsgbox',\n                      'pytweening>=1.0.4',\n                      'pyscreeze>=0.1.21',\n                      'pygetwindow>=0.0.5',\n                      'mouseinfo'],\n    keywords=\"gui automation test testing keyboard mouse cursor click press keystroke control\",\n    classifiers=[\n        'Development Status :: 4 - Beta',\n        'Environment :: Win32 (MS Windows)',\n        'Environment :: X11 Applications',\n        'Environment :: MacOS X',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: BSD License',\n        'Operating System :: OS Independent',\n        'Programming Language :: Python',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.1',\n        'Programming Language :: Python :: 3.2',\n        'Programming Language :: Python :: 3.3',\n        'Programming Language :: Python :: 3.4',\n        'Programming Language :: Python :: 3.5',\n        'Programming Language :: Python :: 3.6',\n        'Programming Language :: Python :: 3.7',\n        'Programming Language :: Python :: 3.8',\n        'Programming Language :: Python :: 3.9',\n        'Programming Language :: Python :: 3.10',\n        'Programming Language :: Python :: 3.11',\n    ],\n)\n\n"
  },
  {
    "path": "tests/test_pyautogui.py",
    "content": "from __future__ import division, print_function\n\nimport os\nimport random\nimport sys\nimport threading\nimport time\nimport unittest\nimport doctest\nfrom collections import namedtuple  # Added in Python 2.6.\n\nimport pyautogui\n\n# Make the cwd the folder that this test_pyautogui.py file resides in:\nscriptFolder = os.path.dirname(os.path.realpath(__file__))\nos.chdir(scriptFolder)\n\nrunningOnPython2 = sys.version_info[0] == 2\n\nif runningOnPython2:\n    INPUT_FUNC = raw_input\nelse:\n    INPUT_FUNC = input\n\n\ntry:\n    import pytweening\nexcept:\n    assert False, \"The PyTweening module must be installed to complete the tests: pip install pytweening\"\n\ntry:\n    import pyscreeze\nexcept:\n    assert False, \"The PyScreeze module must be installed to complete the tests: pip install pyscreeze\"\n\n\"\"\"\n# TODO - pygetwindow is Windows-only for now, so don't require it for testing just yet.\ntry:\n    import pygetwindow\nexcept:\n    assert False, 'The PyGetWindow module must be installed to complete the tests: pip install pygetwindow'\n\"\"\"\n\n# TODO - note that currently most of the click-related functionality is not tested.\n\n\nclass P(namedtuple(\"P\", [\"x\", \"y\"])):\n    \"\"\"Simple, immutable, 2D point/vector class, including some basic\n    arithmetic functions.\n    \"\"\"\n\n    def __str__(self):\n        return \"{0},{1}\".format(self.x, self.y)\n\n    def __repr__(self):\n        return \"P({0}, {1})\".format(self.x, self.y)\n\n    def __eq__(self, other):\n        return self.x == other.x and self.y == other.y\n\n    def __ne__(self, other):\n        return self.x != other.x and self.y != other.y\n\n    def __add__(self, other):\n        return P(self.x + other.x, self.y + other.y)\n\n    def __sub__(self, other):\n        return P(self.x - other.x, self.y - other.y)\n\n    def __mul__(self, other):\n        return P(self.x * other, self.y * other)\n\n    def __rmul__(self, other):\n        return self.__mul__(other)\n\n    def __floordiv__(self, other):\n        return P(self.x // other, self.y // other)\n\n    def __truediv__(self, other):\n        return P(self.x / other, self.y / other)\n\n    def __neg__(self):\n        return P(-self.x, -self.y)\n\n    def __pos__(self):\n        return self\n\n    def __neg__(self):\n        return P(abs(self.x), abs(self.y))\n\n\nclass TestGeneral(unittest.TestCase):\n    def setUp(self):\n        self.oldFailsafeSetting = pyautogui.FAILSAFE\n        pyautogui.FAILSAFE = False\n        pyautogui.moveTo(42, 42)  # make sure failsafe isn't triggered during this test\n        pyautogui.FAILSAFE = True\n\n    def tearDown(self):\n        pyautogui.FAILSAFE = self.oldFailsafeSetting\n\n    def test_accessibleNames(self):\n        # Check that all the functions are defined.\n\n        # mouse-related API\n        pyautogui.moveTo\n        pyautogui.moveRel\n        pyautogui.dragTo\n        pyautogui.dragRel\n        pyautogui.mouseDown\n        pyautogui.mouseUp\n        pyautogui.click\n        pyautogui.rightClick\n        pyautogui.doubleClick\n        pyautogui.tripleClick\n\n        # keyboard-related API\n        pyautogui.typewrite\n        pyautogui.hotkey\n        pyautogui.keyDown\n        pyautogui.keyUp\n        pyautogui.press\n        pyautogui.hold\n\n        # The functions implemented in the platform-specific modules should also show up in the pyautogui namespace:\n        pyautogui.position\n        pyautogui.size\n        pyautogui.scroll\n        pyautogui.hscroll\n        pyautogui.vscroll\n\n        # util API\n        pyautogui.KEYBOARD_KEYS\n        pyautogui.isShiftCharacter\n\n        # Screenshot-related API\n        pyautogui.locateAll\n        pyautogui.locate\n        pyautogui.locateOnScreen\n        pyautogui.locateAllOnScreen\n        pyautogui.locateCenterOnScreen\n        pyautogui.center\n        pyautogui.pixelMatchesColor\n        pyautogui.pixel\n        pyautogui.screenshot\n        #pyautogui.grab # grab() was removed, use screenshot()\n\n        # TODO(denilsonsa): I believe we should get rid of these symbols. If someone wants tweening, import pytweening module instead!\n        # Tweening-related API\n        pyautogui.getPointOnLine\n        pyautogui.linear\n        pyautogui.easeInQuad\n        pyautogui.easeOutQuad\n        pyautogui.easeInOutQuad\n        pyautogui.easeInCubic\n        pyautogui.easeOutCubic\n        pyautogui.easeInOutCubic\n        pyautogui.easeInQuart\n        pyautogui.easeOutQuart\n        pyautogui.easeInOutQuart\n        pyautogui.easeInQuint\n        pyautogui.easeOutQuint\n        pyautogui.easeInOutQuint\n        pyautogui.easeInSine\n        pyautogui.easeOutSine\n        pyautogui.easeInOutSine\n        pyautogui.easeInExpo\n        pyautogui.easeOutExpo\n        pyautogui.easeInOutExpo\n        pyautogui.easeInCirc\n        pyautogui.easeOutCirc\n        pyautogui.easeInOutCirc\n        pyautogui.easeInElastic\n        pyautogui.easeOutElastic\n        pyautogui.easeInOutElastic\n        pyautogui.easeInBack\n        pyautogui.easeOutBack\n        pyautogui.easeInOutBack\n        pyautogui.easeInBounce\n        pyautogui.easeOutBounce\n        pyautogui.easeInOutBounce\n\n    def test_size(self):\n        width, height = pyautogui.size()\n\n        self.assertTrue(isinstance(width, int), \"Type of width is %s\" % (type(width)))\n        self.assertTrue(isinstance(height, int), \"Type of height is %s\" % (type(height)))\n        self.assertTrue(width > 0, \"Width is set to %s\" % (width))\n        self.assertTrue(height > 0, \"Height is set to %s\" % (height))\n\n    def test_position(self):\n        mousex, mousey = pyautogui.position()\n\n        self.assertTrue(isinstance(mousex, int), \"Type of mousex is %s\" % (type(mousex)))\n        self.assertTrue(isinstance(mousey, int), \"Type of mousey is %s\" % (type(mousey)))\n\n        # Test passing x and y arguments to position().\n        pyautogui.moveTo(mousex + 1, mousey + 1)\n        x, y = pyautogui.position(mousex, None)\n        self.assertEqual(x, mousex)\n        self.assertNotEqual(y, mousey)\n\n        x, y = pyautogui.position(None, mousey)\n        self.assertNotEqual(x, mousex)\n        self.assertEqual(y, mousey)\n\n    def test_onScreen(self):\n        zero = P(0, 0)\n        xone = P(1, 0)\n        yone = P(0, 1)\n        size = P(*pyautogui.size())\n        half = size / 2\n\n        on_screen = [zero, zero + xone, zero + yone, zero + xone + yone, half, size - xone - yone]\n        off_screen = [zero - xone, zero - yone, zero - xone - yone, size - xone, size - yone, size]\n\n        for value, coords in [(True, on_screen), (False, off_screen)]:\n            for coord in coords:\n                self.assertEqual(\n                    value,\n                    pyautogui.onScreen(*coord),\n                    \"onScreen({0}, {1}) should be {2}\".format(coord.x, coord.y, value),\n                )\n                self.assertEqual(\n                    value,\n                    pyautogui.onScreen(list(coord)),\n                    \"onScreen([{0}, {1}]) should be {2}\".format(coord.x, coord.y, value),\n                )\n                self.assertEqual(\n                    value,\n                    pyautogui.onScreen(tuple(coord)),\n                    \"onScreen(({0}, {1})) should be {2}\".format(coord.x, coord.y, value),\n                )\n                self.assertEqual(\n                    value, pyautogui.onScreen(coord), \"onScreen({0}) should be {1}\".format(repr(coord), value)\n                )\n\n        # These raise PyAutoGUIException.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui.onScreen([0, 0], 0)\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui.onScreen((0, 0), 0)\n\n    def test_pause(self):\n        oldValue = pyautogui.PAUSE\n\n        startTime = time.time()\n        pyautogui.PAUSE = 0.35  # there should be a 0.35 second pause after each call\n        pyautogui.moveTo(1, 1)\n        pyautogui.moveRel(0, 1)\n        pyautogui.moveTo(1, 1)\n\n        elapsed = time.time() - startTime\n        self.assertTrue(1.0 < elapsed < 1.1, \"Took %s seconds, expected 1.0 < 1.1 seconds.\" % (elapsed))\n\n        pyautogui.PAUSE = oldValue  # restore the old PAUSE value\n\n\nclass TestHelperFunctions(unittest.TestCase):\n    def test__normalizeXYArgs(self):\n        self.assertEqual(pyautogui._normalizeXYArgs(1, 2), pyautogui.Point(x=1, y=2))\n        self.assertEqual(pyautogui._normalizeXYArgs((1, 2), None), pyautogui.Point(x=1, y=2))\n        self.assertEqual(pyautogui._normalizeXYArgs([1, 2], None), pyautogui.Point(x=1, y=2))\n\n        pyautogui.useImageNotFoundException()\n        with self.assertRaises(pyautogui.ImageNotFoundException):\n            pyautogui._normalizeXYArgs(\"100x100blueimage.png\", None)\n        pyautogui.useImageNotFoundException(False)\n        self.assertEqual(pyautogui._normalizeXYArgs(\"100x100blueimage.png\", None), None)\n\n\nclass TestDoctests(unittest.TestCase):\n    def test_doctests(self):\n        doctest.testmod(pyautogui)\n\n\nclass TestMouse(unittest.TestCase):\n    # NOTE - The user moving the mouse during many of these tests will cause them to fail.\n\n    # There is no need to test all tweening functions.\n    TWEENS = [\n        \"linear\",\n        \"easeInElastic\",\n        \"easeOutElastic\",\n        \"easeInOutElastic\",\n        \"easeInBack\",\n        \"easeOutBack\",\n        \"easeInOutBack\",\n    ]\n\n    def setUp(self):\n        self.oldFailsafeSetting = pyautogui.FAILSAFE\n        self.center = P(*pyautogui.size()) // 2\n\n        pyautogui.FAILSAFE = False\n        pyautogui.moveTo(*self.center)  # make sure failsafe isn't triggered during this test\n        pyautogui.FAILSAFE = True\n\n    def tearDown(self):\n        pyautogui.FAILSAFE = self.oldFailsafeSetting\n\n    def test_moveTo(self):\n        # moving the mouse\n        desired = self.center\n        pyautogui.moveTo(*desired)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # no coordinate specified (should be a NO-OP)\n        pyautogui.moveTo(None, None)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # moving the mouse to a new location\n        desired += P(42, 42)\n        pyautogui.moveTo(*desired)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # moving the mouse over time (1/5 second)\n        desired -= P(42, 42)\n        pyautogui.moveTo(desired.x, desired.y, duration=0.2)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a list instead of separate x and y.\n        desired += P(42, 42)\n        pyautogui.moveTo(list(desired))\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a tuple instead of separate x and y.\n        desired += P(42, 42)\n        pyautogui.moveTo(tuple(desired))\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a sequence-like object instead of separate x and y.\n        desired -= P(42, 42)\n        pyautogui.moveTo(desired)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n    def test_moveToWithTween(self):\n        origin = self.center - P(100, 100)\n        destination = self.center + P(100, 100)\n\n        def resetMouse():\n            pyautogui.moveTo(*origin)\n            mousepos = P(*pyautogui.position())\n            self.assertEqual(mousepos, origin)\n\n        for tweenName in self.TWEENS:\n            tweenFunc = getattr(pyautogui, tweenName)\n            resetMouse()\n            pyautogui.moveTo(destination.x, destination.y, duration=pyautogui.MINIMUM_DURATION * 2, tween=tweenFunc)\n            mousepos = P(*pyautogui.position())\n            self.assertEqual(\n                mousepos,\n                destination,\n                \"%s tween move failed. mousepos set to %s instead of %s\" % (tweenName, mousepos, destination),\n            )\n\n    def test_moveRel(self):\n        # start at the center\n        desired = self.center\n        pyautogui.moveTo(*desired)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move down and right\n        desired += P(42, 42)\n        pyautogui.moveRel(42, 42)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move up and left\n        desired -= P(42, 42)\n        pyautogui.moveRel(-42, -42)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move right\n        desired += P(42, 0)\n        pyautogui.moveRel(42, 0)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move down\n        desired += P(0, 42)\n        pyautogui.moveRel(0, 42)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move left\n        desired += P(-42, 0)\n        pyautogui.moveRel(-42, 0)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # move up\n        desired += P(0, -42)\n        pyautogui.moveRel(0, -42)\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a list instead of separate x and y.\n        desired += P(42, 42)\n        pyautogui.moveRel([42, 42])\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a tuple instead of separate x and y.\n        desired -= P(42, 42)\n        pyautogui.moveRel((-42, -42))\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n        # Passing a sequence-like object instead of separate x and y.\n        desired += P(42, 42)\n        pyautogui.moveRel(P(42, 42))\n        mousepos = P(*pyautogui.position())\n        self.assertEqual(mousepos, desired)\n\n    def test_moveRelWithTween(self):\n        origin = self.center - P(100, 100)\n        delta = P(200, 200)\n        destination = origin + delta\n\n        def resetMouse():\n            pyautogui.moveTo(*origin)\n            mousepos = P(*pyautogui.position())\n            self.assertEqual(mousepos, origin)\n\n        for tweenName in self.TWEENS:\n            tweenFunc = getattr(pyautogui, tweenName)\n            resetMouse()\n            pyautogui.moveRel(delta.x, delta.y, duration=pyautogui.MINIMUM_DURATION * 2, tween=tweenFunc)\n            mousepos = P(*pyautogui.position())\n            self.assertEqual(\n                mousepos,\n                destination,\n                \"%s tween move failed. mousepos set to %s instead of %s\" % (tweenName, mousepos, destination),\n            )\n\n    def test_scroll(self):\n        # TODO - currently this just checks that scrolling doesn't result in an error.\n        pyautogui.scroll(1)\n        pyautogui.scroll(-1)\n        pyautogui.hscroll(1)\n        pyautogui.hscroll(-1)\n        pyautogui.vscroll(1)\n        pyautogui.vscroll(-1)\n\n\n    def test_mouse_button_swap(self):\n        pass  # TODO - I'm not even sure how I could test this in an automated way. We'd need a separate GUI app.\n\n\nclass TestRun(unittest.TestCase):\n    def test_getNumberToken(self):\n        self.assertEqual(pyautogui._getNumberToken(\"5hello\"), \"5\")\n        self.assertEqual(pyautogui._getNumberToken(\"-5hello\"), \"-5\")\n        self.assertEqual(pyautogui._getNumberToken(\"+5hello\"), \"+5\")\n        self.assertEqual(pyautogui._getNumberToken(\"5.5hello\"), \"5.5\")\n        self.assertEqual(pyautogui._getNumberToken(\"+5.5hello\"), \"+5.5\")\n        self.assertEqual(pyautogui._getNumberToken(\"-5.5hello\"), \"-5.5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  5hello\"), \"  5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  -5hello\"), \"  -5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  +5hello\"), \"  +5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  5.5hello\"), \"  5.5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  +5.5hello\"), \"  +5.5\")\n        self.assertEqual(pyautogui._getNumberToken(\"  -5.5hello\"), \"  -5.5\")\n\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getNumberToken(\"\")  # Blank string and no number.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getNumberToken(\"hello\")  # Missing a number.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getNumberToken(\"    \")  # Missing a number.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getNumberToken(\"hello 42\")  # Number is not at the start.\n\n    def test_getQuotedStringToken(self):\n        self.assertEqual(pyautogui._getQuotedStringToken(\"'hello'world\"), \"'hello'\")\n        self.assertEqual(pyautogui._getQuotedStringToken(\"''world\"), \"''\")\n        self.assertEqual(pyautogui._getQuotedStringToken(\"  'hello'world\"), \"  'hello'\")\n\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"xyz\")  # No quotes.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"xyz\")  # No quotes.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"  xyz\")  # No quotes, spaces in front.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"'xyz\")  # Start quote only.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"xyz'\")  # End quote only.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken('\"xyz\"')  # Double quotes don't count.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"\")  # Blank string.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getQuotedStringToken(\"xyz 'hello'\")  # Quoted string is not at the start.\n\n    def test_getCommaToken(self):\n        self.assertEqual(pyautogui._getCommaToken(\",\"), \",\")\n        self.assertEqual(pyautogui._getCommaToken(\"  ,\"), \"  ,\")\n\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getCommaToken(\"\")  # Blank string.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getCommaToken(\"hello,\")  # Comma is not at the start.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getCommaToken(\"hello\")  # No comma.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getCommaToken(\"    \")  # No comma.\n\n    def test_getParensCommandStrToken(self):\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"()\"), \"()\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"  ()\"), \"  ()\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"()hello\"), \"()\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"  ()hello\"), \"  ()\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"(hello)world\"), \"(hello)\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"  (hello)world\"), \"  (hello)\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"(he(ll)(o))world\"), \"(he(ll)(o))\")\n        self.assertEqual(pyautogui._getParensCommandStrToken(\"  (he(ll)(o))world\"), \"  (he(ll)(o))\")\n\n        self.assertEqual(\n            pyautogui._getParensCommandStrToken(\"(he(ll)(o)))world\"), \"(he(ll)(o))\"\n        )  # Extra close parentheses.\n        self.assertEqual(\n            pyautogui._getParensCommandStrToken(\"  (he(ll)(o)))world\"), \"  (he(ll)(o))\"\n        )  # Extra close parentheses.\n\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\"\")  # Blank string.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\"  \")  # No parens.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\"hello\")  # No parens\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\" (\")  # No close parenthesis.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\"(he(ll)o\")  # Not enough close parentheses.\n        with self.assertRaises(pyautogui.PyAutoGUIException):\n            pyautogui._getParensCommandStrToken(\"\")  # Blank string.\n\n    def test_tokenizeCommandStr(self):\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"\"), [])  # Empty command string.\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  \"), [])  # Whitespace only command string.\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"c\"), [\"c\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  c  \"), [\"c\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"ccc\"), [\"c\", \"c\", \"c\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  c  c  c  \"), [\"c\", \"c\", \"c\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"clmr\"), [\"c\", \"l\", \"m\", \"r\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"susdss\"), [\"su\", \"sd\", \"ss\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\" su sd ss \"), [\"su\", \"sd\", \"ss\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"clmrsusdss\"), [\"c\", \"l\", \"m\", \"r\", \"su\", \"sd\", \"ss\"])\n\n        # Do a whole bunch of tests with random no-argument commands with random whitespace.\n        random.seed(42)\n        for i in range(100):\n            commands = []\n            commands.extend([\"c\"] * random.randint(0, 9))\n            commands.extend([\"l\"] * random.randint(0, 9))\n            commands.extend([\"m\"] * random.randint(0, 9))\n            commands.extend([\"r\"] * random.randint(0, 9))\n            commands.extend([\"su\"] * random.randint(0, 9))\n            commands.extend([\"sd\"] * random.randint(0, 9))\n            commands.extend([\"ss\"] * random.randint(0, 9))\n            random.shuffle(commands)\n            commandStr = []\n            for command in commands:\n                commandStr.append(command)\n                commandStr.append(\" \" * random.randint(0, 9))\n            commandStr = \"\".join(commandStr)\n            self.assertEqual(pyautogui._tokenizeCommandStr(commandStr), commands)\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g10,10\"), [\"g\", \"10\", \"10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g 10,10\"), [\"g\", \"10\", \"10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g10 ,10\"), [\"g\", \"10\", \"10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g10, 10\"), [\"g\", \"10\", \"10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\" g 10 , 10 \"), [\"g\", \"10\", \"10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  g  10  ,  10  \"), [\"g\", \"10\", \"10\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g+10,+10\"), [\"g\", \"+10\", \"+10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g +10,+10\"), [\"g\", \"+10\", \"+10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g+10 ,+10\"), [\"g\", \"+10\", \"+10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g+10, +10\"), [\"g\", \"+10\", \"+10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\" g +10 , +10 \"), [\"g\", \"+10\", \"+10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  g  +10  ,  +10  \"), [\"g\", \"+10\", \"+10\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g-10,-10\"), [\"g\", \"-10\", \"-10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g -10,-10\"), [\"g\", \"-10\", \"-10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g-10 ,-10\"), [\"g\", \"-10\", \"-10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"g-10, -10\"), [\"g\", \"-10\", \"-10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\" g -10 , -10 \"), [\"g\", \"-10\", \"-10\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"  g  -10  ,  -10  \"), [\"g\", \"-10\", \"-10\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"d10,10\"), [\"d\", \"10\", \"10\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"d1,2g3,4\"), [\"d\", \"1\", \"2\", \"g\", \"3\", \"4\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"w'hello'\"), [\"w\", \"hello\"])\n\n        self.assertEqual(\n            pyautogui._tokenizeCommandStr(\"d1,2w'hello'g3,4\"), [\"d\", \"1\", \"2\", \"w\", \"hello\", \"g\", \"3\", \"4\"]\n        )\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"s42\"), [\"s\", \"42\"])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"s42.3\"), [\"s\", \"42.3\"])\n\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"f10(c)\"), [\"f\", \"10\", [\"c\"]])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"f10(lmr)\"), [\"f\", \"10\", [\"l\", \"m\", \"r\"]])\n        self.assertEqual(pyautogui._tokenizeCommandStr(\"f10(f5(cc))\"), [\"f\", \"10\", [\"f\", \"5\", [\"c\", \"c\"]]])\n\n        # TODO add negative cases\n\n        # TODO add mocks for pyautogui for this.\n\n\nclass TypewriteThread(threading.Thread):\n    def __init__(self, msg, interval=0.0):\n        super(TypewriteThread, self).__init__()\n        self.msg = msg\n        self.interval = interval\n\n    def run(self):\n        time.sleep(0.25)  # NOTE: BE SURE TO ACCOUNT FOR THIS QUARTER SECOND FOR TIMING TESTS!\n        pyautogui.typewrite(self.msg, self.interval)\n\n\nclass PressThread(threading.Thread):\n    def __init__(self, keysArg):\n        super(PressThread, self).__init__()\n        self.keysArg = keysArg\n\n    def run(self):\n        time.sleep(0.25)  # NOTE: BE SURE TO ACCOUNT FOR THIS QUARTER SECOND FOR TIMING TESTS!\n        pyautogui.press(self.keysArg)\n\n\nclass HoldThread(threading.Thread):\n    def __init__(self, holdKeysArg, pressKeysArg=None):\n        super(HoldThread, self).__init__()\n        self.holdKeysArg = holdKeysArg\n        self.pressKeysArg = pressKeysArg\n\n\n    def run(self):\n        time.sleep(0.25)  # NOTE: BE SURE TO ACCOUNT FOR THIS QUARTER SECOND FOR TIMING TESTS!\n        with pyautogui.hold(self.holdKeysArg):\n            if self.pressKeysArg is not None:\n                pyautogui.press(self.pressKeysArg)\n            else:\n                pass\n\n\nclass TestKeyboard(unittest.TestCase):\n    # NOTE: The terminal window running this script must be in focus during the keyboard tests.\n    # You cannot run this as a scheduled task or remotely.\n\n    def setUp(self):\n        self.oldFailsafeSetting = pyautogui.FAILSAFE\n        pyautogui.FAILSAFE = False\n        pyautogui.moveTo(42, 42)  # make sure failsafe isn't triggered during this test\n        pyautogui.FAILSAFE = True\n\n    def tearDown(self):\n        pyautogui.FAILSAFE = self.oldFailsafeSetting\n\n    def test_typewrite(self):\n        # 'Hello world!\\n' test\n        t = TypewriteThread(\"Hello world!\\n\")\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"Hello world!\")\n\n        # 'Hello world!\\n' as a list argument\n        t = TypewriteThread(list(\"Hello world!\\n\"))\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"Hello world!\")\n\n        # All printable ASCII characters test\n        allKeys = []\n        for c in range(32, 127):\n            allKeys.append(chr(c))\n        allKeys = \"\".join(allKeys)\n\n        t = TypewriteThread(allKeys + \"\\n\")\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, allKeys)\n\n    def checkForValidCharacters(self, msg):\n        for c in msg:\n            self.assertTrue(pyautogui.isValidKey(c), '\"%c\" is not a valid key on platform %s' % (c, sys.platform))\n\n    def test_typewrite_slow(self):\n\n        # Test out the interval parameter to make sure it adds pauses.\n        t = TypewriteThread(\"Hello world!\\n\", 0.1)\n        startTime = time.time()\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"Hello world!\")\n        elapsed = time.time() - startTime\n        self.assertTrue(1.0 < elapsed < 2.0, \"Took %s seconds, expected 1.0 < x 2.0 seconds.\" % (elapsed))\n\n    def test_typewrite_editable(self):\n        # Backspace test\n        t = TypewriteThread([\"a\", \"b\", \"c\", \"\\b\", \"backspace\", \"x\", \"y\", \"z\", \"\\n\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"axyz\")\n\n        # TODO - Currently the arrow keys don't seem to work entirely correctly on OS X.\n        if sys.platform != \"darwin\":\n            # Arrow key test\n            t = TypewriteThread([\"a\", \"b\", \"c\", \"left\", \"left\", \"right\", \"x\", \"\\n\"])\n            t.start()\n            response = INPUT_FUNC()\n            self.assertEqual(response, \"abxc\")\n\n        # Del key test\n        t = TypewriteThread([\"a\", \"b\", \"c\", \"left\", \"left\", \"left\", \"del\", \"delete\", \"\\n\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"c\")\n\n        # Home and end key test\n        t = TypewriteThread([\"a\", \"b\", \"c\", \"home\", \"x\", \"end\", \"z\", \"\\n\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"xabcz\")\n\n    def test_press(self):\n        # '' test\n        t = PressThread(\"enter\")\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"\")\n\n        # 'a' test, also test sending list of 1- and multi-length strings\n        t = PressThread([\"a\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"a\")\n\n        # 'ba' test, also test sending list of 1- and multi-length strings\n        t = PressThread([\"a\", \"left\", \"b\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"ba\")\n\n    def test_hold(self):\n        # '' test\n        t = HoldThread(\"enter\")\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"\")\n\n        # 'a' test, also test sending list of 1- and multi-length strings\n        t = HoldThread([\"a\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"a\")\n\n        # 'ba' test, also test sending list of 1- and multi-length strings\n        t = HoldThread([\"a\", \"left\", \"b\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"ba\")\n\n    def test_press_during_hold(self):\n        # '' test\n        t = HoldThread(\"shift\", \"enter\")\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"\")\n\n        # 'a' test, also test sending list of 1- and multi-length strings\n        t = HoldThread(\"shift\", [\"a\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"A\")\n\n        # 'ab' test, also test sending list of 1- and multi-length strings\n        t = HoldThread(\"shift\", [\"a\", \"b\", \"enter\"])\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"AB\")\n\n    def test_typewrite_space(self):\n        # Backspace test\n        t = TypewriteThread([\"space\", \" \", \"\\n\"])  # test both 'space' and ' '\n        t.start()\n        response = INPUT_FUNC()\n        self.assertEqual(response, \"  \")\n\n    def test_isShiftCharacter(self):\n        for char in \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" + '~!@#$%^&*()_+{}|:\"<>?':\n            self.assertTrue(pyautogui.isShiftCharacter(char))\n        for char in \"abcdefghijklmnopqrstuvwxyz\" + \" `1234567890-=,./;'[]\\\\\":\n            self.assertFalse(pyautogui.isShiftCharacter(char))\n\n\nclass TestFailSafe(unittest.TestCase):\n    def test_failsafe(self):\n        self.oldFailsafeSetting = pyautogui.FAILSAFE\n\n        pyautogui.moveTo(1, 1)  # make sure mouse is not in failsafe position to begin with\n        for x, y in pyautogui.FAILSAFE_POINTS:\n            pyautogui.FAILSAFE = True\n            # When move(), moveTo(), drag(), or dragTo() moves the mouse to a\n            # failsafe point, it shouldn't raise the fail safe. (This would\n            # be annoying. Only a human moving the mouse to a failsafe point\n            # should trigger the failsafe.)\n            pyautogui.moveTo(x, y)\n\n            pyautogui.FAILSAFE = False\n            pyautogui.moveTo(1, 1)  # make sure mouse is not in failsafe position to begin with (for the next iteration)\n\n        pyautogui.moveTo(1, 1)  # make sure mouse is not in failsafe position to begin with\n        for x, y in pyautogui.FAILSAFE_POINTS:\n            pyautogui.FAILSAFE = True\n            pyautogui.moveTo(x, y)  # This line should not cause the fail safe exception to be raised.\n\n            # A second pyautogui function call to do something while the cursor is in a fail safe point SHOULD raise the failsafe:\n            self.assertRaises(pyautogui.FailSafeException, pyautogui.press, \"esc\")\n\n            pyautogui.FAILSAFE = False\n            pyautogui.moveTo(1, 1)  # make sure mouse is not in failsafe position to begin with (for the next iteration)\n\n        for x, y in pyautogui.FAILSAFE_POINTS:\n            pyautogui.FAILSAFE = False\n            pyautogui.moveTo(x, y)  # This line should not cause the fail safe exception to be raised.\n\n            # This line shouldn't cause a failsafe to trigger because FAILSAFE is set to False.\n            pyautogui.press(\"esc\")\n\n        pyautogui.FAILSAFE = self.oldFailsafeSetting\n\n\nclass TestPyScreezeFunctions(unittest.TestCase):\n    def test_locateFunctions(self):\n        # TODO - for now, we only test that the \"return None\" and \"raise pyautogui.ImageNotFoundException\" is raised.\n\n        pyautogui.useImageNotFoundException()\n        with self.assertRaises(pyautogui.ImageNotFoundException):\n            pyautogui.locate(\"100x100blueimage.png\", \"100x100redimage.png\")\n        # Commenting out the locateAll*() functions because they return generators, even if the image can't be found. Should they instead raise an exception? This is a question for pyscreeze's design.\n        # with self.assertRaises(pyautogui.ImageNotFoundException):\n        #    pyautogui.locateAll('100x100blueimage.png', '100x100redimage.png')\n\n        # with self.assertRaises(pyautogui.ImageNotFoundException):\n        #    pyautogui.locateAllOnScreen('100x100blueimage.png') # NOTE: This test fails if there is a blue square visible on the screen.\n        with self.assertRaises(pyautogui.ImageNotFoundException):\n            pyautogui.locateOnScreen(\n                \"100x100blueimage.png\"\n            )  # NOTE: This test fails if there is a blue square visible on the screen.\n        with self.assertRaises(pyautogui.ImageNotFoundException):\n            pyautogui.locateCenterOnScreen(\n                \"100x100blueimage.png\"\n            )  # NOTE: This test fails if there is a blue square visible on the screen.\n\n        pyautogui.useImageNotFoundException(False)\n        self.assertEqual(pyautogui.locate(\"100x100blueimage.png\", \"100x100redimage.png\"), None)\n        # self.assertEqual(pyautogui.locateAll('100x100blueimage.png', '100x100redimage.png'), None)\n        # self.assertEqual(pyautogui.locateAllOnScreen('100x100blueimage.png'), None) # NOTE: This test fails if there is a blue square visible on the screen.\n        self.assertEqual(\n            pyautogui.locateOnScreen(\"100x100blueimage.png\"), None\n        )  # NOTE: This test fails if there is a blue square visible on the screen.\n        self.assertEqual(\n            pyautogui.locateCenterOnScreen(\"100x100blueimage.png\"), None\n        )  # NOTE: This test fails if there is a blue square visible on the screen.\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "tox.ini",
    "content": "# tox (https://tox.readthedocs.io/) is a tool for running tests\n# in multiple virtualenvs. This configuration file will run the\n# test suite on all supported python versions. To use it, \"pip install tox\"\n# and then run \"tox\" from this directory.\n\n[tox]\nenvlist = py27, py31, py32, py33, py34, py35, py36, py37\n\n[testenv]\ndeps =\n    pymsgbox\n    pillow\n    pytest\n    pytweening\n    pyscreeze\ncommands =\n    python tests/test_pyautogui.py\n"
  }
]