Title: Python tkinter form display a few pixels off
Tags: python-3.x,tkinter

Question: I'm attempting to use tkinter to display a window in a specific point in the screen (0.0 = top/left, 1.0 = bottom/right).  Unfortunately, the display is often approximately 8 pixels off from where it should be.  As I want to be able to center the form (not its top left point), I've written a function to calculate the x and y positions with the form's dimensions.  It uses win32api.GetMonitorInfo and win32api.MonitorFromPoint to calculate the monitor and taskbar's size so it does not generate the form under the taskbar.)
Since tkinter allows positioning using the geometry("form_width x form_height + x_offset + y_offset"), whenever I attempt to get it to generate at an offset of (0,0) it generates slightly too far to the right - a position of (-8,0) is needed to load the window at the top left of the screen with no gap.
Loading it at the bottom left (0,1) generates it slightly too high (there is a gap between the form and taskbar) and too far to the right.  Similar problems exist for top right and bottom right as well.  In short, it always generates about 8 pixels too far to the right, and if it's attempting to generate at the bottom of the workspace of the monitor, it generates 8 too high.  (Generating at the top does not put it too high.)
When the positioning function is called after all elements have been added to the form, it calls .update() on the form to recalculate its required space, then uses .winfo_reqwidth() and .winfo_reqheight() to perform all necessary calculations, after which the result is passed to the window's geometry().
Why is the pixel offset problem caused?  Is it due to some padding of the form's elements that update() does not account for, or is it a problem with my computer's display?  (I don't think it is with the screen - all other applications function properly, but I could be wrong.)
The function to calculate the position of the form is below.  Parameters: window - the form/toplevel to calculate the position, pos_xy - a list/tuple or enum (containing a tuple) for its position in the screen (top left 0,0; bottom right 1,1).
    def new_calc_position(self, window, pos_xy):
        # if size of desktop minus taskbar has not been calculated, calculate it
        if self.work_area is None:
            monitor_info = GetMonitorInfo(MonitorFromPoint((0, 0)))
            workspace = monitor_info.get("Work")
            self.work_area = [workspace[2], workspace[3]]  # [width, height]
            print(f"Work area: {workspace[2]}, {workspace[3]}")

            monitor_area = monitor_info.get("Monitor")
            self.taskbar_height = monitor_area[3] - workspace[3]
            print(f"Monitor area: {monitor_area[2]}, {monitor_area[3]}")
            print(f"Taskbar height: {self.taskbar_height}")

        # test that pos_xy is enum Position or list containing two floats 0.0 <= x <= 1.0
        if type(pos_xy) is Position:
            pos_xy = pos_xy.value  # convert enum to list for use
        elif isinstance(pos_xy, (list, tuple)) and len(pos_xy) == 2 and all(isinstance(el, float) and
                                                                            0.0 <= el <= 1.0 for el in pos_xy):
            pass  # is list/tuple, length of 2, and all numbers are floats 0.0 <= x <= 1.0
        else:
            raise TypeError("pos_xy must be of type Position or a list containing two numbers between 0.0 and 1.0")

        window.withdraw()  # stop window from showing
        window.update()  # force it to update its required size; would flash to screen if not withdrawn
        window.deiconify()  # allow window to show

        # calculate targeted position
        target_width = self.work_area[0] * pos_xy[0]
        target_height = self.work_area[1] * pos_xy[1]

        print("Monitor width:   " + str(self.work_area[0]))
        print("Monitor height:  " + str(self.work_area[1]))

        print("Width percent:   " + str(pos_xy[0]))
        print("Height percent:  " + str(pos_xy[1]))

        print("Width target:    " + str(target_width))
        print("Height target:   " + str(target_height))

        # calculate required width and height
        width = window.winfo_reqwidth()
        height = window.winfo_reqheight()
        print("Form width:      " + str(width))
        print("Form height:     " + str(height))

        # TODO create a lock parameter to allow a certain generation point
        x_offset = int(target_width - (width / 2))
        y_offset = int(target_height - (height / 2))
        print("Initial xoffset: " + str(x_offset))
        print("Initial yoffset: " + str(y_offset))

        # bounce window to display entirely in screen; assume will not overlap both sides in one dimension
        if x_offset < 0: # too far to left
            x_offset = 0
        elif x_offset + width > self.work_area[0]: # too far to right
            x_offset = self.work_area[0] - width

        if y_offset < 0:
            y_offset = 0
        elif y_offset + height > self.work_area[1]:
            y_offset = self.work_area[1] - self.taskbar_height - height

        print("Ending xoffset:  " + str(x_offset))
        print("Ending yoffset:  " + str(y_offset))

        print(f"{width}x{height}+{x_offset}+{y_offset}")
        return f"{width}x{height}+{x_offset}+{y_offset}"

Answer: I can't tell you why the x offset issue is happening, but I can at least confirm that you are quite right.
I had never noticed this before, but on my Windows 10 machine, an x offset of 0 and y offset of 0 will place the root window correctly at the top of the screen. But it sits about 7 pixels (in my case) to the right, leaving a small gap at the left hand side of the screen. Setting the x offset to -7 will correctly position the root window at the left side of the screen with no gap.
Note also that you can grab and move the root window to the left side of the screen with the mouse. So whether you use a negative offset, or move the window manually, it has no problem sitting correctly at the left side of the screen when forced to do so.
Other Windows applications do sit correctly at the left hand side of the screen when maximized, so this narrows it down to either a quirk of tkinter, or an interaction between Windows and tkinter.
If this behavior is the same on Linux and Mac, then it is a quirk of tkinter. If not, then it is a Windows + tkinter issue.
Most importantly, your code is not the problem.