File indexing completed on 2025-01-05 03:53:17

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2019-04-02
0007  * Description : plugin to export image as wallpaper - Windows version.
0008  *
0009  * SPDX-FileCopyrightText: 2019      by Igor Antropov <antropovi at yahoo dot com>
0010  * SPDX-FileCopyrightText: 2019-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "wallpaperplugin.h"
0017 
0018 // Qt includes
0019 
0020 #include <QMessageBox>
0021 #include <QProcess>
0022 #include <QDir>
0023 
0024 // KDE includes
0025 
0026 #include <klocalizedstring.h>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 
0032 // Windows includes
0033 
0034 #ifdef Q_OS_WIN
0035 #   include <windows.h>
0036 #   include <wininet.h>
0037 #   include <shlobj.h>
0038 #endif
0039 
0040 namespace DigikamGenericWallpaperPlugin
0041 {
0042 
0043 bool s_checkErrorCode(HRESULT status, const QString& path, const QString& context)
0044 {
0045     if (FAILED(status))
0046     {
0047         // Code to catch error string from error code with Windows API.
0048 
0049         LPWSTR bufPtr        = nullptr;
0050         DWORD werr           = GetLastError();
0051         FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
0052                        FORMAT_MESSAGE_FROM_SYSTEM     |
0053                        FORMAT_MESSAGE_IGNORE_INSERTS,
0054                        nullptr,
0055                         werr,
0056                        0,
0057                        (LPWSTR)&bufPtr,
0058                        0,
0059                        nullptr);
0060 
0061         // cppcheck-suppress knownConditionTrueFalse
0062         QString errStr = (bufPtr) ? QString::fromUtf16((const ushort*)bufPtr).trimmed()
0063                                   : i18n("Unknown Error %1", werr);
0064         LocalFree(bufPtr);
0065 
0066         QMessageBox::warning(nullptr,
0067                              i18nc("@title:window",
0068                                    "Error While to Set Image as Wallpaper"),
0069                              i18n("Cannot change wallpaper image from current desktop with\n"
0070                                   "%1\n\nContext: %2\n\nError: %3",
0071                                   path,
0072                                   context,
0073                                   errStr));
0074 
0075         return false;
0076     }
0077 
0078     return true;
0079 }
0080 
0081 bool WallpaperPlugin::setWallpaper(const QString& path, int layout) const
0082 {
0083     // NOTE: IDesktopWallpaper is only defined with Windows >= 8.
0084     //       To be compatible with Windows 7, we needs to use IActiveDesktop instead.
0085 
0086     CoInitializeEx(0, COINIT_APARTMENTTHREADED);
0087 
0088     IActiveDesktop* iADesktop = nullptr;
0089     HRESULT status            = CoCreateInstance(CLSID_ActiveDesktop,
0090                                                  nullptr,
0091                                                  CLSCTX_INPROC_SERVER,
0092                                                  IID_IActiveDesktop,
0093                                                  (void**)&iADesktop);
0094 
0095     if (!s_checkErrorCode(status, path, i18n("Cannot create desktop context.")))
0096     {
0097         CoUninitialize();
0098 
0099         return false;
0100     }
0101 
0102     WALLPAPEROPT wOption;
0103     ZeroMemory(&wOption, sizeof(WALLPAPEROPT));
0104     wOption.dwSize            = sizeof(WALLPAPEROPT);
0105 
0106     switch (layout)
0107     {
0108         case Mosaic:
0109         {
0110             wOption.dwStyle = WPSTYLE_TILE;
0111             break;
0112         }
0113 
0114         case Centered:
0115         {
0116             wOption.dwStyle = WPSTYLE_CENTER;
0117             break;
0118         }
0119 
0120         default:    // *Adjusted*
0121         {
0122             wOption.dwStyle = WPSTYLE_STRETCH;
0123             break;
0124         }
0125     }
0126 
0127     status = iADesktop->SetWallpaper((PCWSTR)QDir::toNativeSeparators(path).utf16(), 0);
0128 
0129     if (!s_checkErrorCode(status, path, i18n("Cannot set wall paper image path.")))
0130     {
0131         iADesktop->Release();
0132         CoUninitialize();
0133 
0134         return false;
0135     }
0136 
0137     status = iADesktop->SetWallpaperOptions(&wOption, 0);
0138 
0139     if (!s_checkErrorCode(status, path, i18n("Cannot set wallpaper properties.")))
0140     {
0141         iADesktop->Release();
0142         CoUninitialize();
0143 
0144         return false;
0145     }
0146 
0147     status = iADesktop->ApplyChanges(AD_APPLY_ALL);
0148 
0149     if (!s_checkErrorCode(status, path, i18n("Cannot apply changes to desktop wallpaper.")))
0150     {
0151         iADesktop->Release();
0152         CoUninitialize();
0153 
0154         return false;
0155     }
0156 
0157     iADesktop->Release();
0158     CoUninitialize();
0159 
0160     return true;
0161 }
0162 
0163 } // namespace DigikamGenericWallpaperPlugin