def test_as_rects(self): """StrutPartial: as_rects (basic function)""" test_struts = [ StrutPartial(left=1, right=2, top=3, bottom=4), StrutPartial( left=1, right=2, top=3, bottom=4, left_start_y=5, left_end_y=6, right_start_y=7, right_end_y=8, top_start_x=9, top_end_x=10, bottom_start_x=11, bottom_end_x=12), StrutPartial(left=5000, right=6000, top=7000, bottom=8000), StrutPartial( left=1, right=2, top=3, bottom=4, left_start_y=-2000, left_end_y=3000, right_start_y=-4000, right_end_y=5000, top_start_x=-6000, top_end_x=7000, bottom_start_x=-8000, bottom_end_x=9000), StrutPartial( left=1, right=2, top=3, bottom=4, left_start_y=2000, left_end_y=-3000, right_start_y=4000, right_end_y=-5000, top_start_x=6000, top_end_x=-7000, bottom_start_x=8000, bottom_end_x=-9000), ] for dtop_rect in (Rectangle(0, 0, 20, 30), Rectangle(40, 50, 70, 80)): print("Desktop Rectangle: ", dtop_rect) for strut in test_struts: print("Desktop Rectangle: ", dtop_rect, " | Strut: ", strut) self.assertEqual(strut.as_rects(dtop_rect), [x for x in ( # Left (Edge.LEFT, Rectangle(x=dtop_rect.x, y=strut.left_start_y, width=strut.left, y2=strut.left_end_y ).intersect(dtop_rect)), # Right (Edge.RIGHT, Rectangle( x=dtop_rect.x2, y=strut.right_start_y, width=-strut.right, y2=strut.right_end_y ).intersect(dtop_rect)), # Top (Edge.TOP, Rectangle(x=strut.top_start_x, y=dtop_rect.y, x2=strut.top_end_x, height=strut.top ).intersect(dtop_rect)), # Bottom (Edge.BOTTOM, Rectangle( x=strut.bottom_start_x, y=dtop_rect.y2, x2=strut.bottom_end_x, height=-strut.bottom ).intersect(dtop_rect))) if x[1]])
def test_as_rects_pruning(self): """StrutPartial: as_rects doesn't return empty rects""" dtop_rect = Rectangle(1, 2, 30, 40) self.assertEqual( StrutPartial(5, 0, 0, 0).as_rects(dtop_rect), [(Edge.LEFT, Rectangle(x=1, y=2, width=5, height=40))]) self.assertEqual( StrutPartial(0, 6, 0, 0).as_rects(dtop_rect), [(Edge.RIGHT, Rectangle( x=dtop_rect.x2 - 6, y=2, width=6, height=40))]) self.assertEqual( StrutPartial(0, 0, 7, 0).as_rects(dtop_rect), [(Edge.TOP, Rectangle(x=1, y=2, width=30, height=7))]) self.assertEqual( StrutPartial(0, 0, 0, 8).as_rects(dtop_rect), [(Edge.BOTTOM, Rectangle( x=1, y=dtop_rect.y2 - 8, width=30, height=8))])
def test_repr(self): """UsableRegion: __repr__""" test_region = UsableRegion() self.assertEqual(repr(test_region), "Region(<Monitors=[], Struts=[]>)") test_region.set_monitors([Rectangle(1, 2, 3, 4)]) self.assertEqual(repr(test_region), "Region(" "<Monitors=[Rectangle(x=1, y=2, width=3, height=4)], Struts=[]>)") test_region.set_panels( [StrutPartial(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)]) self.assertEqual(repr(test_region), "Region(<" "Monitors=[Rectangle(x=1, y=2, width=3, height=4)], " "Struts=[StrutPartial(left=1, right=2, top=3, bottom=4, " "left_start_y=5, left_end_y=6, right_start_y=7, right_end_y=8, " "top_start_x=9, top_end_x=10, bottom_start_x=11, bottom_end_x=12)]" ">)")
def test_issue_108(self): """UsableRegion: windows use of space left free by narrow panels Regression test for #64, #65, and #108. """ test_region = UsableRegion() test_region.set_monitors([Rectangle(0, 0, 1920, 1080)]) test_region.set_panels([StrutPartial(bottom=33, bottom_start_x=1022, bottom_end_x=1919)]) # Left half self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, 0, 960, 1080)), Rectangle(x=0, y=0, width=960, height=1080)) # Right half self.assertEqual(test_region.clip_to_usable_region( Rectangle(960, 0, 960, 1080)), Rectangle(x=960, y=0, width=960, height=1080 - 33))
def test_update_typecheck(self): """UsableRegion: type enforcement for internal _update function""" test_region = UsableRegion() with self.assertRaises(TypeError): # Must be a *list* of Rectangles test_region.set_monitors(Rectangle(0, 0, 1280, 1024)) test_region = UsableRegion() with self.assertRaises(TypeError): # Use a tuple as a test because, just because it's a namedtuple # doesn't mean we want *any* tuple with the right arity test_region.set_monitors([(0, 0, 1280, 1024)]) test_region = UsableRegion() with self.assertRaises(TypeError): # Must be a *list* of StrutPartials test_region.set_panels( StrutPartial(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) test_region = UsableRegion() with self.assertRaises(TypeError): # Use a tuple as a test because, just because it's a namedtuple # doesn't mean we want *any* tuple with the right arity test_region.set_panels([(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)])
def test_issue_45(self): """UsableRegion: struts on internal monitor edges work properly (Test that the ambiguous aspect of the spec is interpreted in accordance with how Unity actually implemented it.) """ # Use the actual --debug geometry from issue 45 so this is also # a regression test. test_region = UsableRegion() test_region.set_monitors([ Rectangle(0, 0, 1920, 1200), Rectangle(1920, 0, 1920, 1200)]) test_region.set_panels([StrutPartial(*x) for x in [ [49, 0, 0, 0, 24, 1199, 0, 0, 0, 0, 0, 0], [1969, 0, 0, 0, 24, 1199, 0, 0, 0, 0, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 0, 1919, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 1920, 3839, 0, 0]]]) # Right monitor (easy case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1920, 0, 100, 100)), Rectangle(x=1969, y=24, width=100 - 49, height=100 - 24)) # Left monitor (problem case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, 0, 100, 100)), Rectangle(x=49, y=24, width=100 - 49, height=100 - 24)) # Asymmetric monitors (left monitor bigger) test_region = UsableRegion() test_region.set_monitors([ Rectangle(0, 0, 1920, 1200), Rectangle(1920, 0, 1280, 1024)]) test_region.set_panels([StrutPartial(*x) for x in [ [49, 0, 0, 0, 24, 1199, 0, 0, 0, 0, 0, 0], [1969, 0, 0, 0, 24, 1023, 0, 0, 0, 0, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 0, 1919, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 1920, 3199, 0, 0]]]) # Right monitor (easy case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1920, 0, 100, 100)), Rectangle(x=1969, y=24, width=100 - 49, height=100 - 24)) # Left monitor (problem case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, 0, 100, 100)), Rectangle(x=49, y=24, width=100 - 49, height=100 - 24)) # Asymmetric monitors (left monitor smaller) test_region = UsableRegion() test_region.set_monitors([ Rectangle(0, 0, 1280, 1024), Rectangle(1280, 0, 1920, 1200)]) test_region.set_panels([StrutPartial(*x) for x in [ [49, 0, 0, 0, 24, 1023, 0, 0, 0, 0, 0, 0], [1329, 0, 0, 0, 24, 1199, 0, 0, 0, 0, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 0, 1023, 0, 0], [0, 0, 24, 0, 0, 0, 0, 0, 1024, 3199, 0, 0]]]) # Right monitor (easy case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1280, 0, 100, 100)), Rectangle(x=1329, y=24, width=100 - 49, height=100 - 24)) # Left monitor (problem case) self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, 0, 100, 100)), Rectangle(x=49, y=24, width=100 - 49, height=100 - 24))
def test_move_to_usable_region(self): """UsableRegion: move_to_usable_region""" test_region = UsableRegion() # Quick integration test for internal call to find_monitor_for self.assertIsNone( test_region.move_to_usable_region(Rectangle(0, 0, 1, 1))) # Actual rectangles of my monitors # TODO: Double-check that this matches the real-world API outputs # (eg. make sure there are no lurking off-by-one errors) test_region.set_monitors([ Rectangle(0, 56, 1280, 1024), Rectangle(1280, 0, 1920, 1080), Rectangle(3200, 56, 1280, 1024)]) # Actual struts harvested from my desktop's panels # (Keep the empty struts at the beginning and end. One from an # auto-hiding Plasma 5 panel caught an early bug where # only the last strut subtracted from a monitor was retained) test_region.set_panels([ StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 3200, 4479), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 1280, 3199), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1279), StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ]) # Out-of-bounds Space bottom = 1024 + 56 panel = 30 self.assertEqual(test_region.move_to_usable_region( Rectangle(-3, 1, 2, 3)), Rectangle(0, 56, 2, 3)) self.assertEqual(test_region.move_to_usable_region( Rectangle(200, -5, 4, 5)), Rectangle(200, 56, 4, 5)) self.assertEqual(test_region.move_to_usable_region( Rectangle(5000, 200, 6, 7)), Rectangle(4480 - 6, 200, 6, 7)) self.assertEqual(test_region.move_to_usable_region( Rectangle(200, 5000, 8, 31)), Rectangle(200, bottom - panel - 31, 8, 31)) self.assertEqual(test_region.move_to_usable_region( Rectangle(2000, 5000, 10, 32)), Rectangle(2000, 1080 - panel - 32, 10, 32)) self.assertEqual(test_region.move_to_usable_region( Rectangle(3300, 5000, 12, 33)), Rectangle(3300, bottom - panel - 33, 12, 33)) # Dead Space self.assertEqual(test_region.move_to_usable_region( Rectangle(1, 2, 3, 4)), Rectangle(1, 56, 3, 4)) self.assertEqual(test_region.move_to_usable_region( Rectangle(3203, 5, 6, 7)), Rectangle(3203, 56, 6, 7)) # Reserved Space (fallback) self.assertEqual(test_region.move_to_usable_region( Rectangle(0, bottom - panel - 3, 1, 5)), Rectangle(0, bottom - panel - 5, 1, 5)) self.assertEqual(test_region.move_to_usable_region( Rectangle(2000, bottom - panel - 4, 1, 6)), Rectangle(2000, bottom - panel - 6, 1, 6)) self.assertEqual(test_region.move_to_usable_region( Rectangle(3300, bottom - panel + 5, 1, 7)), Rectangle(3300, bottom - panel - 7, 1, 7)) # Available Space for test_rect in ( Rectangle(10, 640, 1, 1), Rectangle(3000, 640, 1, 1), Rectangle(3300, 640, 1, 1), ): self.assertIs(test_region.move_to_usable_region(test_rect), test_rect)
def test_clip_to_usable_region(self): """UsableRegion: clip_to_usable_region""" test_region = UsableRegion() # Quick integration test for internal call to find_monitor_for self.assertIsNone( test_region.clip_to_usable_region(Rectangle(0, 0, 1, 1))) # Actual rectangles of my monitors # TODO: Double-check that this matches the real-world API outputs # (eg. make sure there are no lurking off-by-one errors) test_region.set_monitors([ Rectangle(0, 56, 1280, 1024), Rectangle(1280, 0, 1920, 1080), Rectangle(3200, 56, 1280, 1024)]) # Actual struts harvested from my desktop's panels # (Keep the empty struts at the beginning and end. One from an # auto-hiding Plasma 5 panel caught an early bug where # only the last strut subtracted from a monitor was retained) test_region.set_panels([ StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 3200, 4479), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 1280, 3199), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1279), StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ]) # Out of bounds (no overlap) self.assertIsNone(test_region.clip_to_usable_region( # top Rectangle(3200, -4, 3, 4))) self.assertIsNone(test_region.clip_to_usable_region( # right Rectangle(4480, 0, 3, 4))) self.assertIsNone(test_region.clip_to_usable_region( # bottom Rectangle(3200, 1080, 3, 4))) self.assertIsNone(test_region.clip_to_usable_region( # left Rectangle(-3, 100, 3, 4))) # Out of bounds (overlap) # Top bottom = 1024 + 56 panel = 30 self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, -4, 3, 4 + 56 + 4)), Rectangle(0, 56, 3, 4)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1920, -4, 3, 4 + 4)), Rectangle(1920, 0, 3, 4)) # Right self.assertEqual(test_region.clip_to_usable_region( Rectangle(4480 - 3, 56, 3 + 3, 4)), Rectangle(4480 - 3, 56, 3, 4)) # Bottom self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, bottom - panel - 4, 3, 4 + panel + 4)), Rectangle(0, bottom - panel - 4, 3, 4)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1920, 1080 - panel - 4, 3, 4 + panel + 4)), Rectangle(1920, 1080 - panel - 4, 3, 4)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(3300, bottom - panel - 4, 3, 4 + panel + 4)), Rectangle(3300, bottom - panel - 4, 3, 4)) # Left self.assertEqual(test_region.clip_to_usable_region( Rectangle(-3, 100, 6, 4)), Rectangle(0, 100, 6 - 3, 4)) # Dead Space (no overlap) self.assertIsNone(test_region.clip_to_usable_region( Rectangle(0, 0, 20, 20))) self.assertIsNone(test_region.clip_to_usable_region( Rectangle(3200, 0, 20, 20))) # Dead Space (overlap) self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, 0, 80, 80)), Rectangle(0, 56, 80, 80 - 56)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(3200, 0, 80, 80)), Rectangle(3200, 56, 80, 80 - 56)) # Reserved Space (no overlap) self.assertIsNone(test_region.clip_to_usable_region( Rectangle(0, 1277, 1, 1)), None) self.assertIsNone(test_region.clip_to_usable_region( Rectangle(1920, 1060, 1, 1)), None) self.assertIsNone(test_region.clip_to_usable_region( Rectangle(3200, 1277, 1, 1)), None) # Reserved Space (overlap) self.assertEqual(test_region.clip_to_usable_region( Rectangle(0, bottom - panel - 10, 1, 40)), Rectangle(0, bottom - panel - 10, 1, 10)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(1920, 1080 - panel - 10, 1, 40)), Rectangle(1920, bottom - panel - 10, 1, 10)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(3200, bottom - panel - 10, 1, 40)), Rectangle(3200, bottom - panel - 10, 1, 10)) # Available Space self.assertEqual(test_region.clip_to_usable_region( Rectangle(10, 640, 1, 1)), Rectangle(10, 640, 1, 1)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(3000, 640, 1, 1)), Rectangle(3000, 640, 1, 1)) self.assertEqual(test_region.clip_to_usable_region( Rectangle(3300, 640, 1, 1)), Rectangle(3300, 640, 1, 1))
def test_find_monitor_for(self): """UsableRegion: find_monitor_for""" test_region = UsableRegion() # No monitors set self.assertIsNone(test_region.find_monitor_for(Rectangle(0, 0, 1, 1))) # Actual rectangles of my monitors # TODO: Double-check that this matches the real-world API outputs # (eg. make sure there are no lurking off-by-one errors) test_region.set_monitors([ Rectangle(0, 56, 1280, 1024), Rectangle(1280, 0, 1920, 1080), Rectangle(3200, 56, 1280, 1024)]) # Actual struts harvested from my desktop's panels # to verify that it's returning the *monitor* rectangle and not the # largest usable rectangle within. # # (Keep the empty struts at the beginning and end. One from an # auto-hiding Plasma 5 panel caught an early bug where # only the last strut subtracted from a monitor was retained) test_region.set_panels([ StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 3200, 4479), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 1280, 3199), StrutPartial(0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 1279), StrutPartial(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ]) # Out-of-bounds Space self.assertEqual(test_region.find_monitor_for( Rectangle(-3, 1, 1, 1)), Rectangle(0, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(200, -5, 1, 1)), Rectangle(0, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(5000, 200, 1, 1)), Rectangle(3200, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(200, 5000, 1, 1)), Rectangle(0, 56, 1280, 1024)) # Dead Space self.assertEqual(test_region.find_monitor_for( Rectangle(1, 1, 1, 1)), Rectangle(0, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(3203, 1, 1, 1)), Rectangle(3200, 56, 1280, 1024)) # Space under panels self.assertEqual(test_region.find_monitor_for( Rectangle(0, 1277, 1, 1)), Rectangle(0, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(0, 2000, 1, 1)), Rectangle(0, 56, 1280, 1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(3000, 2000, 1, 1)), Rectangle(1280, 0, 1920, 1080)) self.assertEqual(test_region.find_monitor_for( Rectangle(3400, 1277, 1, 1)), Rectangle(3200, 56, 1280, 1024)) # Available Space self.assertEqual(test_region.find_monitor_for( Rectangle(10, 640, 1, 1)), Rectangle(x=0, y=56, width=1280, height=1024)) self.assertEqual(test_region.find_monitor_for( Rectangle(3000, 640, 1, 1)), Rectangle(x=1280, y=0, width=1920, height=1080)) self.assertEqual(test_region.find_monitor_for( Rectangle(3300, 640, 1, 1)), Rectangle(x=3200, y=56, width=1280, height=1024))
def test_construction(self): """StrutPartial: construction""" self.assertEqual(StrutPartial(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), StrutPartial(left=1, right=2, top=3, bottom=4, left_start_y=5, left_end_y=6, right_start_y=7, right_end_y=8, top_start_x=9, top_end_x=10, bottom_start_x=11, bottom_end_x=12))