Skip to content

Commit b8ee65f

Browse files
committed
Get PD minimally working under Wine (again)
With this commit, PhotoDemon should once again start correctly under Wine. A lot of things may not work well (or at all!), but at least the app loads and provides minimal functionality again. (Turns out the biggest problem was setting layered window bits on the main window, which previously improved compositing performance of PD's toolbars under Vista+ but breaks completely under Wine. Because PD no longer provides semi-transparent panel support, this line could be removed entirely.) To further improve Wine compatibility, PD now sets a bunch of internal flags to "XP compatibility mode" when Wine is detected as the "OS". This fixes a number of rendering issues that have nothing to do with XP per se but which produce noticeably better results under Wine. That said, some UI issues, like never receiving WM_MOUSELEAVE events so all UI bits look hovered, are Wine-specific issues that I can't easily address at present. I'll keep poking around to see if I can find fixes for these, but no promises on a timeline...
1 parent c4beae5 commit b8ee65f

File tree

5 files changed

+70
-16
lines changed

5 files changed

+70
-16
lines changed

Classes/pdDisplays.cls

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,7 @@ Private Sub FillDetailedDisplayInfo(ByVal displayIndex As Long)
448448
' to Vista or later.
449449

450450
'If we have not yet retrieved an EDID value for this monitor, attempt to do so now
451-
'And OS.IsVistaOrLater
452-
If (Not listOfDisplays(displayIndex).HasEDID) Then
451+
If (Not listOfDisplays(displayIndex).HasEDID) And OS.IsVistaOrLater() Then
453452

454453
'Retrieve and cache the device ID
455454
Dim devID As String

Classes/pdWindowManager.cls

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -711,12 +711,10 @@ Friend Sub RegisterMainForm(ByRef parentForm As Form)
711711

712712
If PDMain.IsProgramRunning() Then
713713

714-
'Apply any unique styles to the parent window
714+
'Apply any unique styles to the parent window. (PD uses complex nested windows for toolbars,
715+
' and setting the WS_EX_COMPOSITED bit reduces flickering on older versions of Windows.)
715716
Dim newWinStyle As Long
716717
newWinStyle = GetWindowLong(parentForm.hWnd, GWL_EXSTYLE) Or WS_EX_COMPOSITED
717-
718-
'On Vista+, layered windows consume a bit more resources but they play very nicely with DWM
719-
If OS.IsVistaOrLater Then newWinStyle = newWinStyle Or WS_EX_LAYERED
720718
SetWindowLong m_MainWindowHWnd, GWL_EXSTYLE, newWinStyle
721719

722720
'Enforce minimum size handling. (Note that this will subclass the main window, which allows us to handle

Forms/MainWindow.frm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,8 +2138,8 @@ Private Sub Form_Load()
21382138
PDDebug.LogAction "Program initialization complete. Second baseline memory measurement:"
21392139
PDDebug.LogAction vbNullString, PDM_Mem_Report
21402140

2141-
'Before setting focus to the main form, active a focus tracker; it catches some cases that VB's
2142-
' built-in focus events do not.
2141+
'Before setting focus to the main form, activate a focus tracker.
2142+
' (PD uses this class to catch some focus cases that VB's built-in focus events do not.)
21432143
Set m_FocusDetector = New pdFocusDetector
21442144
m_FocusDetector.StartFocusTracking FormMain.hWnd
21452145

Modules/OS.bas

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,11 @@ End Type
276276
Private Declare Function CloseHandle Lib "kernel32" (ByVal Handle As Long) As Long
277277
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
278278
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
279-
Private Declare Function GetKeyState Lib "user32" (ByVal vKey As Long) As Integer
280279
Private Declare Function GetCommandLineW Lib "kernel32" () As Long
280+
Private Declare Function GetKeyState Lib "user32" (ByVal vKey As Long) As Integer
281281
Private Declare Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As Long, ByVal ptrToFileNameBuffer As Long, ByVal nSize As Long) As Long
282+
Private Declare Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As Long) As Long
283+
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
282284
Private Declare Sub GetNativeSystemInfo Lib "kernel32" (ByRef lpSystemInfo As OS_SystemInfo)
283285
Private Declare Sub GetSystemTimeAsFileTime Lib "kernel32" (ByRef dstTime As Currency)
284286
Private Declare Function GetTempPathW Lib "kernel32" (ByVal nBufferLength As Long, ByVal lpStrBuffer As Long) As Long
@@ -347,6 +349,9 @@ End Enum
347349

348350
Private m_ThemingAvailable As PD_ThemingAvailable
349351

