Skip to content

Commit

Permalink
Fix windows not resizing correctly when moving between displays with …
Browse files Browse the repository at this point in the history
…different scaling

For some reason, Windows doesn't always set the window size correctly after moving it to a display
that has different scaling to the previous one. I don't know if it's trying to be clever by being aware of the
target display's scaling and adjusting the size parameter automatically?
This is fixed by just retrying the operation until the window's rect matches our target.

I actually implemented this in LKP previously in what might have been a related issue. Retries
are now built into `Window.move`, which `Window.set_pos` now uses. Therefore, retry logic in
the LKP function is no longer required
  • Loading branch information
Crozzers committed Nov 24, 2023
1 parent 86db902 commit 6fb326d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 14 deletions.
25 changes: 17 additions & 8 deletions src/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,24 @@ def is_minimised(self) -> bool:
def is_resizable(self) -> bool:
return win32gui.GetWindowLong(self.id, win32con.GWL_STYLE) & win32con.WS_THICKFRAME

def move(self, coords: XandY):
def move(self, coords: XandY, size: Optional[XandY] = None):
"""
Move the window to a new position. This does not resize the window or
adjust placement
Move the window to a new position. This does not adjust placement.
Args:
coords: the new coordinates to move do
size: if given, the window will be set to this size.
Otherwise, current window size will be maintained
"""
size = size_from_rect(win32gui.GetWindowRect(self.id))
win32gui.MoveWindow(self.id, *coords, *size, False)
size = size or self.get_size()
target_rect: Rect = (*coords, coords[0] + size[0], coords[1] + size[1])
tries = 0
while self.get_rect() != target_rect and tries < 3:
# multi-monitor setups with different scaling often don't resize the window properly first try
# so we try multiple times and force repaints after the first one
win32gui.MoveWindow(self.id, *coords, *size, tries > 1)
tries += 1
log.debug(f'move window {self.id}, {target_rect=}, {self.get_rect()=}, {tries=}')
self.refresh()

def rebound(self, coords: XandY | Rect) -> XandY:
Expand Down Expand Up @@ -367,9 +378,7 @@ def set_pos(self, rect: Rect, placement: Optional[Placement] = None):
if placement:
win32gui.SetWindowPlacement(self.id, placement)

win32gui.MoveWindow(self.id, *rect[:2], w, h, True)
log.debug(f'move window {self.id}, X,Y:{rect[:2]!r}, W:{w}, H:{h}')
self.refresh()
self.move(rect[:2], (w, h))
except pywintypes.error as e:
log.error('err moving window %s : %s' % (win32gui.GetWindowText(self.id), e))

Expand Down
7 changes: 1 addition & 6 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ def lkp(window: Window) -> bool:
if not last_instance:
return False
log.info(f'apply LKP: {window} -> {last_instance}')
orig_rect = window.rect
tries = 0

# if the last known process instance was minimised then we need to override the placement here
rect = last_instance.rect
Expand All @@ -126,10 +124,7 @@ def lkp(window: Window) -> bool:
rect = placement[4]
placement = (placement[0], show_cmd, (-1, -1), (-1, -1), placement[4])

while window.get_rect() == orig_rect and tries < 3:
window.set_pos(rect, placement)
tries += 1
time.sleep(0.1)
window.set_pos(rect, placement)
return True

def mtm(window: Window) -> bool:
Expand Down

0 comments on commit 6fb326d

Please sign in to comment.