Browse Source

Code cleanup + formatting

master v0.0.1
Adam Pippin 4 years ago
parent
commit
e89ce855df
  1. 3
      .phan/config.php
  2. 12
      app/Commands/Layout.php
  3. 18
      app/Commands/Monitor.php
  4. 61
      app/Configuration.php
  5. 71
      app/Display.old.php
  6. 31
      app/Engine.php
  7. 55
      app/ILayoutDriver.php
  8. 51
      app/Layout.php
  9. 27
      app/LayoutDriver/Xrandr.php
  10. 28
      app/Providers/AppServiceProvider.php
  11. 12
      app/Providers/LayoutServiceProvider.php
  12. 77
      app/Screen.php
  13. 2
      bootstrap/app.php
  14. 3
      config/app.php
  15. 2
      config/commands.php
  16. 2
      tests/CreatesApplication.php
  17. 9
      tests/Feature/InspiringCommandTest.php
  18. 2
      tests/TestCase.php
  19. 6
      tests/Unit/ExampleTest.php

3
.phan/config.php

@ -12,8 +12,7 @@ return [
'vendor/laravel-zero/', 'vendor/laravel-zero/',
'vendor/nunomaduro/', 'vendor/nunomaduro/',
'vendor/composer/', 'vendor/composer/',
'vendor/symfony/', 'vendor/symfony/'
'vendor/aws/'
], ],
'exclude_analysis_directory_list' => [ 'exclude_analysis_directory_list' => [

12
app/Commands/Layout.php

@ -1,9 +1,16 @@
<?php <?php
declare(strict_types=1);
namespace App\Commands; namespace App\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
/**
* Do a one-time layout
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Layout extends Command class Layout extends Command
{ {
/** /**
@ -33,14 +40,17 @@ class Layout extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return mixed * @param \App\ILayoutDriver $driver
* @return void
*/ */
public function handle(\App\ILayoutDriver $driver) public function handle(\App\ILayoutDriver $driver)
{ {
$config_file = $this->argument('config'); $config_file = $this->argument('config');
if (!file_exists($config_file) || !is_readable($config_file)) if (!file_exists($config_file) || !is_readable($config_file))
{
throw new \Exception("Cannot read config file: $config_file"); throw new \Exception("Cannot read config file: $config_file");
}
$config = new \App\Configuration(); $config = new \App\Configuration();
$config->load($config_file); $config->load($config_file);

18
app/Commands/Monitor.php

@ -1,9 +1,16 @@
<?php <?php
declare(strict_types=1);
namespace App\Commands; namespace App\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
/**
* Continually relayout based on the passed in config
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Monitor extends Command class Monitor extends Command
{ {
/** /**
@ -11,7 +18,7 @@ class Monitor extends Command
* *
* @var string * @var string
*/ */
protected $signature = 'monitor {config} {--interval=5}'; protected $signature = 'monitor {config} {--interval=5 : how often to attempt relayout in seconds}';
/** /**
* The console command description. * The console command description.
@ -33,14 +40,17 @@ class Monitor extends Command
/** /**
* Execute the console command. * Execute the console command.
* *
* @return mixed * @param \App\ILayoutDriver $driver
* @return void
*/ */
public function handle(\App\ILayoutDriver $driver) public function handle(\App\ILayoutDriver $driver)
{ {
$config_file = $this->argument('config'); $config_file = $this->argument('config');
if (!file_exists($config_file) || !is_readable($config_file)) if (!file_exists($config_file) || !is_readable($config_file))
{
throw new \Exception("Cannot read config file: $config_file"); throw new \Exception("Cannot read config file: $config_file");
}
$config = new \App\Configuration(); $config = new \App\Configuration();
$config->load($config_file); $config->load($config_file);
@ -49,7 +59,7 @@ class Monitor extends Command
declare(ticks=1); declare(ticks=1);
$signal_handler = function($signal) use ($config_file, &$engine) { $signal_handler = static function(int $signal) use ($config_file, &$engine) {
switch ($signal) switch ($signal)
{ {
case SIGHUP: case SIGHUP:
@ -65,7 +75,7 @@ class Monitor extends Command
while (true) while (true)
{ {
$engine->layout(); $engine->layout();
sleep($this->option('interval')); sleep((int)$this->option('interval'));
} }
} }
} }

61
app/Configuration.php

@ -1,20 +1,45 @@
<?php <?php
declare(strict_types=1);
namespace App; namespace App;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
/**
* Represent the configuration containing screens and layouts
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Configuration class Configuration
{ {
/**
* Represents the available screens and their configuration
* @var array<string, Screen>
*/
protected $_screens; protected $_screens;
/**
* Represents the available layouts
* @var array<string, Layout>
*/
protected $_layouts; protected $_layouts;
/**
* Initialize an empty config
*/
public function __construct() public function __construct()
{ {
$this->_screens = []; $this->_screens = [];
$this->_layouts = []; $this->_layouts = [];
} }
/**
* Load a configuration from a YAML file
*
* @param string $file
* @return void
*/
public function load(string $file): void public function load(string $file): void
{ {
$config = Yaml::parseFile($file); $config = Yaml::parseFile($file);
@ -32,33 +57,63 @@ class Configuration
} }
} }
public function getScreen(string $screen): Screen /**
* Fetch a specific screen
*
* @param string $screen_name
* @return Screen
*/
public function getScreen(string $screen_name): Screen
{ {
return $this->_screens[$screen]; return $this->_screens[$screen_name];
} }
/**
* Fetch the primary screen
*
* @return Screen
*/
public function getPrimaryScreen(): Screen public function getPrimaryScreen(): Screen
{ {
return $this->getScreen($this->getPrimaryScreenName()); return $this->getScreen($this->getPrimaryScreenName());
} }
/**
* Fetch the name of the primary screen
*
* @return string
*/
public function getPrimaryScreenName(): string public function getPrimaryScreenName(): string
{ {
foreach ($this->_screens as $name => $screen) foreach ($this->_screens as $name => $screen)
{ {
if ($screen->isPrimary()) if ($screen->isPrimary())
{
return $name; return $name;
} }
} }
throw new \Exception("No primary screen found");
}
/**
* Fetch a specific layout
*
* @param string $layout
* @return Layout
*/
public function getLayout(string $layout): Layout public function getLayout(string $layout): Layout
{ {
return $this->_layouts[$layout]; return $this->_layouts[$layout];
} }
/**
* Fetch all the layouts
*
* @return array<string, Layout>
*/
public function getLayouts(): array public function getLayouts(): array
{ {
return $this->_layouts; return $this->_layouts;
} }
} }

71
app/Display.old.php

@ -1,71 +0,0 @@
<?php
namespace App;
class Display
{
protected $_names;
protected $_output;
protected $_width;
protected $_height;
protected $_x;
protected $_y;
public function __construct(array $names)
{
$this->_names = $names;
}
public function read()
{
foreach ($this->_names as $name)
{
$xrandr = trim(shell_exec('xrandr | grep "^'.$name.'"'));
if (!empty($xrandr))
break;
}
if (empty($xrandr))
throw new \Exception("Cannot load display: ".end($this->_names));
# DVI-I-2-1 connected 1920x1080+1920+1440 (normal left inverted right x axis y axis) 521mm x 293mm
if (!preg_match('/^(?<output>[^ ]+) connected (?<screen_w>[0-9]+)x(?<screen_h>[0-9]+)\\+(?<screen_x>[0-9]+)\\+(?<screen_y>[0-9]+) /', $xrandr, $matches))
throw new \Exception("Cannot parse xrandr response for: ".$name);
$this->_output = $matches['output'];
$this->_x = $matches['screen_x'];
$this->_y = $matches['screen_y'];
$this->_width = $matches['screen_w'];
$this->_height = $matches['screen_h'];
}
public function getX(): int
{
return (int)$this->_x;
}
public function getY(): int
{
return (int)$this->_y;
}
public function getWidth(): int
{
return (int)$this->_width;
}
public function getHeight(): int
{
return (int)$this->_height;
}
public function setOffset(int $x, int $y): void
{
shell_exec('xrandr --output '.$this->_output.' --pos '.$x.'x'.$y);
}
public function setDimensions(int $width, int $height): void
{
shell_exec('xrandr --output '.$this->_output.' --mode '.$width.'x'.$height);
}
}

31
app/Engine.php

@ -1,18 +1,44 @@
<?php <?php
declare(strict_types=1);
namespace App; namespace App;
/**
* Main logic for actually doing things with the passed in config
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Engine class Engine
{ {
protected $_config, $_driver; /**
* The configuration laying out the screens and layouts we're trying to implement
* @var Configuration
*/
protected $_config;
/**
* The driver to allow us to manipulate display offsets/dimensions/etc
* @var ILayoutDriver
*/
protected $_driver;
/**
* Set up the engine
* @param Configuration $config
* @param ILayoutDriver $driver
*/
public function __construct(\App\Configuration $config, \App\ILayoutDriver $driver) public function __construct(\App\Configuration $config, \App\ILayoutDriver $driver)
{ {
$this->_config = $config; $this->_config = $config;
$this->_driver = $driver; $this->_driver = $driver;
} }
public function layout() /**
* Perform a layout
*
* @return void
*/
public function layout(): void
{ {
foreach ($this->_config->getLayouts() as $layout_name => $layout) foreach ($this->_config->getLayouts() as $layout_name => $layout)
{ {
@ -34,6 +60,5 @@ class Engine
$layout->execute($this->_config, $this->_driver); $layout->execute($this->_config, $this->_driver);
break; break;
} }
} }
} }

