#!/usr/bin/php $v) { if (!array_key_exists($k, $default)) { unset($data[$k]); } elseif (is_array($default[$k]) && !is_array($v)) { $data[$k] = (array) $v; } } foreach ($default as $k => $v) { if (!array_key_exists($k, $data)) { $data[$k] = $v; } } return $data; } function filterScreen(array $data) { $default = [ 'name' => null, 'resolutionX' => null, 'resolutionY' => null, ]; return filter($data, $default); } function filterMode(array $data) { $default = [ 'config' => [], 'primary' => null, ]; $data = filter($data, $default); foreach ($data['config'] as $k => $v) { $v = explode(',', $v); $v = array_map('trim', $v); $data['config'][$k] = $v; } return $data; } function getCurrentModeFile() { return sys_get_temp_dir().'/monitordisplay.tmp'; } function getCurrentMode() { $currentModeFile = getCurrentModeFile(); if (file_exists($currentModeFile)) { $currentMode = (array) @parse_ini_file($currentModeFile); } else { $currentMode = []; } return filter($currentMode, [ 'mode' => null, 'config' => null, ]); } function build(array $modes, array $screens, $mode, $toggle, array $currentMode, $addOff) { if ($mode === null) { if (!array_key_exists($currentMode['mode'], $modes)) { return; } $tmpMode = $currentMode['mode']; $mode = $modes[$currentMode['mode']]; } else { if (!array_key_exists($mode, $modes)) { return; } $tmpMode = $mode; $mode = $modes[$mode]; } if ($toggle !== false) { if ($currentMode['mode'] === null) { return; } if ($currentMode['config'] === null) { return; } $configs = $mode['config']; $configsKeys = array_keys($configs); if (!array_key_exists($currentMode['config'], $mode['config'])) { $currentMode['config'] = $configsKeys[0]; } if ($toggle === true) { foreach ($configsKeys as $k => $key) { if ($key === $currentMode['config']) { $currentKey = $k; } } ; $config = $configsKeys[($currentKey + 1) % count($configsKeys)]; } elseif (array_key_exists($toggle, $configs)) { $config = $toggle; } else { error(sprintf('Invalid config "%s"', $toggle)); die(1); } } else { $config = 0; } if (!array_key_exists($config, $mode['config'])) { return; } $tmpConfig = $config; $config = $mode['config'][$config]; $command = ['xrandr']; $x = 0; $screensUsed = []; foreach ($config as $screen) { if (!array_key_exists($screen, $screens)) { return; } $tScreen = $screens[$screen]; $name = $tScreen['name']; $resolutionX = $tScreen['resolutionX']; $resolutionY = $tScreen['resolutionY']; if (empty($name) || empty($resolutionX) || empty($resolutionY)) { error(sprintf('Invalid screen configuration "%s"', $screen)); die(1); } $command[] = '--output'; $command[] = $name; $screensUsed[] = $name; if ($mode['primary'] === $name) { $command[] = '--primary'; } $command[] = '--mode'; $command[] = sprintf('%dx%d', $resolutionX, $resolutionY); $command[] = '--pos'; $command[] = sprintf('%dx%d', $x, 0); $x += $resolutionX; } if ($addOff) { foreach ($screens as $screen) { if (!in_array($screen['name'], $screensUsed)) { $command[] = '--output'; $command[] = $screen['name']; $command[] = '--off'; } } } $command = implode(' ', $command); return [ 'config' => sprintf("mode=%s\nconfig=%s", $tmpMode, $tmpConfig), 'command' => $command, ]; } $files = [ '/etc/monitordisplay/config.ini', getenv('HOME').'/.config/monitordisplay/config.ini', getenv('HOME').'/.monitordisplay', ]; $config = []; $currentMode = getCurrentMode(); foreach ($files as $file) { if (file_exists($file)) { $parsing = @parse_ini_file($file, true); if ($parsing === false) { error(sprintf('The file "%s" is not a valid ini file.', $file)); continue; } notice(sprintf('Configuration file merged: %s', $file)); $config = array_merge( $config, $parsing ); } } if (empty($config)) { error('No configuration found'); error(sprintf('Paths checked: %s', implode(', ', $files))); die(1); } $screens = []; $modes = []; foreach ($config as $section => $values) { $type = explode(':', $section); if (count($type) !== 2) { error(sprintf('Invalid section "%s". Ignored.', $section)); } if ($type[0] === 'screen') { $screens[$type[1]] = filterScreen($values); } elseif ($type[0] === 'mode') { $modes[$type[1]] = filterMode($values); } else { error(sprintf('Invalid section "%s". Ignored.', $section)); } } if (empty($screens)) { error('No screen found.'); die(1); } if (empty($modes)) { error('No mode found.'); die(1); } $options = getopt('m:t::s'); $mode = isset($options['m']) ? $options['m'] : null; $toggle = isset($options['t']) ? (false === $options['t'] ? true : $options['t']) : false; $addOff = !isset($options['s']); $build = build($modes, $screens, $mode, $toggle, $currentMode, $addOff); if (!empty($build)) { file_put_contents(getCurrentModeFile(), $build['config']); shell_exec($build['command']); }