Example #1
0
    def test_compose_mode_args(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [Output("LVDS1", Geometry(1366, 768), primary=True),
                   Output("DP1", Geometry(1920, 1080, 1366, 0)),
                   Output("VGA1", Geometry(800, 600, 0, 768))]

        p = Profile("default", outputs)

        xrandr_connections = [XrandrOutput("HDMI1"), XrandrOutput("HDMI2")]

        command = xrandr.__compose_mode_args__(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(xrandr_connections), command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))
Example #2
0
    def test_compose_mode_args(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [
            Output("LVDS1", Geometry(1366, 768), primary=True),
            Output("DP1", Geometry(1920, 1080, 1366, 0)),
            Output("VGA1", Geometry(800, 600, 0, 768))
        ]

        p = Profile("default", outputs)

        xrandr_connections = [XrandrOutput("HDMI1"), XrandrOutput("HDMI2")]

        command = xrandr.__compose_mode_args__(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(xrandr_connections),
                         command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))
Example #3
0
    def test_compose_mode_args(self):
        xrandr = Xrandr(":0", None)
        xrandr.EXECUTABLE = "stub"

        outputs = {
            "LVDS1": Output(mode='1366x768'),
            "DP1": Output(mode='1920x1080', pos='1366x0', scale='1.5x1.5', panning='1920x1080'),
            "VGA1": Output(mode='800x600', pos='0x768')
        }

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [XrandrConnection("HDMI1"), XrandrConnection("HDMI2")]

        command = xrandr._compose_mode_args(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.PANNING_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.ROTATE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.SCALE_KEY))
        self.assertEqual(len(xrandr_connections), command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))
Example #4
0
    def get_randrctl(self):
        config = ConfigParser(allow_no_value=True, strict=False)

        config_files = list(
            map(lambda x: os.path.join(x, self.config_name), self.homes))
        config_files.reverse()
        read = config.read(config_files)
        logger.debug("read configuration from %s", read)

        # profile manager
        profile_paths = list(
            map(lambda x: os.path.join(x, self.profile_dir), self.homes))
        profile_reader = ProfileManager(profile_paths)

        # xrandr
        xrandr = Xrandr()

        # hooks
        prior_switch = self.get_safe(config, "hooks", "prior_switch")
        post_switch = self.get_safe(config, "hooks", "post_switch")
        post_fail = self.get_safe(config, "hooks", "post_fail")
        if (prior_switch is not None) | (post_switch is not None) | (
                post_fail is not None):
            hook = Hook(prior_switch, post_switch, post_fail)
            xrandr = hook.decorate(xrandr)

        return RandrCtl(profile_reader, xrandr)
Example #5
0
def build(display: str,
          xauthority: str = None,
          config_dirs: list = default_config_dirs()):
    """
    Builds a RandrCtl instance and all its dependencies given a list of config directories
    :param: display - display
    :return: new ready to use RandrCtl instance
    """
    (primary_config_dir, config) = next(configs(config_dirs),
                                        (config_dirs[0], dict()))

    prior_switch = config.get('hooks', dict()).get('prior_switch', None)
    post_switch = config.get('hooks', dict()).get('post_switch', None)
    post_fail = config.get('hooks', dict()).get('post_fail', None)
    hooks = Hooks(prior_switch, post_switch, post_fail)

    profile_read_locations = [
        os.path.join(primary_config_dir, PROFILE_DIR_NAME)
    ]
    profile_write_location = os.path.join(primary_config_dir, PROFILE_DIR_NAME)
    profile_manager = ProfileManager(profile_read_locations,
                                     profile_write_location)

    xrandr = Xrandr(display, xauthority)

    return RandrCtl(profile_manager, xrandr, hooks)
Example #6
0
    def test_compose_mode_args_exact_line(self):
        xrandr = Xrandr(":0", None)
        xrandr.EXECUTABLE = "stub"

        outputs = {"LVDS1": Output(mode='1366x768')}

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [XrandrConnection("LVDS1"), XrandrConnection("HDMI1")]

        command = xrandr._compose_mode_args(p, xrandr_connections)
        self.assertListEqual([
            '--output', 'LVDS1', '--mode', '1366x768', '--pos', '0x0', '--rotate', 'normal', '--panning', '0x0',
            '--scale', '1x1', '--primary',
            '--output', 'HDMI1', '--off'
        ], command)
