Initial commit
This commit is contained in:
commit
f9c2f8f543
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/vendor
|
17
composer.json
Normal file
17
composer.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "noccylabs/x11",
|
||||||
|
"description": "Interact with windows on Linux/X11",
|
||||||
|
"type": "library",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Christopher Vagnetoft",
|
||||||
|
"email": "cvagnetoft@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"NoccyLabs\\X11\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
examples/find_windows.php
Normal file
20
examples/find_windows.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__."/../vendor/autoload.php";
|
||||||
|
|
||||||
|
use NoccyLabs\X11\WindowList;
|
||||||
|
|
||||||
|
// Create a list of all windows
|
||||||
|
$windows = new WindowList();
|
||||||
|
$windows->dump();
|
||||||
|
|
||||||
|
// Select all the windows with a title matching *code*
|
||||||
|
$windows = $windows->visible()->find("*code*");
|
||||||
|
$windows->dump();
|
||||||
|
|
||||||
|
// Grab the first window
|
||||||
|
$window = $windows->first();
|
||||||
|
$window->dump();
|
||||||
|
|
||||||
|
// Focus the window and simulate F1 being pressed
|
||||||
|
$window->focus()->sendKeys("F1");
|
11
examples/select_window.php
Normal file
11
examples/select_window.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__."/../vendor/autoload.php";
|
||||||
|
|
||||||
|
use NoccyLabs\X11\WindowSelector;
|
||||||
|
|
||||||
|
$selector = new WindowSelector();
|
||||||
|
|
||||||
|
printf("Click a window to select it...\n");
|
||||||
|
$window = $selector->select();
|
||||||
|
$window->dump();
|
8
examples/self_keys.php
Normal file
8
examples/self_keys.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__."/../vendor/autoload.php";
|
||||||
|
|
||||||
|
use NoccyLabs\X11\Window;
|
||||||
|
|
||||||
|
$me = new Window();
|
||||||
|
$me->sendKeys("l s Return", true);
|
97
src/Window.php
Normal file
97
src/Window.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NoccyLabs\X11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Window
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $windowId;
|
||||||
|
|
||||||
|
protected $windowTitle;
|
||||||
|
|
||||||
|
protected $isVisible;
|
||||||
|
|
||||||
|
public function __construct($id=null)
|
||||||
|
{
|
||||||
|
if (!$id) { $id = (int)exec("xdotool getactivewindow"); }
|
||||||
|
$this->windowId = $id;
|
||||||
|
$this->readWindowInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readWindowInfo()
|
||||||
|
{
|
||||||
|
exec("xwininfo -id {$this->windowId} -all -children", $output, $status);
|
||||||
|
foreach ($output as $line) {
|
||||||
|
if (preg_match('/^(.+?): (.+?)$/', trim($line), $match)) {
|
||||||
|
switch ($match[1]) {
|
||||||
|
case 'xwininfo':
|
||||||
|
if (preg_match('/Window id: .+? "(.+?)"/', $match[2], $m)) {
|
||||||
|
$this->windowTitle = $m[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Map State':
|
||||||
|
$this->isVisible = ($match[2]=='IsViewable');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//printf("[%s]->'%s'\n", $match[1], $match[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("---\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return hexdec($this->windowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isVisible()
|
||||||
|
{
|
||||||
|
return $this->isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWindowTitle()
|
||||||
|
{
|
||||||
|
return $this->windowTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendKeys($keys, $forceFocus=false)
|
||||||
|
{
|
||||||
|
if ($forceFocus) {
|
||||||
|
$this->focus();
|
||||||
|
$cmdl = sprintf("xdotool key %s", $keys);
|
||||||
|
} else {
|
||||||
|
$cmdl = sprintf("xdotool key --delay 100 --window %d %s", $this->windowId, $keys);
|
||||||
|
}
|
||||||
|
echo "$ {$cmdl}\n";
|
||||||
|
exec($cmdl);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function focus()
|
||||||
|
{
|
||||||
|
$cmdl = sprintf("xdotool windowfocus %d", $this->windowId);
|
||||||
|
echo "$ {$cmdl}\n";
|
||||||
|
exec($cmdl);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function activate()
|
||||||
|
{
|
||||||
|
$cmdl = sprintf("xdotool windowactivate %d", $this->windowId);
|
||||||
|
echo "$ {$cmdl}\n";
|
||||||
|
exec($cmdl);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dump()
|
||||||
|
{
|
||||||
|
printf("Window: (id=0x%08x)\n Title: %s\n Visible: %s\n",
|
||||||
|
$this->windowId,
|
||||||
|
$this->windowTitle,
|
||||||
|
$this->isVisible?'true':'false'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
88
src/WindowList.php
Normal file
88
src/WindowList.php
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NoccyLabs\X11;
|
||||||
|
|
||||||
|
use IteratorAggregate;
|
||||||
|
use ArrayIterator;
|
||||||
|
use Countable;
|
||||||
|
|
||||||
|
class WindowList implements IteratorAggregate, Countable
|
||||||
|
{
|
||||||
|
|
||||||
|
private $windows = [];
|
||||||
|
|
||||||
|
public function __construct(array $windows=null)
|
||||||
|
{
|
||||||
|
if (null === $windows) {
|
||||||
|
$this->readRootWindowTree();
|
||||||
|
} elseif (is_array($windows)) {
|
||||||
|
$this->windows = $windows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator()
|
||||||
|
{
|
||||||
|
return new ArrayIterator($this->windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function readRootWindowTree()
|
||||||
|
{
|
||||||
|
exec("xwininfo -root -tree", $output, $status);
|
||||||
|
$this->windows = [];
|
||||||
|
foreach ($output as $line) {
|
||||||
|
if (preg_match('/^\s+0x([0-9a-f]+?) (.+?)\: \((.+?)\)/', $line, $match)) {
|
||||||
|
$this->windows[] = new Window(hexdec($match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function find($title)
|
||||||
|
{
|
||||||
|
$found = [];
|
||||||
|
foreach ($this->windows as $window) {
|
||||||
|
if (fnmatch($title, $window->getWindowTitle(), FNM_CASEFOLD)) {
|
||||||
|
$found[] = $window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new WindowList($found);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findByClass($class)
|
||||||
|
{
|
||||||
|
$found = [];
|
||||||
|
return new WindowList($found);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRootWindow()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function visible()
|
||||||
|
{
|
||||||
|
$found = [];
|
||||||
|
foreach ($this->windows as $window) {
|
||||||
|
if ($window->isVisible())
|
||||||
|
$found[] = $window;
|
||||||
|
}
|
||||||
|
return new WindowList($found);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function first()
|
||||||
|
{
|
||||||
|
return count($this->windows)?$this->windows[0]:null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dump()
|
||||||
|
{
|
||||||
|
printf("WindowList: (count=%d)\n", count($this));
|
||||||
|
foreach ($this as $window) {
|
||||||
|
printf(" 0x%08x: %s %s\n", $window->getId(), $window->getWindowTitle(), $window->isVisible()?'(Visible)':'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/WindowSelector.php
Normal file
17
src/WindowSelector.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NoccyLabs\X11;
|
||||||
|
|
||||||
|
class WindowSelector
|
||||||
|
{
|
||||||
|
|
||||||
|
public function select()
|
||||||
|
{
|
||||||
|
$id = exec("xdotool selectwindow");
|
||||||
|
if (is_numeric($id)) {
|
||||||
|
return new Window($id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user