https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bc6d5914288283606c339534c65ceb81af663e5

commit 5bc6d5914288283606c339534c65ceb81af663e5
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Fri Feb 7 21:33:19 2025 +0100
Commit:     GitHub <nore...@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);

Reply via email to