https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bc6d5914288283606c33…
commit 5bc6d5914288283606c339534c65ceb81af663e5
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Fri Feb 7 21:33:19 2025 +0100
Commit: GitHub <noreply(a)github.com>
CommitDate: Fri Feb 7 21:33:19 2025 +0100
[RAPPS] Refresh item info after installer completes (#7697)
- Refresh the details view of the item that was just installed.
- Hint update of uninstallers list is needed.
- Restore focus correctly after installer process finishes.
CORE-17677
---
base/applications/rapps/appinfo.cpp | 12 +++++++--
base/applications/rapps/appview.cpp | 45 ++++++++++++++++++++++++-------
base/applications/rapps/gui.cpp | 41 +++++++++++++++++++++-------
base/applications/rapps/include/appinfo.h | 9 +++++++
base/applications/rapps/include/appview.h | 7 ++++-
base/applications/rapps/include/gui.h | 3 +++
base/applications/rapps/include/rapps.h | 2 ++
base/applications/rapps/loaddlg.cpp | 13 ++++++---
base/applications/rapps/misc.cpp | 2 ++
base/applications/rapps/unattended.cpp | 4 +--
10 files changed, 109 insertions(+), 29 deletions(-)
diff --git a/base/applications/rapps/appinfo.cpp b/base/applications/rapps/appinfo.cpp
index 1970b9459d9..5442380fbad 100644
--- a/base/applications/rapps/appinfo.cpp
+++ b/base/applications/rapps/appinfo.cpp
@@ -10,6 +10,14 @@
#include "rapps.h"
#include "appview.h"
+static inline AppsCategories
+ClampAvailableCategory(AppsCategories Category)
+{
+ if (Category <= ENUM_LASTCATEGORY)
+ return Category;
+ return ENUM_CAT_OTHER; // Treat future categories we don't know as Other
+}
+
CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category)
: szIdentifier(Identifier), iCategory(Category)
{
@@ -24,7 +32,7 @@ CAvailableApplicationInfo::CAvailableApplicationInfo(
const CStringW &PkgName,
AppsCategories Category,
const CPathW &BasePath)
- : CAppInfo(PkgName, Category), m_Parser(Parser), m_ScrnshotRetrieved(false),
m_LanguagesLoaded(false)
+ : CAppInfo(PkgName, ClampAvailableCategory(Category)), m_Parser(Parser),
m_ScrnshotRetrieved(false), m_LanguagesLoaded(false)
{
m_Parser->GetString(L"Name", szDisplayName);
m_Parser->GetString(L"Version", szDisplayVersion);
@@ -588,7 +596,7 @@ CInstalledApplicationInfo::GetInstallerType() const
BOOL
CInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags)
{
- if (GetInstallerType() == INSTALLER_GENERATE)
+ if (GetInstallerType() == INSTALLER_GENERATE && (Flags &
UCF_SAMEPROCESS))
{
return UninstallGenerated(*this, Flags);
}
diff --git a/base/applications/rapps/appview.cpp b/base/applications/rapps/appview.cpp
index c0f18107c1e..248050ebb92 100644
--- a/base/applications/rapps/appview.cpp
+++ b/base/applications/rapps/appview.cpp
@@ -955,19 +955,22 @@ CAppInfoDisplay::Create(HWND hwndParent)
}
VOID
-CAppInfoDisplay::ShowAppInfo(CAppInfo *Info)
+CAppInfoDisplay::ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText)
{
- CStringW ScrnshotLocation;
- if (Info->RetrieveScreenshot(ScrnshotLocation))
+ if (!OnlyUpdateText)
{
- ScrnshotPrev->DisplayImage(ScrnshotLocation);
- }
- else
- {
- ScrnshotPrev->DisplayEmpty();
+ CStringW ScrnshotLocation;
+ if (Info.RetrieveScreenshot(ScrnshotLocation))
+ {
+ ScrnshotPrev->DisplayImage(ScrnshotLocation);
+ }
+ else
+ {
+ ScrnshotPrev->DisplayEmpty();
+ }
}
ResizeChildren();
- Info->ShowAppInfo(RichEdit);
+ Info.ShowAppInfo(RichEdit);
}
void
@@ -1805,6 +1808,22 @@ CApplicationView::SetRedraw(BOOL bRedraw)
m_ListView->SetRedraw(bRedraw);
}
+void
+CApplicationView::RefreshAvailableItem(PCWSTR PackageName)
+{
+ if (ApplicationViewType != AppViewTypeAvailableApps || !PackageName)
+ return;
+ CAppInfo *pApp;
+ for (UINT i = 0; (pApp = (CAppInfo*)m_ListView->GetItemData(i)) != NULL; ++i)
+ {
+ if (pApp->szIdentifier.CompareNoCase(PackageName) == 0)
+ {
+ RefreshDetailsPane(*pApp, true);
+ break;
+ }
+ }
+}
+
void
CApplicationView::SetFocusOnSearchBar()
{
@@ -2134,6 +2153,12 @@ CApplicationView::RestoreListSelection(const RESTORELISTSELECTION
&Restore)
}
}
+VOID
+CApplicationView::RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText)
+{
+ m_AppsInfo->ShowAppInfo(Info, OnlyUpdateText);
+}
+
// this function is called when a item of listview get focus.
// CallbackParam is the param passed to listview when adding the item (the one getting
focus now).
VOID
@@ -2142,7 +2167,7 @@ CApplicationView::ItemGetFocus(LPVOID CallbackParam)
if (CallbackParam)
{
CAppInfo *Info = static_cast<CAppInfo *>(CallbackParam);
- m_AppsInfo->ShowAppInfo(Info);
+ RefreshDetailsPane(*Info);
if (ApplicationViewType == AppViewTypeInstalledApps)
{
diff --git a/base/applications/rapps/gui.cpp b/base/applications/rapps/gui.cpp
index 6f2e1a1d3d8..8470ba092d1 100644
--- a/base/applications/rapps/gui.cpp
+++ b/base/applications/rapps/gui.cpp
@@ -81,6 +81,8 @@ CSideTreeView::~CSideTreeView()
// **** CSideTreeView ****
// **** CMainWindow ****
+HWND CMainWindow::m_hLastFocus = NULL;
+bool CMainWindow::m_PendingInstalledViewRefresh = false;
CMainWindow::CMainWindow(CAppDB *db, BOOL bAppwiz) : m_ClientPanel(NULL), m_Db(db),
m_bAppwizMode(bAppwiz), SelectedEnumType(ENUM_ALL_INSTALLED)
{
@@ -343,10 +345,32 @@ CMainWindow::ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM
wParam, LPARAM lPa
SendMessage(WM_CLOSE, 0, 0);
break;
+ case WM_NOTIFY_INSTALLERFINISHED:
+ m_PendingInstalledViewRefresh = true; // Something just installed, our
uninstall list is probably outdated
+ m_ApplicationView->RefreshAvailableItem((PCWSTR)lParam);
+ break;
+
case DM_REPOSITION:
EmulateDialogReposition(hwnd); // We are not a real dialog, we need help from
a real one
break;
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE)
+ m_hLastFocus = ::GetFocus();
+ break;
+
+ case WM_SETFOCUS:
+ if (m_hLastFocus)
+ ::SetFocus(m_hLastFocus);
+ break;
+
+ case WM_NEXTDLGCTL:
+ if (!LOWORD(lParam))
+ HandleTabOrder(wParam ? -1 : 1);
+ else if (wParam)
+ ::SetFocus((HWND)wParam);
+ break;
+
case WM_COMMAND:
OnCommand(wParam, lParam);
break;
@@ -678,6 +702,12 @@ CMainWindow::UpdateApplicationsList(AppsCategories EnumType, BOOL
bReload, BOOL
if (bCheckAvailable)
CheckAvailable();
+ if (m_PendingInstalledViewRefresh && IsInstalledEnum(EnumType) &&
!IsInstalledEnum(SelectedEnumType))
+ {
+ m_PendingInstalledViewRefresh = FALSE;
+ bReload = TRUE; // Reload because we are switching from Available to Installed
after something installed
+ }
+
BOOL TryRestoreSelection = SelectedEnumType == EnumType;
if (SelectedEnumType != EnumType)
SelectedEnumType = EnumType;
@@ -812,16 +842,7 @@ CMainWindow::ItemCheckStateChanged(BOOL bChecked, LPVOID
CallbackParam)
BOOL
CMainWindow::InstallApplication(CAppInfo *Info)
{
- if (Info)
- {
- if (DownloadApplication(Info))
- {
- //FIXME: Delay UpdateApplicationsList(SelectedEnumType); until install
completes
- return TRUE;
- }
- }
-
- return FALSE;
+ return Info && DownloadApplication(Info);
}
BOOL
diff --git a/base/applications/rapps/include/appinfo.h
b/base/applications/rapps/include/appinfo.h
index 32cfc20b3dd..961ad0711bd 100644
--- a/base/applications/rapps/include/appinfo.h
+++ b/base/applications/rapps/include/appinfo.h
@@ -41,6 +41,7 @@ enum AppsCategories
ENUM_CAT_THEMES,
ENUM_CAT_OTHER,
ENUM_CAT_SELECTED,
+ ENUM_LASTCATEGORY = ENUM_CAT_SELECTED - 1,
ENUM_ALL_INSTALLED = 30,
ENUM_INSTALLED_APPLICATIONS,
ENUM_UPDATES,
@@ -54,6 +55,12 @@ enum AppsCategories
inline BOOL
IsAvailableEnum(INT x)
{
+ C_ASSERT(ENUM_CAT_AUDIO == 1 && ENUM_CAT_THEMES == 15 &&
ENUM_CAT_OTHER == 16);
+ C_ASSERT(ENUM_LASTCATEGORY >= ENUM_CAT_OTHER);
+ C_ASSERT(ENUM_LASTCATEGORY < ENUM_CAT_SELECTED);
+ C_ASSERT(ENUM_LASTCATEGORY < ENUM_INSTALLED_MIN);
+ C_ASSERT(ENUM_CAT_SELECTED < ENUM_INSTALLED_MIN);
+
return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX);
}
@@ -68,7 +75,9 @@ enum UninstallCommandFlags
UCF_NONE = 0x00,
UCF_MODIFY = 0x01,
UCF_SILENT = 0x02,
+ UCF_SAMEPROCESS = 0x04,
};
+DEFINE_ENUM_FLAG_OPERATORS(UninstallCommandFlags);
enum InstallerType
{
diff --git a/base/applications/rapps/include/appview.h
b/base/applications/rapps/include/appview.h
index d457d45c799..169d0b23151 100644
--- a/base/applications/rapps/include/appview.h
+++ b/base/applications/rapps/include/appview.h
@@ -175,7 +175,7 @@ class CAppInfoDisplay : public
CUiWindow<CWindowImpl<CAppInfoDisplay>>
Create(HWND hwndParent);
VOID
- ShowAppInfo(CAppInfo *Info);
+ ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText = false);
void
SetWelcomeText(bool bAppwiz);
VOID
@@ -388,6 +388,8 @@ class CApplicationView : public
CUiWindow<CWindowImpl<CApplicationView>>
void
SetRedraw(BOOL bRedraw);
void
+ RefreshAvailableItem(PCWSTR PackageName);
+ void
SetFocusOnSearchBar();
BOOL
SetDisplayAppType(APPLICATION_VIEW_TYPE AppType);
@@ -415,6 +417,9 @@ class CApplicationView : public
CUiWindow<CWindowImpl<CApplicationView>>
VOID
RestoreListSelection(const RESTORELISTSELECTION &Restore);
+ VOID
+ RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText = false);
+
// this function is called when a item of listview get focus.
// CallbackParam is the param passed to listview when adding the item (the one
getting focus now).
VOID
diff --git a/base/applications/rapps/include/gui.h
b/base/applications/rapps/include/gui.h
index 36ff852dde3..fbe36a7fea1 100644
--- a/base/applications/rapps/include/gui.h
+++ b/base/applications/rapps/include/gui.h
@@ -65,6 +65,9 @@ class CMainWindow : public CWindowImpl<CMainWindow, CWindow,
CFrameWinTraits>
AppsCategories SelectedEnumType;
public:
+ static HWND m_hLastFocus;
+ static bool m_PendingInstalledViewRefresh;
+
explicit CMainWindow(CAppDB *db, BOOL bAppwiz = FALSE);
~CMainWindow();
diff --git a/base/applications/rapps/include/rapps.h
b/base/applications/rapps/include/rapps.h
index c03a06d092d..f42c5919c2e 100644
--- a/base/applications/rapps/include/rapps.h
+++ b/base/applications/rapps/include/rapps.h
@@ -14,8 +14,10 @@
#include "configparser.h"
extern LONG g_Busy;
+extern bool g_PendingInstalledViewRefresh;
#define WM_NOTIFY_OPERATIONCOMPLETED (WM_APP + 0)
+#define WM_NOTIFY_INSTALLERFINISHED (WM_APP + 1)
#define MAINWINDOWCLASSNAME L"ROSAPPMGR2"
#define MAINWINDOWMUTEX szWindowClass
diff --git a/base/applications/rapps/loaddlg.cpp b/base/applications/rapps/loaddlg.cpp
index c863a5e2165..21b7b88d1fc 100644
--- a/base/applications/rapps/loaddlg.cpp
+++ b/base/applications/rapps/loaddlg.cpp
@@ -142,8 +142,7 @@ struct DownloadInfo
AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes);
szName = AppInfo.szDisplayName;
IType = AppInfo.GetInstallerType();
- if (IType == INSTALLER_GENERATE)
- szPackageName = AppInfo.szIdentifier;
+ szPackageName = AppInfo.szIdentifier;
CConfigParser *cfg = static_cast<const
CAvailableApplicationInfo&>(AppInfo).GetConfigParser();
if (cfg)
@@ -452,6 +451,8 @@ ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError)
return FALSE;
}
+ if (hWndOwner && !IsWindowVisible(hWndOwner))
+ hWndOwner = NULL;
MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR);
return TRUE;
}
@@ -1090,8 +1091,12 @@ run:
SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_INSTALLING, 0);
// TODO: issue an install operation separately so that the apps could be
downloaded in the background
- WaitForSingleObject(shExInfo.hProcess, INFINITE);
- CloseHandle(shExInfo.hProcess);
+ if (shExInfo.hProcess)
+ {
+ WaitForSingleObject(shExInfo.hProcess, INFINITE);
+ CloseHandle(shExInfo.hProcess);
+ SendMessageW(hMainWnd, WM_NOTIFY_INSTALLERFINISHED, 0,
(LPARAM)(PCWSTR)Info.szPackageName);
+ }
}
else
{
diff --git a/base/applications/rapps/misc.cpp b/base/applications/rapps/misc.cpp
index c5fe6f0c4bc..baafe5309fd 100644
--- a/base/applications/rapps/misc.cpp
+++ b/base/applications/rapps/misc.cpp
@@ -160,6 +160,8 @@ StartProcess(const CStringW &Path, BOOL Wait)
{
EnableWindow(hMainWnd, TRUE);
SetForegroundWindow(hMainWnd);
+ // We got the real activation message during MsgWaitForMultipleObjects while
+ // we were disabled, we need to set the focus again now.
SetFocus(hMainWnd);
}
diff --git a/base/applications/rapps/unattended.cpp
b/base/applications/rapps/unattended.cpp
index 4967f259de3..06db5f0aba6 100644
--- a/base/applications/rapps/unattended.cpp
+++ b/base/applications/rapps/unattended.cpp
@@ -191,7 +191,7 @@ HandleUninstallCommand(CAppDB &db, UINT argcLeft, LPWSTR
*argvLeft)
if (pInfo)
{
- retval = pInfo->UninstallApplication(silent ? UCF_SILENT : UCF_NONE);
+ retval = pInfo->UninstallApplication((silent ? UCF_SILENT : UCF_NONE) |
UCF_SAMEPROCESS);
}
delete pDelete;
return retval;
@@ -368,7 +368,7 @@ ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int
nCmdShow)
if (hWindow)
{
/* Activate the window in the other instance */
- ShowWindow(hWindow, SW_SHOW);
+ ShowWindow(hWindow, SW_SHOWNA);
SwitchToThisWindow(hWindow, TRUE);
if (bAppwizMode)
PostMessage(hWindow, WM_COMMAND, ID_ACTIVATE_APPWIZ, 0);