55
app/ILayoutDriver.php

@ -1,14 +1,67 @@
<?php <?php
declare(strict_types=1);
namespace App; namespace App;
/**
* Provide an interface to manipulating outputs
*
* @author Adam Pippin <hello@adampippin.ca>
*/
interface ILayoutDriver interface ILayoutDriver
{ {
/**
* Set the offset of an output
*
* @param string $output
* @param int $x
* @param int $y
* @return void
*/
public function setOffset(string $output, int $x, int $y): void; public function setOffset(string $output, int $x, int $y): void;
/**
* Get the offset of an output
*
* @param string $output
* @return int[] x, y
*/
public function getOffset(string $output): array; public function getOffset(string $output): array;
/**
* Set the dimensions of the output
*
* @param string $output
* @param int $x
* @param int $y
* @return void
*/
public function setDimensions(string $output, int $x, int $y): void; public function setDimensions(string $output, int $x, int $y): void;
/**
* Get the dimensions of an output
*
* @param string $output
* @return int[] x, y
*/
public function getDimensions(string $output): array; public function getDimensions(string $output): array;
/**
* Check whether an output is connected
*
* @param string $output
* @return bool
*/
public function isConnected(string $output): bool; public function isConnected(string $output): bool;
/**
* Check whether the output is considered primary
*
* @param string $output
* @return bool
*/
public function isPrimary(string $output): bool; public function isPrimary(string $output): bool;
}
}

