Search code examples
tkintertk-toolkit

How do I calculate the rectangles of the window decoration / taskbar / titlebar in tkinter


Many questions on this site asking about the height of the titlebar or the taskbar in tkinter.
Often is the answer simply no or there are platform specific calls to the window-manager.
So this question is about having a work-around for a cross-platform way to obtain these values.

Does someone has an answer to it ?

Examples:
How to get the height of a tkinter window title bar
Python/tkinter - How do I get the window size including borders on Windows?
How do I create a new python tkinter window so fits exactly in the available desktop area, but isn't maximized?


Solution

  • You can use this formula, it takes advantage of the fact that the window manager will size your window appropriately by maximizing it. By spanning a frame into the client area you get the client you can measure from the client area y point in screen coordinates to the y point of the window in screen coordinates. Therefore you can get the height of the titlebar and are able to calculate the points for the working area of your desktop, therefore you can calculate the taskbar.

    By using wax1 and way1 this small script tries to take care of the possibility of having multiple screens. However this script was only tested on Windows11 and a single display.

    Those 3 rectangles in the end has the form of (x1,y1, width, height) as it is usual in tkinter.

    import tkinter as tk
    import sys
    
    root = tk.Tk()
    
    f = tk.Frame(root, bg='orange')
    f.place(relwidth=1,relheight=1, relx=0,rely=0)
    
    if sys.platform == "win32":
        root.state('zoomed')
    else:
        root.wm_attributes('-zoomed', True)
    root.update()
    bd      = borderwidth           = root.winfo_rootx()-root.winfo_x()
    tbh     = titlebarheight        = f.winfo_rooty()-root.winfo_y()-bd
    wax1    = working_area_x1       = root.winfo_x()+bd
    way1    = working_area_y1       = root.winfo_rooty()-tbh
    wax2    = working_area_x2       = wax1+root.winfo_width()
    way2    = working_area_y2       = way1+root.winfo_height() + tbh
    waw     = working_area_width    = wax1+root.winfo_width() - wax1
    wah     = working_area_height   = way1+root.winfo_height() - way1 + tbh
    if root.winfo_screenheight()-wah:
        tko = taskbar_offset = root.winfo_screenheight()-wah
        if way2+tko == root.winfo_screenheight():
            tkrect = wax1,way2,waw,tko
            screct = wax1,way1,waw,way2+tko
        else:#up
            tkrect = wax1,way1-tko,waw,tko
            screct = wax1,way1-tko,waw,way2
    elif root.winfo_screenwidth()-waw:
        tko = taskbar_offset = root.winfo_screenwidth()-waw
        if wax2+tko == root.winfo_screenwidth():
            tkrect = wax2,way1,tko,wah
            screct = wax1,way1,wax2+tko,wah
        else:#left
            tkrect = wax1-tko,way1,tko,wah
            screct = wax1-tko,way1,wax2,wah
    tkrect = taskbar_rect       = tkrect
    warect = working_area_rect  = wax1, way1, waw, wah
    screct = screen_rect        = screct
    
    if sys.platform == "win32":
        root.state('normal')
    else:
        root.wm_attributes('-zoomed', False)
    print(tkrect, warect, screct)
    root.mainloop()