-
-
Notifications
You must be signed in to change notification settings - Fork 685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add window refresh lock to block window from updating while handler is running. #2955
base: main
Are you sure you want to change the base?
Changes from all commits
fd2db81
b4b2832
3a08317
bfa36c5
b695904
227a0e8
64bbb9d
16c45ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Windows now have a refresh lock to stop refreshing window layout happening after every add() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,7 +61,7 @@ def test_noop_handler_with_cleanup_error(capsys): | |
|
||
|
||
def test_function_handler(): | ||
"""A function can be used as a handler.""" | ||
"""A function can be used as a handler""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why all these updates to remove punctuation? |
||
obj = Mock() | ||
handler_call = {} | ||
|
||
|
@@ -86,7 +86,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_function_handler_error(capsys): | ||
"""A function handler can raise an error.""" | ||
"""A function handler can raise an error""" | ||
obj = Mock() | ||
handler_call = {} | ||
|
||
|
@@ -116,7 +116,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_function_handler_with_cleanup(): | ||
"""A function handler can have a cleanup method.""" | ||
"""A function handler can have a cleanup method""" | ||
obj = Mock() | ||
cleanup = Mock() | ||
handler_call = {} | ||
|
@@ -180,7 +180,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_generator_handler(event_loop): | ||
"""A generator can be used as a handler.""" | ||
"""A generator can be used as a handler""" | ||
obj = Mock() | ||
handler_call = {} | ||
|
||
|
@@ -213,7 +213,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_generator_handler_error(event_loop, capsys): | ||
"""A generator can raise an error.""" | ||
"""A generator can raise an error""" | ||
obj = Mock() | ||
handler_call = {} | ||
|
||
|
@@ -248,7 +248,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_generator_handler_with_cleanup(event_loop): | ||
"""A generator can have cleanup.""" | ||
"""A generator can have cleanup""" | ||
obj = Mock() | ||
cleanup = Mock() | ||
handler_call = {} | ||
|
@@ -285,7 +285,7 @@ def handler(*args, **kwargs): | |
|
||
|
||
def test_generator_handler_with_cleanup_error(event_loop, capsys): | ||
"""A generator can raise an error during cleanup.""" | ||
"""A generator can raise an error during cleanup""" | ||
obj = Mock() | ||
cleanup = Mock(side_effect=Exception("Problem in cleanup")) | ||
handler_call = {} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
assert_action_not_performed, | ||
assert_action_performed, | ||
assert_action_performed_with, | ||
performed_actions, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to see this in the form of an |
||
) | ||
|
||
|
||
|
@@ -172,6 +173,92 @@ def test_change_content(window, app): | |
assert content1.window is None | ||
|
||
|
||
def test_change_content_locked(window, app): | ||
"""The refresh of a window can be locked""" | ||
with window.refresh_lock(): | ||
assert window.content is None | ||
assert window.app == app | ||
|
||
# Set the content of the window | ||
content1 = toga.Box() | ||
window.content = content1 | ||
|
||
# The content has been assigned and not (yet) refreshed | ||
assert content1.app == app | ||
assert content1.window == window | ||
assert_action_performed_with(window, "set content", widget=content1._impl) | ||
assert_action_not_performed(content1, "refresh") | ||
|
||
# Set the content of the window to something new | ||
content2 = toga.Box() | ||
window.content = content2 | ||
|
||
# The content has been assigned and not (yet) refreshed | ||
assert content2.app == app | ||
assert content2.window == window | ||
assert_action_performed_with(window, "set content", widget=content2._impl) | ||
assert_action_not_performed(content2, "refresh") | ||
|
||
# The original content has been removed | ||
assert content1.window is None | ||
|
||
# Action refresh must not have been performed on content1 | ||
assert_action_not_performed(content1, "refresh") | ||
|
||
# Action refresh must have been performed on content2 | ||
assert_action_performed(content2, "refresh") | ||
assert len(performed_actions(content2, "refresh")) == 2 | ||
|
||
|
||
def test_change_content_locked_normal_refreshes(window, app): | ||
"""When a window is locked, a lot less refreshes would be called...""" | ||
assert window.content is None | ||
assert window.app == app | ||
boxes = [] | ||
|
||
# Set the content of the window | ||
content1 = toga.Box() | ||
window.content = content1 | ||
|
||
for w in range(0, 200): | ||
boxes.append(toga.Box()) | ||
content1.add(boxes[-1]) | ||
|
||
# Action refresh must have been performed on content1 | ||
assert_action_performed(content1, "refresh") | ||
assert len(performed_actions(content1, "refresh")) == 402 | ||
|
||
# Action refresh must have been performed on all boxes | ||
for box in boxes: | ||
assert_action_performed(box, "create Box") | ||
assert len(performed_actions(box, "create Box")) == 1 | ||
|
||
|
||
def test_change_content_locked_less_refreshes(window, app): | ||
"""When a window is locked, a lot less refreshes are called...""" | ||
with window.refresh_lock(): | ||
assert window.content is None | ||
assert window.app == app | ||
boxes = [] | ||
|
||
# Set the content of the window | ||
content1 = toga.Box() | ||
window.content = content1 | ||
|
||
for w in range(0, 200): | ||
boxes.append(toga.Box()) | ||
content1.add(boxes[-1]) | ||
|
||
# Action refresh must have been performed on content1 | ||
assert_action_performed(content1, "refresh") | ||
assert len(performed_actions(content1, "refresh")) == 2 | ||
|
||
# Action refresh must have been performed on all boxes | ||
for box in boxes: | ||
assert_action_performed(box, "create Box") | ||
assert len(performed_actions(box, "create Box")) == 1 | ||
|
||
|
||
def test_set_position(window): | ||
"""The position of the window can be set.""" | ||
window.position = (123, 456) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This flag definitely shouldn't be writable. A user shouldn't be able to inadvertently change the locking state. A getter makes sense; but I can't see a use case for releasing the lock being a public API (outside of the context manager)