51
app/Layout.php

@ -1,28 +1,30 @@
<?php <?php
declare(strict_types=1);
namespace App; namespace App;
/** /**
* Calculate the layout of a collection of screens * Calculate the layout of a collection of screens.
* *
* @author Adam Pippin <hello@adampippin.ca> * @author Adam Pippin <hello@adampippin.ca>
*/ */
class Layout class Layout
{ {
/** /**
* List of screens this layout uses * List of screens this layout uses.
* @var array[] * @var array<string,array>
*/ */
protected $_screens; protected $_screens;
/** /**
* Relations between the screens * Relations between the screens.
* @var array[] * @var array[]
*/ */
protected $_links; protected $_links;
/** /**
* Initialize a new layout * Initialize a new layout.
* *
* @param array[] $screens * @param array[] $screens
* @param array[] $links * @param array[] $links
@ -34,7 +36,7 @@ class Layout
} }
/** /**
* Fetch the names of the screens this layout depends on * Fetch the names of the screens this layout depends on.
* *
* @return string[] * @return string[]
*/ */
@ -44,7 +46,7 @@ class Layout
} }
/** /**
* Execute this layout * Execute this layout.
* *
* @param Configuration $config * @param Configuration $config
* @param ILayoutDriver $driver * @param ILayoutDriver $driver
@ -82,7 +84,10 @@ class Layout
$calculate_layout = null; $calculate_layout = null;
if (isset($link['above'])) if (isset($link['above']))
{ {
$calculate_layout = function($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h) { /**
* @return int[]
*/
$calculate_layout = static function(int $s_x, int $s_y, int $s_w, int $s_h, int $d_x, int $d_y, int $d_w, int $d_h): array {
$center = $s_x + ($s_w / 2); $center = $s_x + ($s_w / 2);
$x = $center - ($d_w / 2); $x = $center - ($d_w / 2);
$y = $s_y - $d_h; $y = $s_y - $d_h;
@ -92,7 +97,10 @@ class Layout
} }
elseif (isset($link['below'])) elseif (isset($link['below']))
{ {
$calculate_layout = function($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h) { /**
* @return int[]
*/
$calculate_layout = static function(int $s_x, int $s_y, int $s_w, int $s_h, int $d_x, int $d_y, int $d_w, int $d_h): array {
$center = $s_x + ($s_w / 2); $center = $s_x + ($s_w / 2);
$x = $center - ($d_w / 2); $x = $center - ($d_w / 2);
$y = $s_y + $s_h; $y = $s_y + $s_h;
@ -102,13 +110,19 @@ class Layout
} }
elseif (isset($link['left_of'])) elseif (isset($link['left_of']))
{ {
$calculate_layout = function($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h) { /**
* @return int[]
*/
$calculate_layout = static function(int $s_x, int $s_y, int $s_w, int $s_h, int $d_x, int $d_y, int $d_w, int $d_h): array {
return [$s_x - $d_w, $s_y]; return [$s_x - $d_w, $s_y];
}; };
} }
elseif (isset($link['right_of'])) elseif (isset($link['right_of']))
{ {
$calculate_layout = function($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h) { /**
* @return int[]
*/
$calculate_layout = static function(int $s_x, int $s_y, int $s_w, int $s_h, int $d_x, int $d_y, int $d_w, int $d_h): array {
return [$s_x + $s_w, $s_y]; return [$s_x + $s_w, $s_y];
}; };
} }
@ -123,9 +137,9 @@ class Layout
} }
else else
{ {
list($s_x, $s_y) = $source->getOffset(); [$s_x, $s_y] = $source->getOffset();
} }
list($s_w, $s_h) = $source->getDimensions(); [$s_w, $s_h] = $source->getDimensions();
if (isset($layout[$target_name])) if (isset($layout[$target_name]))
{ {
@ -134,11 +148,11 @@ class Layout
} }
else else
{ {
list($d_x, $d_y) = $target->getOffset(); [$d_x, $d_y] = $target->getOffset();
} }
list($d_w, $d_h) = $target->getDimensions(); [$d_w, $d_h] = $target->getDimensions();
list($x, $y) = $calculate_layout($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h); [$x, $y] = $calculate_layout($s_x, $s_y, $s_w, $s_h, $d_x, $d_y, $d_w, $d_h);
$layout[$target_name] = ['x' => $x, 'y' => $y]; $layout[$target_name] = ['x' => $x, 'y' => $y];
$layout_stack[] = $target_name; $layout_stack[] = $target_name;
@ -157,14 +171,11 @@ class Layout
foreach ($layout as $screen_name => $screen_offset) foreach ($layout as $screen_name => $screen_offset)
{ {
list($current_x, $current_y) = $config->getScreen($screen_name)->getOffset(); [$current_x, $current_y] = $config->getScreen($screen_name)->getOffset();
if ($current_x != $screen_offset['x'] - $min_x || $current_y != $screen_offset['y'] - $min_y) if ($current_x != $screen_offset['x'] - $min_x || $current_y != $screen_offset['y'] - $min_y)
{ {
$config->getScreen($screen_name)->setOffset($screen_offset['x'] - $min_x, $screen_offset['y'] - $min_y); $config->getScreen($screen_name)->setOffset($screen_offset['x'] - $min_x, $screen_offset['y'] - $min_y);
} }
} }
} }
} }