352+
'Used to detect if we're running under Wine or not. (Added in 2024-05 to try and solve Wine-specific problems.)
353+
Private m_InsideWine As Boolean, m_LookedForWineAlready As Boolean
354+
350355
'Function for returning this application's current memory usage. Note that this function will return warped
351356
' values inside the IDE (because the reported total is for *all* of VB6, including the IDE itself).
352357
Public Function AppMemoryUsage(Optional returnPeakValue As Boolean = False) As Long
@@ -635,7 +640,7 @@ End Function
635640
'PD will attempt to forcibly enable DEP on Win 7+ (when compiled, obviously).
636641
' This may decrease issues with garbage 3rd-party virus and malware scanners.
637642
Public Function EnableProcessDEP() As Boolean
638-
If (OS.IsWin7OrLater And OS.IsProgramCompiled) Then
643+
If (OS.IsWin7OrLater And OS.IsProgramCompiled And (Not OS.IsWinActuallyWine)) Then
639644
Const PROCESS_DEP_ENABLE As Long = &H1&
640645
SetProcessDEPPolicy PROCESS_DEP_ENABLE
641646
End If
@@ -757,36 +762,88 @@ End Function
757762
'Check for a version >= the specified version.
758763
Public Function IsVistaOrLater() As Boolean
759764
If (Not m_VersionInfoCached) Then CacheOSVersion
760-
IsVistaOrLater = (m_OSVI.dwMajorVersion >= 6)
765+
If OS.IsWinActuallyWine Then
766+
IsVistaOrLater = False
767+
Else
768+
IsVistaOrLater = (m_OSVI.dwMajorVersion >= 6)
769+
End If
761770
End Function
762771

763772
Public Function IsWin7OrLater() As Boolean
764773
If (Not m_VersionInfoCached) Then CacheOSVersion
765-
IsWin7OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 1))
774+
If OS.IsWinActuallyWine Then
775+
IsWin7OrLater = False
776+
Else
777+
IsWin7OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 1))
778+
End If
766779
End Function
767780

768781
Public Function IsWin8OrLater() As Boolean
769782
If (Not m_VersionInfoCached) Then CacheOSVersion
770-
IsWin8OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 2))
783+
If OS.IsWinActuallyWine Then
784+
IsWin8OrLater = False
785+
Else
786+
IsWin8OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 2))
787+
End If
771788
End Function
772789

773790
Public Function IsWin81OrLater() As Boolean
774791
If (Not m_VersionInfoCached) Then CacheOSVersion
775-
IsWin81OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 3))
792+
If OS.IsWinActuallyWine Then
793+
IsWin81OrLater = False
794+
Else
795+
IsWin81OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 3))
796+
End If
776797
End Function
777798

778799
' (NOTE: the Win-10 check requires a manifest, so don't rely on it in the IDE. Also, MS doesn't guarantee that this
779800
' check will remain valid forever, though it does work as of Windows 10-1703.)
780801
Public Function IsWin10OrLater() As Boolean
781802
If (Not m_VersionInfoCached) Then CacheOSVersion
782-
IsWin10OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 4))
803+
If OS.IsWinActuallyWine Then
804+
IsWin10OrLater = False
805+
Else
806+
IsWin10OrLater = (m_OSVI.dwMajorVersion > 6) Or ((m_OSVI.dwMajorVersion = 6) And (m_OSVI.dwMinorVersion >= 4))
807+
End If
783808
End Function
784809

785810
Public Function GetWin10Build() As Long
786811
If (Not m_VersionInfoCached) Then CacheOSVersion
787812
GetWin10Build = m_OSVI.dwBuildNumber
788813
End Function
789814

815+
'Are we running inside Wine? Thanks to StackOverflow for the implementation idea:
816+
' https://stackoverflow.com/questions/7372388/determine-whether-a-program-is-running-under-wine-at-runtime
817+
'
818+
'PD doesn't officially support Wine, but I've found that lying to PD and claiming that Wine is actually XP
819+
' produces a reasonably usable version of the app.
820+
Public Function IsWinActuallyWine() As Boolean
821+
822+
'Cache check once, on first call
823+
If (Not m_LookedForWineAlready) Then
824+
825+
m_LookedForWineAlready = True
826+
827+
Dim modName As String
828+
modName = "ntdll.dll"
829+
830+
Dim hMod As Long
831+
hMod = GetModuleHandleW(StrPtr(modName))
832+
If (hMod <> 0) Then
833+
Dim hProc As Long
834+
hProc = GetProcAddress(hMod, "wine_get_version")
835+
m_InsideWine = (hProc <> 0)
836+
Else
837+
PDDebug.LogAction "WARNING: couldn't find ntdll?"
838+
m_InsideWine = False
839+
End If
840+
841+
End If
842+
843+
IsWinActuallyWine = m_InsideWine
844+
845+
End Function
846+
790847
'Return the number of logical cores on this system
791848
Public Function LogicalCoreCount() As Long
792849
Dim tmpSysInfo As OS_SystemInfo

PhotoDemon.vbp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ Description="PhotoDemon Photo Editor"
527527
CompatibleMode="0"
528528
MajorVer=2024
529529
MinorVer=4
530-
RevisionVer=26
530+
RevisionVer=40
531531
AutoIncrementVer=1
532532
ServerSupportFiles=0
533533
VersionComments="Copyright 2000-2024 Tanner Helland - photodemon.org"

0 commit comments

Comments
 (0)