smplayer-dev / smplayer

Free Media Player for Windows, Linux and Mac OS with YouTube support.
https://smplayer.info
GNU General Public License v2.0
668 stars 94 forks source link

SMPlayer's last window position is wrong calculated when X/Y are negative. (2022 UPDATED ISSUE) #399

Open ElektroStudios opened 2 years ago

ElektroStudios commented 2 years ago

Bug Report Context

I'll open this discussion because the original thread was closed, and the bug is still present in all the later versions of SMPlayer.

I discovered a very important factor that causes this bug. So now I think it will be very clear for the dev to find and fix the bug.

So I would like to add this factor that I discovered, and more detailed steps info to help the developer in order that he could reproduce the bug and finally try to fix it.

Describe the bug

In strange circumstances and when the X/Y (Top/Left) coordinates of the SMPlayer window position are negative, and the SMPlayer window is closed, SMPlayer doesn't calculate correctly the last window position, so the SMPlayer window position slides to the right in the screen at every next program startup.

So, this bug only seem to occur when SMPlayer window is closed having x,y negative coordinates.

To Reproduce

  1. I suspect you must use Windows 10 to reproduce this problem, due the DWM frame effects / window transparent border size differences.
  2. Run SMplayer v21.8, v21.10 or v22.2, and in case of you have maximized the SMPlayer window, put it in normal mode.
  3. Double click on a video file to open it directly in the SMPlayer window. Or drag and drop a video file to SMPlayer window.
  4. Use the next Powershell script - OR ANY OTHER METHOD THAT YOU KNOW - to set the SMPlayer window position to X/Y negative coordinate values:

This script will set the SMPlayer window position to: -1, -1, 640, 480 (X, Y, Width, Height)

Just copy the script content and run it without any modifications in the code.

Set_SMPlayer_Window_Position.ps1

