diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index f8074755..8c29d2ec 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -41,6 +41,8 @@ using namespace Gdiplus; #define SNAPDISTANCE 10 +#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) + enum TIMER { TIMER_METER = 1, @@ -431,7 +433,11 @@ void CMeterWindow::Refresh(bool init, bool all) ScreenToWindow(); - if (all || oldZPos != m_WindowZPosition) + if (init) + { + ChangeSingleZPos(m_WindowZPosition, all); + } + else if (all || oldZPos != m_WindowZPosition) { ChangeZPos(m_WindowZPosition, all); } @@ -590,8 +596,6 @@ void CMeterWindow::MoveWindow(int x, int y) */ void CMeterWindow::ChangeZPos(ZPOSITION zPos, bool all) { -#define ZPOS_FLAGS (SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING) - HWND winPos = HWND_NOTOPMOST; m_WindowZPosition = zPos; @@ -622,12 +626,11 @@ void CMeterWindow::ChangeZPos(ZPOSITION zPos, bool all) } break; + case ZPOSITION_NORMAL: + if (all || !Rainmeter->IsNormalStayDesktop()) break; case ZPOSITION_ONDESKTOP: if (CSystem::GetShowDesktop()) { - // Set WS_EX_TOPMOST flag - SetWindowPos(m_Window, HWND_TOPMOST, 0, 0, 0, 0, ZPOS_FLAGS); - winPos = CSystem::GetHelperWindow(); if (all) @@ -669,6 +672,30 @@ void CMeterWindow::ChangeZPos(ZPOSITION zPos, bool all) SetWindowPos(m_Window, winPos, 0, 0, 0, 0, ZPOS_FLAGS); } +/* +** ChangeSingleZPos +** +** Sets the window's z-position in proper order. +** +*/ +void CMeterWindow::ChangeSingleZPos(ZPOSITION zPos, bool all) +{ + if (zPos == ZPOSITION_NORMAL && m_Rainmeter->IsNormalStayDesktop() && (!all || CSystem::GetShowDesktop())) + { + m_WindowZPosition = zPos; + + // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + SetWindowPos(m_Window, CSystem::GetBackmostTopWindow(), 0, 0, 0, 0, ZPOS_FLAGS); + + // Bring window on top of other application windows + BringWindowToTop(m_Window); + } + else + { + ChangeZPos(zPos, all); + } +} + /* ** RunBang ** @@ -3812,7 +3839,7 @@ void CMeterWindow::SetWindowHide(HIDEMODE hide) */ void CMeterWindow::SetWindowZPosition(ZPOSITION zpos) { - ChangeZPos(zpos); + ChangeSingleZPos(zpos); WriteConfig(SETTING_ALWAYSONTOP); } @@ -3950,14 +3977,22 @@ LRESULT CMeterWindow::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam) */ LRESULT CMeterWindow::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam) { - LPWINDOWPOS wp=(LPWINDOWPOS)lParam; + LPWINDOWPOS wp = (LPWINDOWPOS)lParam; if (!m_Refreshing) { - if (m_WindowZPosition == ZPOSITION_ONBOTTOM || m_WindowZPosition == ZPOSITION_ONDESKTOP) + if (m_WindowZPosition == ZPOSITION_NORMAL && m_Rainmeter->IsNormalStayDesktop() && CSystem::GetShowDesktop()) { - // do not change the z-order. This keeps the window on bottom. - wp->flags|=SWP_NOZORDER; + if (!(wp->flags & (SWP_NOOWNERZORDER | SWP_NOACTIVATE))) + { + // Set window on top of all other ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + wp->hwndInsertAfter = CSystem::GetBackmostTopWindow(); + } + } + else if (m_WindowZPosition == ZPOSITION_ONDESKTOP || m_WindowZPosition == ZPOSITION_ONBOTTOM) + { + // Do not change the z-order. This keeps the window on bottom. + wp->flags |= SWP_NOZORDER; } } diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index 15153d23..344411a0 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -188,6 +188,7 @@ public: void MoveWindow(int x, int y); void ChangeZPos(ZPOSITION zPos, bool all = false); + void ChangeSingleZPos(ZPOSITION zPos, bool all = false); void FadeWindow(int from, int to); void ResizeBlur(const WCHAR* arg, int mode); diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 98f2d66f..f0006f32 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -757,6 +757,7 @@ CRainmeter::CRainmeter() : m_NewVersion(false), m_DesktopWorkAreaChanged(false), m_DesktopWorkAreaType(false), + m_NormalStayDesktop(true), m_MenuActive(false), m_DisableRDP(false), m_DisableDragging(false), @@ -2220,6 +2221,8 @@ void CRainmeter::ReadGeneralSettings(const std::wstring& iniFile) m_DesktopWorkAreaType = 0!=parser.ReadInt(L"Rainmeter", L"DesktopWorkAreaType", 0); + m_NormalStayDesktop = 0!=parser.ReadInt(L"Rainmeter", L"NormalStayDesktop", 1); + for (int i = 0, isize = (int)m_ConfigStrings.size(); i < isize; ++i) { int active = parser.ReadInt(m_ConfigStrings[i].config.c_str(), L"Active", 0); diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index 8d5328ca..41433e97 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -143,6 +143,8 @@ public: bool GetDisableDragging() { return m_DisableDragging; } void SetDisableDragging(bool dragging); + bool IsNormalStayDesktop() { return m_NormalStayDesktop; } + void AddAboutLogInfo(int level, LPCWSTR time, LPCWSTR message); const std::list& GetAboutLogData() { return m_LogData; } @@ -242,6 +244,8 @@ private: std::map m_DesktopWorkAreas; std::vector m_OldDesktopWorkAreas; + bool m_NormalStayDesktop; + bool m_MenuActive; bool m_DisableRDP; diff --git a/Library/System.cpp b/Library/System.cpp index 5c242c19..3f5eb71a 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -102,6 +102,31 @@ void CSystem::Initialize(HINSTANCE instance) SetWindowPos(c_Window, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); SetWindowPos(c_HelperWindow, HWND_BOTTOM, 0, 0, 0, 0, ZPOS_FLAGS); + OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; + if (GetVersionEx((OSVERSIONINFO*)&osvi)) + { + if (osvi.dwMajorVersion == 5) + { + // Not checking for osvi.dwMinorVersion >= 1 because Rainmeter won't run on pre-XP + c_Platform = OSPLATFORM_XP; + } + else if (osvi.dwMajorVersion == 6) + { + if (osvi.dwMinorVersion == 0) + { + c_Platform = OSPLATFORM_VISTA; // Vista, Server 2008 + } + else + { + c_Platform = OSPLATFORM_7; // 7, Server 2008R2 + } + } + else // newer OS + { + c_Platform = OSPLATFORM_7; + } + } + c_Monitors.monitors.reserve(8); SetMultiMonitorInfo(); @@ -623,6 +648,33 @@ HWND CSystem::GetWorkerW() return WorkerW; } +/* +** GetBackmostTopWindow +** +** Returns the first window whose position is not ZPOSITION_ONDESKTOP, +** ZPOSITION_BOTTOM, or ZPOSITION_NORMAL. +** +*/ +HWND CSystem::GetBackmostTopWindow() +{ + HWND winPos = c_HelperWindow; + + // Skip all ZPOSITION_ONDESKTOP, ZPOSITION_BOTTOM, and ZPOSITION_NORMAL windows + while (winPos = ::GetNextWindow(winPos, GW_HWNDPREV)) + { + CMeterWindow* wnd = Rainmeter->GetMeterWindow(winPos); + if (!wnd || + (wnd->GetWindowZPosition() != ZPOSITION_NORMAL && + wnd->GetWindowZPosition() != ZPOSITION_ONDESKTOP && + wnd->GetWindowZPosition() != ZPOSITION_ONBOTTOM)) + { + break; + } + } + + return winPos; +} + /* ** BelongToSameProcess ** @@ -657,7 +709,9 @@ BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lParam) (Window = Rainmeter->GetMeterWindow(hwnd))) { ZPOSITION zPos = Window->GetWindowZPosition(); - if (zPos == ZPOSITION_ONDESKTOP || zPos == ZPOSITION_ONBOTTOM) + if (zPos == ZPOSITION_ONDESKTOP || + (zPos == ZPOSITION_NORMAL && Rainmeter->IsNormalStayDesktop()) || + zPos == ZPOSITION_ONBOTTOM) { if (lParam) { @@ -705,29 +759,31 @@ void CSystem::ChangeZPosInOrder() // Retrieve the Rainmeter's meter windows in Z-order EnumWindows(MyEnumWindowsProc, (LPARAM)(&windowsInZOrder)); - if (!c_ShowDesktop) + auto resetZPos = [=](ZPOSITION zpos) { // Reset ZPos in Z-order (Bottom) std::vector::const_iterator iter = windowsInZOrder.begin(), iterEnd = windowsInZOrder.end(); for ( ; iter != iterEnd; ++iter) { - if ((*iter)->GetWindowZPosition() == ZPOSITION_ONBOTTOM) + if ((*iter)->GetWindowZPosition() == zpos) { - (*iter)->ChangeZPos(ZPOSITION_ONBOTTOM); // reset + (*iter)->ChangeZPos(zpos); // reset } } + }; + + if (Rainmeter->IsNormalStayDesktop()) + { + resetZPos(ZPOSITION_NORMAL); } - // Reset ZPos in Z-order (On Desktop) - std::vector::const_iterator iter = windowsInZOrder.begin(), iterEnd = windowsInZOrder.end(); - for ( ; iter != iterEnd; ++iter) + if (!c_ShowDesktop) { - if ((*iter)->GetWindowZPosition() == ZPOSITION_ONDESKTOP) - { - (*iter)->ChangeZPos(ZPOSITION_ONDESKTOP); // reset - } + resetZPos(ZPOSITION_ONBOTTOM); } + resetZPos(ZPOSITION_ONDESKTOP); + if (logging) { Log(LOG_DEBUG, L"2: ----- AFTER -----"); @@ -839,6 +895,17 @@ bool CSystem::CheckDesktopState(HWND WorkerW) PrepareHelperWindow(WorkerW); ChangeZPosInOrder(); + + if (c_ShowDesktop) + { + KillTimer(c_Window, TIMER_SHOWDESKTOP); + SetTimer(c_Window, TIMER_SHOWDESKTOP, 100, NULL); + } + else + { + KillTimer(c_Window, TIMER_SHOWDESKTOP); + SetTimer(c_Window, TIMER_SHOWDESKTOP, INTERVAL_SHOWDESKTOP, NULL); + } } return stateChanged; @@ -955,59 +1022,6 @@ LRESULT CALLBACK CSystem::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP return DefWindowProc(hWnd, uMsg, wParam, lParam); } -/* -** GetOSPlatform -** -** Checks which OS you are running. -** -*/ -OSPLATFORM CSystem::GetOSPlatform() -{ - if (c_Platform == OSPLATFORM_UNKNOWN) - { - OSVERSIONINFOEX osvi = {sizeof(OSVERSIONINFOEX)}; - if (!GetVersionEx((OSVERSIONINFO*)&osvi) || osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) - { - c_Platform = OSPLATFORM_9X; - } - else - { - if (osvi.dwMajorVersion <= 4) // NT4 or older - { - c_Platform = OSPLATFORM_NT4; - } - else if (osvi.dwMajorVersion == 5) // 2000 / XP (x64 / Server 2003, R2) - { - if (osvi.dwMinorVersion == 0) - { - c_Platform = OSPLATFORM_2K; - } - else - { - c_Platform = OSPLATFORM_XP; - } - } - else if (osvi.dwMajorVersion == 6) // Vista (Server 2008) / 7 (Server 2008R2) - { - if (osvi.dwMinorVersion == 0) - { - c_Platform = OSPLATFORM_VISTA; - } - else - { - c_Platform = OSPLATFORM_7; - } - } - else // newer OS - { - c_Platform = OSPLATFORM_7; - } - } - } - - return c_Platform; -} - /* ** GetTickCount64 ** diff --git a/Library/System.h b/Library/System.h index 32c4f45a..68777812 100644 --- a/Library/System.h +++ b/Library/System.h @@ -25,9 +25,6 @@ enum OSPLATFORM { OSPLATFORM_UNKNOWN = 0, - OSPLATFORM_9X, - OSPLATFORM_NT4, - OSPLATFORM_2K, OSPLATFORM_XP, OSPLATFORM_VISTA, OSPLATFORM_7 @@ -59,17 +56,18 @@ public: static void Initialize(HINSTANCE instance); static void Finalize(); - static HWND GetWindow() { return c_Window; } - static const MULTIMONITOR_INFO& GetMultiMonitorInfo() { return c_Monitors; } static size_t GetMonitorCount(); static bool GetShowDesktop() { return c_ShowDesktop; } + static HWND GetWindow() { return c_Window; } + static HWND GetBackmostTopWindow(); + static HWND GetHelperWindow() { return c_HelperWindow; } static void PrepareHelperWindow(HWND WorkerW = GetWorkerW()); - static OSPLATFORM GetOSPlatform(); + static OSPLATFORM GetOSPlatform() { return c_Platform; } static ULONGLONG GetTickCount64(); static bool IsPathSeparator(WCHAR ch) { return (ch == L'\\' || ch == L'/'); }