Skip to content

Commit

Permalink
Merge pull request #2155 from proneon267/patch-20
Browse files Browse the repository at this point in the history
Improved DPI Scaling on Windows and Fixed related Bugs
  • Loading branch information
mhsmith authored Nov 11, 2024
2 parents 3376c06 + 066d5b6 commit 75806d2
Show file tree
Hide file tree
Showing 22 changed files with 742 additions and 151 deletions.
1 change: 1 addition & 0 deletions changes/2155.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DPI scaling on Windows is now improved and related bugs are fixed.
14 changes: 10 additions & 4 deletions core/src/toga/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __str__(self) -> str:


class Position(NamedTuple):
"""A 2D window position."""
"""A 2D position."""

#: X coordinate, in CSS pixels.
x: int
Expand All @@ -46,15 +46,21 @@ def __add__(self, other):
def __sub__(self, other):
return Position(self.x - other.x, self.y - other.y)

def __mul__(self, other):
return Position(self.x * other, self.y * other)


class Size(NamedTuple):
"""A 2D window size."""
"""A 2D size."""

#: Width
#: Width, in CSS pixels.
width: int

#: Height
#: Height, in CSS pixels.
height: int

def __str__(self) -> str:
return f"({self.width} x {self.height})"

def __mul__(self, other):
return Size(self.width * other, self.height * other)
23 changes: 22 additions & 1 deletion core/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ def test_position_properties():
assert p.x == 1
assert p.y == 2
assert str(p) == "(1, 2)"
p == (1, 2) # Tuple equivalence for backwards-compatibility

assert p == Position(1, 2)
assert p != Position(1, 3)

assert p == (1, 2) # Tuple equivalence for backwards-compatibility
assert p != (1, 3)


def test_add_positions():
Expand All @@ -20,10 +25,26 @@ def test_sub_positions():
assert Position(1, 2) - Position(3, 4) == Position(-2, -2)


def test_mul_position():
"""Multiplying a Position multiplies its X and Y values"""
assert Position(1, 2) * 2 == Position(2, 4)
assert Position(1, 2) * 0.5 == Position(0.5, 1)
assert Position(1, 2) * 0 == Position(0, 0)
assert Position(1, 2) * -1 == Position(-1, -2)


def test_size_properties():
"""A Size NamedTuple has a width and height."""
s = Size(1, 2)
assert s.width == 1
assert s.height == 2
assert str(s) == "(1 x 2)"
s == (1, 2) # Tuple equivalence for backwards-compatibility