Function Set-Window {
<#
.SYNOPSIS
Retrieve/Set the window size and coordinates of a process window.

.DESCRIPTION
Retrieve/Set the size (height,width) and coordinates (x,y) 
of a process window.

.PARAMETER ProcessName
Name of the process to determine the window characteristics. 
(All processes if omitted).

.PARAMETER Id
Id of the process to determine the window characteristics. 

.PARAMETER X
Set the position of the window in pixels from the left.

.PARAMETER Y
Set the position of the window in pixels from the top.

.PARAMETER Width
Set the width of the window.

.PARAMETER Height
Set the height of the window.

.PARAMETER Passthru
Returns the output object of the window.

.NOTES
Name:   Set-Window
Author: Boe Prox
Version History:
    1.0//Boe Prox - 11/24/2015 - Initial build
    1.1//JosefZ   - 19.05.2018 - Treats more process instances 
                                 of supplied process name properly
    1.2//JosefZ   - 21.02.2019 - Parameter Id

.OUTPUTS
None
System.Management.Automation.PSCustomObject
System.Object

.EXAMPLE
Get-Process powershell | Set-Window -X 20 -Y 40 -Passthru -Verbose
VERBOSE: powershell (Id=11140, Handle=132410)

Id          : 11140
ProcessName : powershell
Size        : 1134,781
TopLeft     : 20,40
BottomRight : 1154,821

Description: Set the coordinates on the window for the process PowerShell.exe

.EXAMPLE
$windowArray = Set-Window -Passthru
WARNING: cmd (1096) is minimized! Coordinates will not be accurate.

    PS C:\>$windowArray | Format-Table -AutoSize

  Id ProcessName    Size     TopLeft       BottomRight  
  -- -----------    ----     -------       -----------  
1096 cmd            199,34   -32000,-32000 -31801,-31966
4088 explorer       1280,50  0,974         1280,1024    
6880 powershell     1280,974 0,0           1280,974     

Description: Get the coordinates of all visible windows and save them into the
             $windowArray variable. Then, display them in a table view.

.EXAMPLE
Set-Window -Id $PID -Passthru | Format-Table
​‌‍
  Id ProcessName Size     TopLeft BottomRight
  -- ----------- ----     ------- -----------
7840 pwsh        1024,638 0,0     1024,638

Description: Display the coordinates of the window for the current 
             PowerShell session in a table view.

#>
[cmdletbinding(DefaultParameterSetName='Name')]
Param (
    [parameter(Mandatory=$False,
        ValueFromPipelineByPropertyName=$True, ParameterSetName='Name')]
    [string]$ProcessName='*',
    [parameter(Mandatory=$True,
        ValueFromPipeline=$False,              ParameterSetName='Id')]
    [int]$Id,
    [int]$X,
    [int]$Y,
    [int]$Width,
    [int]$Height,
    [switch]$Passthru
)
Begin {
    Try { 
        [void][Window]
    } Catch {
    Add-Type @"
        using System;
        using System.Runtime.InteropServices;
        public class Window {
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(
            IntPtr hWnd, out RECT lpRect);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public extern static bool MoveWindow( 
            IntPtr handle, int x, int y, int width, int height, bool redraw);

        [DllImport("user32.dll")] 
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool ShowWindow(
            IntPtr handle, int state);
        }
        public struct RECT
        {
        public int Left;        // x position of upper-left corner
        public int Top;         // y position of upper-left corner
        public int Right;       // x position of lower-right corner
        public int Bottom;      // y position of lower-right corner
        }
"@
    }
}
Process {
    $Rectangle = New-Object RECT
    If ( $PSBoundParameters.ContainsKey('Id') ) {
        $Processes = Get-Process -Id $Id -ErrorAction SilentlyContinue
    } else {
        $Processes = Get-Process -Name "$ProcessName" -ErrorAction SilentlyContinue
    }
    if ( $null -eq $Processes ) {
        If ( $PSBoundParameters['Passthru'] ) {
            Write-Warning 'No process match criteria specified'
        }
    } else {
        $Processes | ForEach-Object {
            $Handle = $_.MainWindowHandle
            Write-Verbose "$($_.ProcessName) `(Id=$($_.Id), Handle=$Handle`)"
            if ( $Handle -eq [System.IntPtr]::Zero ) { return }
            $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle)
            If (-NOT $PSBoundParameters.ContainsKey('X')) {
                $X = $Rectangle.Left            
            }
            If (-NOT $PSBoundParameters.ContainsKey('Y')) {
                $Y = $Rectangle.Top
            }
            If (-NOT $PSBoundParameters.ContainsKey('Width')) {
                $Width = $Rectangle.Right - $Rectangle.Left
            }
            If (-NOT $PSBoundParameters.ContainsKey('Height')) {
                $Height = $Rectangle.Bottom - $Rectangle.Top
            }
            If ( $Return ) {
                $Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True)
            }
            If ( $PSBoundParameters['Passthru'] ) {
                $Rectangle = New-Object RECT
                $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle)
                If ( $Return ) {
                    $Height      = $Rectangle.Bottom - $Rectangle.Top
                    $Width       = $Rectangle.Right  - $Rectangle.Left
                    $Size        = New-Object System.Management.Automation.Host.Size        -ArgumentList $Width, $Height
                    $TopLeft     = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Left , $Rectangle.Top
                    $BottomRight = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Right, $Rectangle.Bottom
                    If ($Rectangle.Top    -lt 0 -AND 
                        $Rectangle.Bottom -lt 0 -AND
                        $Rectangle.Left   -lt 0 -AND
                        $Rectangle.Right  -lt 0) {
                        Write-Warning "$($_.ProcessName) `($($_.Id)`) is minimized! Coordinates will not be accurate."
                    }
                    $Object = [PSCustomObject]@{
                        Id          = $_.Id
                        ProcessName = $_.ProcessName
                        Size        = $Size
                        TopLeft     = $TopLeft
                        BottomRight = $BottomRight
                    }
                    $Object
                }
            }
        }
    }
}
}