Example #7
0
    def test_compose_mode_args_exact_line(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [Output("LVDS1", mode='1366x768')]

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [
            XrandrConnection("LVDS1"),
            XrandrConnection("HDMI1")
        ]

        command = xrandr._compose_mode_args(p, xrandr_connections)
        self.assertListEqual([
            '--output', 'LVDS1', '--mode', '1366x768', '--pos', '0x0',
            '--rotate', 'normal', '--panning', '0x0', '--scale', '1x1',
            '--primary', '--output', 'HDMI1', '--off'
        ], command)
Example #8
0
    def test_compose_mode_args(self):
        xrandr = Xrandr(":0", None)
        xrandr.EXECUTABLE = "stub"

        outputs = {
            "LVDS1":
            Output(mode='1366x768'),
            "DP1":
            Output(mode='1920x1080',
                   pos='1366x0',
                   scale='1.5x1.5',
                   panning='1920x1080'),
            "VGA1":
            Output(mode='800x600', pos='0x768')
        }

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [
            XrandrConnection("HDMI1"),
            XrandrConnection("HDMI2")
        ]

        command = xrandr._compose_mode_args(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.PANNING_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.ROTATE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.SCALE_KEY))
        self.assertEqual(len(xrandr_connections),
                         command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))
Example #9
0
    def decorate(self, xrandr: Xrandr):
        do_apply = xrandr.apply

        def apply_hook(p: Profile):
            try:
                self.hook(self.prior_switch, p)
                do_apply(p)
                self.hook(self.post_switch, p)
            except Exception as e:
                self.hook(self.post_fail, p, str(e))
                raise e

        xrandr.apply = apply_hook
        return xrandr
Example #10
0
    def decorate(self, xrandr: Xrandr):
        do_apply = xrandr.apply

        def apply_hook(p: Profile):
            try:
                self.hook(self.prior_switch, p)
                do_apply(p)
                self.hook(self.post_switch, p)
            except Exception as e:
                self.hook(self.post_fail, p, str(e))
                raise e

        xrandr.apply = apply_hook
        return xrandr
Example #11
0
def _build(primary_config_dir: str, config: dict):
    prior_switch = config.get('hooks', dict()).get('prior_switch', None)
    post_switch = config.get('hooks', dict()).get('post_switch', None)
    post_fail = config.get('hooks', dict()).get('post_fail', None)
    hooks = Hooks(prior_switch, post_switch, post_fail)

    profile_read_locations = [
        os.path.join(primary_config_dir, PROFILE_DIR_NAME)
    ]
    profile_write_location = os.path.join(primary_config_dir, PROFILE_DIR_NAME)
    profile_manager = ProfileManager(profile_read_locations,
                                     profile_write_location)

    xrandr = Xrandr()

    return RandrCtl(profile_manager, xrandr, hooks)
Example #12
0
    def get_randrctl(self):
        # Load configuration files as a dictionary
        config = self._load_config_files()

        # profile manager
        profile_paths = list(
            map(lambda x: os.path.join(x, self.profile_dir), self.homes))
        profile_reader = ProfileManager(profile_paths)

        # xrandr
        xrandr = Xrandr()

        # hooks
        prior_switch = self._config_safe(config, "hooks", "prior_switch")
        post_switch = self._config_safe(config, "hooks", "post_switch")
        post_fail = self._config_safe(config, "hooks", "post_fail")
        if (prior_switch is not None) | (post_switch is not None) | (
                post_fail is not None):
            hook = Hook(prior_switch, post_switch, post_fail)
            xrandr = hook.decorate(xrandr)

        return RandrCtl(profile_reader, xrandr)