def test_mul_size():
"""Multiplying a Size multiplies its width and height values"""
assert Size(1, 2) * 2 == Size(2, 4)
assert Size(1, 2) * 0.5 == Size(0.5, 1)
assert Size(1, 2) * 0 == Size(0, 0)
assert Size(1, 2) * -1 == Size(-1, -2)
3 changes: 1 addition & 2 deletions examples/command/command/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,9 @@ def startup(self):
cmd5 = toga.Command(
self.action5,
text="TB Action 5",
tooltip="Perform toolbar action 5",
order=2,
group=sub_menu,
) # there is deliberately no icon to show that a toolbar action also works with text
) # there is deliberately no icon or tooltip
cmd6 = toga.Command(
self.action6,
text="Action 6",
Expand Down
117 changes: 87 additions & 30 deletions examples/window/window/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,79 @@
from functools import partial

import toga
from toga.constants import COLUMN, RIGHT
from toga.constants import COLUMN, RIGHT, ROW
from toga.style import Pack


class WindowDemoApp(toga.App):
# Button callback functions
def do_origin(self, widget, **kwargs):
self.main_window.position = (0, 0)
self.do_report()

def do_up(self, widget, **kwargs):
self.main_window.position = (
self.main_window.position.x,
self.main_window.position.y - 200,
)
self.do_report()

def do_down(self, widget, **kwargs):
self.main_window.position = (
self.main_window.position.x,
self.main_window.position.y + 200,
)
self.do_report()

def do_left(self, widget, **kwargs):
self.main_window.position = (-1000, 500)
self.main_window.position = (
self.main_window.position.x - 200,
self.main_window.position.y,
)
self.do_report()

def do_right(self, widget, **kwargs):
self.main_window.position = (2000, 500)
self.main_window.position = (
self.main_window.position.x + 200,
self.main_window.position.y,
)
self.do_report()

def do_left_current_screen(self, widget, **kwargs):
self.main_window.screen_position = (0, 100)
def do_screen_top(self, widget, **kwargs):
self.main_window.screen_position = (
self.main_window.screen_position.x,
0,
)
self.do_report()

def do_screen_bottom(self, widget, **kwargs):
self.main_window.screen_position = (
self.main_window.screen_position.x,
self.main_window.screen.size.height - self.main_window.size.height,
)
self.do_report()

def do_right_current_screen(self, widget, **kwargs):
self.main_window.screen_position = (1080, 100)
def do_screen_left(self, widget, **kwargs):
self.main_window.screen_position = (
0,
self.main_window.screen_position.y,
)
self.do_report()

def do_screen_right(self, widget, **kwargs):
self.main_window.screen_position = (
self.main_window.screen.size.width - self.main_window.size.width,
self.main_window.screen_position.y,
)
self.do_report()

def do_small(self, widget, **kwargs):
self.main_window.size = (400, 300)
self.do_report()

def do_large(self, widget, **kwargs):
self.main_window.size = (1500, 1000)
self.do_report()

def do_app_full_screen(self, widget, **kwargs):
if self.is_full_screen:
Expand Down Expand Up @@ -85,6 +132,7 @@ def do_new_windows(self, widget, **kwargs):

def do_screen_change(self, screen, widget, **kwargs):
self.current_window.screen = screen
self.do_report()

async def do_save_screenshot(self, screen, window, **kwargs):
screenshot = screen.as_image()
Expand Down Expand Up @@ -112,11 +160,14 @@ async def do_hide_cursor(self, widget, **kwargs):
self.show_cursor()
self.label.text = "Cursor should be back!"

def do_report(self, widget, **kwargs):
def do_report(self, *args, **kwargs):
window = self.main_window
screen = window.screen
self.label.text = (
f"Window {self.main_window.title!r} "
f"has size {self.main_window.size!r} "
f"at {self.main_window.position!r}"
f"Window: size={tuple(window.size)}, position={tuple(window.position)}, "
f"screen_position={tuple(window.screen_position)}\n"
f"Screen: name={screen.name!r}, size={tuple(screen.size)}, "
f"origin={tuple(screen.origin)}"
)

def do_next_content(self, widget):
Expand Down Expand Up @@ -166,21 +217,30 @@ def startup(self):

# Buttons
btn_style = Pack(flex=1, padding=5)
btn_do_origin = toga.Button(
"Go to origin", on_press=self.do_origin, style=btn_style
)
btn_do_left = toga.Button("Go left", on_press=self.do_left, style=btn_style)
btn_do_right = toga.Button("Go right", on_press=self.do_right, style=btn_style)
btn_do_left_current_screen = toga.Button(
"Go left on current screen",
on_press=self.do_left_current_screen,
style=btn_style,

row_move = toga.Box(
style=Pack(direction=ROW),
children=[
toga.Label("Move: "),
toga.Button("Origin", on_press=self.do_origin, style=btn_style),
toga.Button("Up", on_press=self.do_up, style=btn_style),
toga.Button("Down", on_press=self.do_down, style=btn_style),
toga.Button("Left", on_press=self.do_left, style=btn_style),
toga.Button("Right", on_press=self.do_right, style=btn_style),
],
)
btn_do_right_current_screen = toga.Button(
"Go right on current screen",
on_press=self.do_right_current_screen,
style=btn_style,

row_screen_edge = toga.Box(
style=Pack(direction=ROW),
children=[
toga.Label("Screen edge: "),
toga.Button("Top", on_press=self.do_screen_top, style=btn_style),
toga.Button("Bottom", on_press=self.do_screen_bottom, style=btn_style),
toga.Button("Left", on_press=self.do_screen_left, style=btn_style),
toga.Button("Right", on_press=self.do_screen_right, style=btn_style),
],
)

btn_do_small = toga.Button(
"Become small", on_press=self.do_small, style=btn_style
)
Expand Down Expand Up @@ -256,11 +316,9 @@ def startup(self):
self.inner_box = toga.Box(
children=[
self.label,
btn_do_origin,
btn_do_left,
btn_do_right,
btn_do_left_current_screen,
btn_do_right_current_screen,
row_move,
row_screen_edge,
btn_do_report,
btn_do_small,
btn_do_large,
btn_do_app_full_screen,
Expand All @@ -269,7 +327,6 @@ def startup(self):
btn_do_new_windows,
btn_do_current_window_cycling,
btn_do_hide_cursor,
btn_do_report,
btn_change_content,
btn_hide,
btn_beep,
Expand Down
Loading

0 comments on commit 75806d2

Please sign in to comment.