27
app/LayoutDriver/Xrandr.php

@ -1,17 +1,43 @@
<?php <?php
declare(strict_types=1);
namespace App\LayoutDriver; namespace App\LayoutDriver;
/**
* Interface to xrandr for configuring outputs
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Xrandr implements \App\ILayoutDriver class Xrandr implements \App\ILayoutDriver
{ {
/**
* The xrandr command
* @var \App\System\Command\Xrandr
*/
protected $_xrandr; protected $_xrandr;
/**
* Cache of current display parameters
* @var array<string, array>
*/
protected $_displays; protected $_displays;
/**
* Create a new xrandr driver
*
* @param \App\System\Command\Xrandr $xrandr_cmd
*/
public function __construct(\App\System\Command\Xrandr $xrandr_cmd) public function __construct(\App\System\Command\Xrandr $xrandr_cmd)
{ {
$this->_xrandr = $xrandr_cmd; $this->_xrandr = $xrandr_cmd;
} }
/**
* Read display parameters from xrandr
*
* @return void
*/
public function read() public function read()
{ {
$xrandr = $this->_xrandr->__invoke([]); $xrandr = $this->_xrandr->__invoke([]);
@ -73,4 +99,3 @@ class Xrandr implements \App\ILayoutDriver
return isset($this->_displays[$output]); return isset($this->_displays[$output]);
} }
} }