Example #13
0
class TestXrandr(TestCase):
    xrandr = Xrandr()

    def test_compose_mode_args(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [
            Output("LVDS1", mode='1366x768'),
            Output("DP1",
                   mode='1920x1080',
                   pos='1366x0',
                   scale='1.5x1.5',
                   panning='1920x1080'),
            Output("VGA1", mode='800x600', pos='0x768')
        ]

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [
            XrandrConnection("HDMI1"),
            XrandrConnection("HDMI2")
        ]

        command = xrandr._compose_mode_args(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.PANNING_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.ROTATE_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.SCALE_KEY))
        self.assertEqual(len(xrandr_connections),
                         command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))

    def test_compose_mode_args_exact_line(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [Output("LVDS1", mode='1366x768')]

        p = Profile("default", outputs, primary="LVDS1")

        xrandr_connections = [
            XrandrConnection("LVDS1"),
            XrandrConnection("HDMI1")
        ]

        command = xrandr._compose_mode_args(p, xrandr_connections)
        self.assertListEqual([
            '--output', 'LVDS1', '--mode', '1366x768', '--pos', '0x0',
            '--rotate', 'normal', '--panning', '0x0', '--scale', '1x1',
            '--primary', '--output', 'HDMI1', '--off'
        ], command)

    def test_parse_xrandr_connection_not_connected(self):
        query_result = [
            "DP1 disconnected (normal left inverted right x axis y axis)"
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)

        self.assertIsNotNone(connection)
        self.assertEqual(connection.name, "DP1")
        self.assertIsNone(connection.display)
        self.assertIsNone(connection.viewport)
        self.assertFalse(connection.primary)

    def test_parse_xrandr_connection_not_active(self):
        query_result = [
            "HDMI1 connected (normal left inverted right x axis y axis)",
            "    1920x1080     60.00 +",
            "    1280x1024     75.02    60.02",
            "    800x600       75.00    60.32",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)

        self.assertIsNotNone(connection)
        self.assertEqual("HDMI1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertIsNone(connection.display.rate)
        self.assertIsNone(connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080", "1280x1024", "800x600"],
                         connection.display.supported_modes)

        self.assertIsNone(connection.viewport)
        self.assertFalse(connection.primary)

    def test_parse_xrandr_connection_invalid(self):
        query_result = [
            "HDMI1 connected (normal left inverted right x axis y axis)",
            "    1920x1080     60.00*+",
            "    1280x1024     75.02    60.02",
            "    800x600       75.00    60.32",
        ]
        with self.assertRaises(ParseException):
            self.xrandr._parse_xrandr_connection(query_result)

    def test_parse_xrandr_connection_simple_viewport(self):
        query_result = [
            "eDP1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 270mm x 150mm",
            "    1920x1080     60.00*+  48.00",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)
        self.assertIsNotNone(connection)
        self.assertEqual("eDP1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertEqual(60, connection.display.rate)
        self.assertEqual("1920x1080", connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080"], connection.display.supported_modes)

        self.assertIsNotNone(connection.viewport)
        self.assertEqual("1920x1080", connection.viewport.size)
        self.assertEqual("0x0", connection.viewport.panning)
        self.assertEqual("normal", connection.viewport.rotate)
        self.assertEqual("0x0", connection.viewport.pos)
        self.assertEqual("1x1", connection.viewport.scale)

        self.assertTrue(connection.primary)

    def test_parse_xrandr_connection_not_primary(self):
        query_result = [
            "eDP1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 270mm x 150mm",
            "    1920x1080     60.00*+  48.00",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)
        self.assertIsNotNone(connection)
        self.assertEqual("eDP1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertEqual(60, connection.display.rate)
        self.assertEqual("1920x1080", connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080"], connection.display.supported_modes)

        self.assertIsNotNone(connection.viewport)
        self.assertEqual("1920x1080", connection.viewport.size)
        self.assertEqual("0x0", connection.viewport.panning)
        self.assertEqual("normal", connection.viewport.rotate)
        self.assertEqual("0x0", connection.viewport.pos)
        self.assertEqual("1x1", connection.viewport.scale)

        self.assertFalse(connection.primary)

    def test_parse_xrandr_connection_primary_rotated_positioned(self):
        query_result = [
            "eDP1 connected 1920x1080+1280+800 left (normal left inverted right x axis y axis) 270mm x 150mm",
            "    1920x1080     60.00*+  48.00",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)
        self.assertIsNotNone(connection)
        self.assertEqual("eDP1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertEqual(60, connection.display.rate)
        self.assertEqual("1920x1080", connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080"], connection.display.supported_modes)

        self.assertIsNotNone(connection.viewport)
        self.assertEqual("1920x1080", connection.viewport.size)
        self.assertEqual("0x0", connection.viewport.panning)
        self.assertEqual("left", connection.viewport.rotate)
        self.assertEqual("1280x800", connection.viewport.pos)
        self.assertEqual("1x1", connection.viewport.scale)

        self.assertFalse(connection.primary)

    def test_parse_xrandr_connection_primary_positioned_panned(self):
        query_result = [
            "eDP1 connected primary 1920x1080+1280+800 (normal left inverted right x axis y axis) 270mm x 150mm panning 1920x1080+1280+800",
            "    1920x1080     60.00*+  48.00",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)
        self.assertIsNotNone(connection)
        self.assertEqual("eDP1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertEqual(60, connection.display.rate)
        self.assertEqual("1920x1080", connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080"], connection.display.supported_modes)

        self.assertIsNotNone(connection.viewport)
        self.assertEqual("1920x1080", connection.viewport.size)
        self.assertEqual("1920x1080+1280+800", connection.viewport.panning)
        self.assertEqual("normal", connection.viewport.rotate)
        self.assertEqual("1280x800", connection.viewport.pos)
        self.assertEqual("1x1", connection.viewport.scale)

        self.assertTrue(connection.primary)

    def test_parse_xrandr_connection_scaled_positioned(self):
        query_result = [
            "eDP1 connected primary 2496x1404+1920+1080 (normal left inverted right x axis y axis) 270mm x 150mm panning 2496x1404+1920+1080",
            "    1920x1080     60.00*+  48.00",
        ]
        connection = self.xrandr._parse_xrandr_connection(query_result)
        self.assertIsNotNone(connection)
        self.assertEqual("eDP1", connection.name)

        self.assertIsNotNone(connection.display)
        self.assertEqual(60, connection.display.rate)
        self.assertEqual("1920x1080", connection.display.mode)
        self.assertEqual("1920x1080", connection.display.preferred_mode)
        self.assertEqual(["1920x1080"], connection.display.supported_modes)

        self.assertIsNotNone(connection.viewport)
        self.assertEqual("2496x1404", connection.viewport.size)
        self.assertEqual("2496x1404+1920+1080", connection.viewport.panning)
        self.assertEqual("normal", connection.viewport.rotate)
        self.assertEqual("1920x1080", connection.viewport.pos)
        self.assertEqual("1.3x1.3", connection.viewport.scale)

        self.assertTrue(connection.primary)

    def test_parse_geometry(self):
        m = self.xrandr._parse_geometry("1920x1080+100+200")
        expected = ("1920x1080", "100x200")
        self.assertEqual(expected, m)

    def test_xrandr_exception(self):
        try:
            self.xrandr._xrandr(
                ["--output", "FOOBAR", "--mode", "800x600+0+0"])
            self.fail("exception expected")
        except XrandrException:
            pass

    def test_group_query_result(self):
        query_result = [
            "LVDS1 connected", "  1920x1080+*", "  1366x768", "  1280x800",
            "DP1 connected", "  1920x1080+*", "HDMI1 disconnected",
            "VGA1 disconnected"
        ]

        grouped = self.xrandr._group_query_result(query_result)

        self.assertEqual(4, len(grouped))
        self.assertListEqual(query_result[0:4], grouped[0])
        self.assertListEqual(query_result[4:6], grouped[1])
        self.assertListEqual(query_result[6:7], grouped[2])
        self.assertListEqual(query_result[7:], grouped[3])

    def test_edid_from_query_item(self):
        query_result = [
            "LVDS1 connected foo bar", "\tIdentifier: 0x45",
            "\tTimestamp: 123456789", "\tEDID:", "\t\t0", "\t\t1", "\t\t2",
            "\t\t3", "\t\t4", "\t\t5", "\t\t6", "\t\t7",
            "\tBroadcast RGB: Automatic", "\t\tsupported: Automatic, Full",
            "\taudio: auto", "\t\tsupported: auto, on"
        ]

        edid = self.xrandr._edid_from_query_item(query_result)
        self.assertEqual("01234567", edid)
Example #14
0
class TestXrandr(TestCase):
    xrandr = Xrandr()

    def test_compose_mode_args(self):
        xrandr = Xrandr()
        xrandr.EXECUTABLE = "stub"

        outputs = [
            Output("LVDS1", Geometry(1366, 768), primary=True),
            Output("DP1", Geometry(1920, 1080, 1366, 0)),
            Output("VGA1", Geometry(800, 600, 0, 768))
        ]

        p = Profile("default", outputs)

        xrandr_connections = [XrandrOutput("HDMI1"), XrandrOutput("HDMI2")]

        command = xrandr.__compose_mode_args__(p, xrandr_connections)

        num_of_outputs = len(outputs) + len(xrandr_connections)

        self.assertEqual(num_of_outputs, command.count(xrandr.OUTPUT_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.POS_KEY))
        self.assertEqual(len(outputs), command.count(xrandr.MODE_KEY))
        self.assertEqual(len(xrandr_connections),
                         command.count(xrandr.OFF_KEY))
        self.assertEqual(1, command.count(xrandr.PRIMARY_KEY))
        self.assertEqual(1, command.count("LVDS1"))
        self.assertEqual(1, command.count("DP1"))
        self.assertEqual(1, command.count("VGA1"))
        self.assertEqual(1, command.count("HDMI1"))
        self.assertEqual(1, command.count("HDMI2"))

    def test_parse_output_details(self):
        c1 = self.xrandr.parse_output_details("1366x768+0+312 (foo bar)")
        self.assertDictEqual(
            {
                'primary': False,
                'pos': '0x312',
                'res': '1366x768',
                'rotate': None
            }, c1)

        c2 = self.xrandr.parse_output_details(
            "primary 1366x1080+0+0 inverted (foo bar) 130mm x 70mm panning 1366x1080+0+0"
        )
        self.assertDictEqual(
            {
                'primary': True,
                'rotate': 'inverted',
                'res': '1366x1080',
                'pos': '0x0'
            }, c2)

        c3 = self.xrandr.parse_output_details("(foo bar)")
        self.assertDictEqual({}, c3)

    def test_mode_from_str(self):
        m = self.xrandr.parse_geometry("1920x1080+100+200")
        expected = ("1920x1080", "100x200")
        self.assertEqual(expected, m)

    def test_xrandr_exception(self):
        try:
            self.xrandr.__xrandr__(
                ["--output", "FOOBAR", "--mode", "800x600+0+0"])
            self.fail("exception expected")
        except XrandrException:
            pass

    def test_group_query_result(self):
        query_result = [
            "LVDS1 connected", "  1920x1080+*", "  1366x768", "  1280x800",
            "DP1 connected", "  1920x1080+*", "HDMI1 disconnected",
            "VGA1 disconnected"
        ]

        grouped = self.xrandr.group_query_result(query_result)

        self.assertEqual(4, len(grouped))
        self.assertListEqual(query_result[0:4], grouped[0])
        self.assertListEqual(query_result[4:6], grouped[1])
        self.assertListEqual(query_result[6:7], grouped[2])
        self.assertListEqual(query_result[7:], grouped[3])

    def test_edid_from_query_item(self):
        query_result = [
            "LVDS1 connected foo bar", "\tIdentifier: 0x45",
            "\tTimestamp: 123456789", "\tEDID:", "\t\t0", "\t\t1", "\t\t2",
            "\t\t3", "\t\t4", "\t\t5", "\t\t6", "\t\t7",
            "\tBroadcast RGB: Automatic", "\t\tsupported: Automatic, Full",
            "\taudio: auto", "\t\tsupported: auto, on"
        ]

        edid = self.xrandr.edid_from_query_item(query_result)
        self.assertEqual("01234567", edid)