$smplayer = Get-Process smplayer
$smplayer | Set-Window -X -1 -Y -1 -WIDTH 640 -HEIGHT 480 -Passthru -Verbose

( original source: https://stackoverflow.com/a/61242577/1248295 )

  1. Now just close the SMPlayer program window. And make double click on a video file to open SMplayer program again, and you will see that the window position slides to the right in the screen.

  2. At this point you can repeat how many times you wish the step number 5 to continue watching that the SMplayer window position will continue moving more to the right every time that you repeat the step 5.

Step Notes

Please note that, for some strange reason that I'm not aware of, I found that the issue could NOT be reproduced if:

So just follow the same things that I exactly described in the steps, which are the same exactly things that I do in the video proof that I uploaded to Youtube.

Screenshots

You can find screenshots in the original thread.

Video Proof

In this video I reproduce all the steps.

Your Enviroment

Other things

If helpful, let me say smplayer-portable-21.1.0.0-x64.7z and prior versions does not have this bug. Starting with release versions 21.8.0, and then 21.10.0 and 22.2.0 all has this problem present.

This could mean that after version 21.1.0 the dev. changed something in the algorithm used to remember / calculate last window position?.

PS: I referred only to release builds. I didn't tried to find and test experimental or nightly builds.

smplayer-dev commented 2 years ago

Do you have the same problem with the 32-bit version? https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-22.2.0-win32-qt5.6.exe https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-portable-22.2.0.0-win32-qt5.6.7z

ElektroStudios commented 2 years ago

Do you have the same problem with the 32-bit version? https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-22.2.0-win32-qt5.6.exe https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-portable-22.2.0.0-win32-qt5.6.7z

Thanks for support.

I tried the x86 portable now. The window position issue is NOT present in that build.

smplayer-dev commented 2 years ago

Then I guess the problem is caused by Qt 5.15.2, which is used by the 64 bit version.

ElektroStudios commented 2 years ago

Then I guess the problem is caused by Qt 5.15.2, which is used by the 64 bit version.

Just to summarize:

SMplayer 21.1.0 x64 (Qt 5.6.0) and 22.2.0 x86 (Qt 5.6.3) does NOT produce this window position problem.

Ok, so I tried replacing the Qt lib files from SMPlayer 21.1.0 x64 (Qt 5.6.0) to those Qt 5.15.2 files of SMPlayer 21.8.0 x64, SMPlayer 21.10.0 x64 and SMPlayer 22.2.0 x64, but it did not work on my side. It says there are a lot of missing entry points. Also the Qt5Svg.dll file is missing in SMplayer 21.1.0 x64.

Would you consider to downgrade Qt version of next SMplayer x64 releases to solve this issue?. Or maybe could you provide me a workaround for this issue while we hope that a future updated Qt version will not produce this window position issue?. (I ask this without knowing which is the latest available Qt version)

At least now and thanks to you I know that I can use the latest x86 version of SMPlayer without worries about this issue. But it is worth it to use SMPlayer x86 under a x64 OS?, I ask it from my ignorance.

smplayer-dev commented 2 years ago

I've just uploaded 64 bit packages built with Qt 5.6: https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-22.2.0-x64-qt5.6-unsigned.exe https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-portable-22.2.0.0-x64-qt5.6.7z

Please let me know if they work for you.

ElektroStudios commented 2 years ago

I've just uploaded 64 bit packages built with Qt 5.6: https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-22.2.0-x64-qt5.6-unsigned.exe https://github.com/smplayer-dev/smplayer/releases/download/v22.2.0/smplayer-portable-22.2.0.0-x64-qt5.6.7z

Please let me know if they work for you.

Thanks a lot, it works!!!. However, with this v22.2.0 I'm having the other big issue of the green color window.

jimmy-1000 commented 2 years ago

I tested it and I have not problem (Windows 7). I think only happens in Windows 10.