28
app/Providers/AppServiceProvider.php

@ -1,28 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}

12
app/Providers/LayoutServiceProvider.php

@ -1,9 +1,21 @@
<?php <?php
declare(strict_types=1);
namespace App\Providers; namespace App\Providers;
/**
* Register the layout driver singleton
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class LayoutServiceProvider extends \Illuminate\Support\ServiceProvider class LayoutServiceProvider extends \Illuminate\Support\ServiceProvider
{ {
/**
* Register the layout driver
*
* @return void
*/
public function register() public function register()
{ {
$this->app->singleton(\App\ILayoutDriver::class, \App\LayoutDriver\Xrandr::class); $this->app->singleton(\App\ILayoutDriver::class, \App\LayoutDriver\Xrandr::class);

77
app/Screen.php

@ -1,54 +1,125 @@
<?php <?php
declare(strict_types=1);
namespace App; namespace App;
/**
* Represents and provides an interface for manipulating screens
*
* @author Adam Pippin <hello@adampippin.ca>
*/
class Screen class Screen
{ {
/**
* A list of possible hardware outputs that could implement this screen
* @var string[]
*/
protected $_outputs; protected $_outputs;
/**
* The driver for manipulating the layout
* @var ILayoutDriver
*/
protected $_driver; protected $_driver;
/**
* Set up a new screen
*
* @param string[] $outputs
* @param ILayoutDriver $driver
*/
public function __construct(array $outputs, ILayoutDriver $driver) public function __construct(array $outputs, ILayoutDriver $driver)
{ {
$this->_outputs = $outputs; $this->_outputs = $outputs;
$this->_driver = $driver; $this->_driver = $driver;
} }
protected function getOutputName(): ?string /**
* Enumerate all possible outputs and return the first that is found to be connected
*
* @return string
*/
protected function getOutputName(): string
{ {
foreach ($this->_outputs as $output) foreach ($this->_outputs as $output)
{ {
if ($this->_driver->isConnected($output)) if ($this->_driver->isConnected($output))
{
return $output; return $output;
} }
}
return null; throw new \Exception("No connected output found!");
} }
/**
* Determine whether this screen is connected
*
* @return bool
*/
public function isConnected(): bool public function isConnected(): bool
{ {
return !empty($this->getOutputName()); try
{
$this->getOutputName();
return true;
}
catch (\Exception $ex)
{
return false;
}
} }
/**
* Determine whether this screen is considered the "primary" screen
*
* @return bool
*/
public function isPrimary(): bool public function isPrimary(): bool
{ {
return $this->_driver->isPrimary($this->getOutputName()); return $this->_driver->isPrimary($this->getOutputName());
} }
/**
* Get the pixel dimensions of the screen
*
* @return int[] x, y
*/
public function getDimensions(): array public function getDimensions(): array
{ {
return $this->_driver->getDimensions($this->getOutputName()); return $this->_driver->getDimensions($this->getOutputName());
} }
/**
* Get the pixel offset of the screen
*
* @return int[] x, y
*/
public function getOffset(): array public function getOffset(): array
{ {
return $this->_driver->getOffset($this->getOutputName()); return $this->_driver->getOffset($this->getOutputName());
} }
/**
* Set the pixel offset of the screen
*
* @param int $x
* @param int $y
* @return void
*/
public function setOffset(int $x, int $y): void public function setOffset(int $x, int $y): void
{ {
$this->_driver->setOffset($this->getOutputName(), $x, $y); $this->_driver->setOffset($this->getOutputName(), $x, $y);
} }
/**
* Set the resolution of the screen
*
* @param int $w
* @param int $h
* @return void
*/
public function setDimensions(int $w, int $h): void public function setDimensions(int $w, int $h): void
{ {
$this->_driver->setDimensions($this->getOutputName(), $w, $h); $this->_driver->setDimensions($this->getOutputName(), $w, $h);

2
bootstrap/app.php

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Create The Application | Create The Application

3
config/app.php

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*
@ -54,7 +56,6 @@ return [
*/ */
'providers' => [ 'providers' => [
App\Providers\AppServiceProvider::class,
App\Providers\LayoutServiceProvider::class App\Providers\LayoutServiceProvider::class
], ],

2
config/commands.php

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*

2
tests/CreatesApplication.php

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Tests; namespace Tests;
use Illuminate\Contracts\Console\Kernel; use Illuminate\Contracts\Console\Kernel;

9
tests/Feature/InspiringCommandTest.php

@ -1,9 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace Tests\Feature; namespace Tests\Feature;
use Tests\TestCase; use Tests\TestCase;
/**
* @internal
* @coversNothing
*/
class InspiringCommandTest extends TestCase class InspiringCommandTest extends TestCase
{ {
/** /**
@ -15,6 +21,7 @@ class InspiringCommandTest extends TestCase
{ {
$this->artisan('inspiring') $this->artisan('inspiring')
->expectsOutput('Simplicity is the ultimate sophistication.') ->expectsOutput('Simplicity is the ultimate sophistication.')
->assertExitCode(0); ->assertExitCode(0)
;
} }
} }

2
tests/TestCase.php

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Tests; namespace Tests;
use LaravelZero\Framework\Testing\TestCase as BaseTestCase; use LaravelZero\Framework\Testing\TestCase as BaseTestCase;

6
tests/Unit/ExampleTest.php

@ -1,9 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace Tests\Unit; namespace Tests\Unit;
use Tests\TestCase; use Tests\TestCase;
/**
* @internal
* @coversNothing
*/
class ExampleTest extends TestCase class ExampleTest extends TestCase
{ {
/** /**

Loading…
Cancel
Save