17db96d56Sopenharmony_ci"Zoom a window to maximum height." 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciimport re 47db96d56Sopenharmony_ciimport sys 57db96d56Sopenharmony_ciimport tkinter 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciclass WmInfoGatheringError(Exception): 97db96d56Sopenharmony_ci pass 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciclass ZoomHeight: 137db96d56Sopenharmony_ci # Cached values for maximized window dimensions, one for each set 147db96d56Sopenharmony_ci # of screen dimensions. 157db96d56Sopenharmony_ci _max_height_and_y_coords = {} 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci def __init__(self, editwin): 187db96d56Sopenharmony_ci self.editwin = editwin 197db96d56Sopenharmony_ci self.top = self.editwin.top 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci def zoom_height_event(self, event=None): 227db96d56Sopenharmony_ci zoomed = self.zoom_height() 237db96d56Sopenharmony_ci 247db96d56Sopenharmony_ci if zoomed is None: 257db96d56Sopenharmony_ci self.top.bell() 267db96d56Sopenharmony_ci else: 277db96d56Sopenharmony_ci menu_status = 'Restore' if zoomed else 'Zoom' 287db96d56Sopenharmony_ci self.editwin.update_menu_label(menu='options', index='* Height', 297db96d56Sopenharmony_ci label=f'{menu_status} Height') 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci return "break" 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci def zoom_height(self): 347db96d56Sopenharmony_ci top = self.top 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci width, height, x, y = get_window_geometry(top) 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci if top.wm_state() != 'normal': 397db96d56Sopenharmony_ci # Can't zoom/restore window height for windows not in the 'normal' 407db96d56Sopenharmony_ci # state, e.g. maximized and full-screen windows. 417db96d56Sopenharmony_ci return None 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci try: 447db96d56Sopenharmony_ci maxheight, maxy = self.get_max_height_and_y_coord() 457db96d56Sopenharmony_ci except WmInfoGatheringError: 467db96d56Sopenharmony_ci return None 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci if height != maxheight: 497db96d56Sopenharmony_ci # Maximize the window's height. 507db96d56Sopenharmony_ci set_window_geometry(top, (width, maxheight, x, maxy)) 517db96d56Sopenharmony_ci return True 527db96d56Sopenharmony_ci else: 537db96d56Sopenharmony_ci # Restore the window's height. 547db96d56Sopenharmony_ci # 557db96d56Sopenharmony_ci # .wm_geometry('') makes the window revert to the size requested 567db96d56Sopenharmony_ci # by the widgets it contains. 577db96d56Sopenharmony_ci top.wm_geometry('') 587db96d56Sopenharmony_ci return False 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci def get_max_height_and_y_coord(self): 617db96d56Sopenharmony_ci top = self.top 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci screen_dimensions = (top.winfo_screenwidth(), 647db96d56Sopenharmony_ci top.winfo_screenheight()) 657db96d56Sopenharmony_ci if screen_dimensions not in self._max_height_and_y_coords: 667db96d56Sopenharmony_ci orig_state = top.wm_state() 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci # Get window geometry info for maximized windows. 697db96d56Sopenharmony_ci try: 707db96d56Sopenharmony_ci top.wm_state('zoomed') 717db96d56Sopenharmony_ci except tkinter.TclError: 727db96d56Sopenharmony_ci # The 'zoomed' state is not supported by some esoteric WMs, 737db96d56Sopenharmony_ci # such as Xvfb. 747db96d56Sopenharmony_ci raise WmInfoGatheringError( 757db96d56Sopenharmony_ci 'Failed getting geometry of maximized windows, because ' + 767db96d56Sopenharmony_ci 'the "zoomed" window state is unavailable.') 777db96d56Sopenharmony_ci top.update() 787db96d56Sopenharmony_ci maxwidth, maxheight, maxx, maxy = get_window_geometry(top) 797db96d56Sopenharmony_ci if sys.platform == 'win32': 807db96d56Sopenharmony_ci # On Windows, the returned Y coordinate is the one before 817db96d56Sopenharmony_ci # maximizing, so we use 0 which is correct unless a user puts 827db96d56Sopenharmony_ci # their dock on the top of the screen (very rare). 837db96d56Sopenharmony_ci maxy = 0 847db96d56Sopenharmony_ci maxrooty = top.winfo_rooty() 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci # Get the "root y" coordinate for non-maximized windows with their 877db96d56Sopenharmony_ci # y coordinate set to that of maximized windows. This is needed 887db96d56Sopenharmony_ci # to properly handle different title bar heights for non-maximized 897db96d56Sopenharmony_ci # vs. maximized windows, as seen e.g. in Windows 10. 907db96d56Sopenharmony_ci top.wm_state('normal') 917db96d56Sopenharmony_ci top.update() 927db96d56Sopenharmony_ci orig_geom = get_window_geometry(top) 937db96d56Sopenharmony_ci max_y_geom = orig_geom[:3] + (maxy,) 947db96d56Sopenharmony_ci set_window_geometry(top, max_y_geom) 957db96d56Sopenharmony_ci top.update() 967db96d56Sopenharmony_ci max_y_geom_rooty = top.winfo_rooty() 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci # Adjust the maximum window height to account for the different 997db96d56Sopenharmony_ci # title bar heights of non-maximized vs. maximized windows. 1007db96d56Sopenharmony_ci maxheight += maxrooty - max_y_geom_rooty 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci self._max_height_and_y_coords[screen_dimensions] = maxheight, maxy 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci set_window_geometry(top, orig_geom) 1057db96d56Sopenharmony_ci top.wm_state(orig_state) 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci return self._max_height_and_y_coords[screen_dimensions] 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_cidef get_window_geometry(top): 1117db96d56Sopenharmony_ci geom = top.wm_geometry() 1127db96d56Sopenharmony_ci m = re.match(r"(\d+)x(\d+)\+(-?\d+)\+(-?\d+)", geom) 1137db96d56Sopenharmony_ci return tuple(map(int, m.groups())) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_cidef set_window_geometry(top, geometry): 1177db96d56Sopenharmony_ci top.wm_geometry("{:d}x{:d}+{:d}+{:d}".format(*geometry)) 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ciif __name__ == "__main__": 1217db96d56Sopenharmony_ci from unittest import main 1227db96d56Sopenharmony_ci main('idlelib.idle_test.test_zoomheight', verbosity=2, exit=False) 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci # Add htest? 125