diff options
-rw-r--r-- | backends/platform/sdl/win32/win32.cpp | 1 | ||||
-rw-r--r-- | backends/taskbar/win32/win32-taskbar.cpp | 144 | ||||
-rw-r--r-- | backends/taskbar/win32/win32-taskbar.h | 19 | ||||
-rw-r--r-- | common/taskbar.h | 16 |
4 files changed, 164 insertions, 16 deletions
diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp index 0fd2fbbd1d..bb254786d5 100644 --- a/backends/platform/sdl/win32/win32.cpp +++ b/backends/platform/sdl/win32/win32.cpp @@ -87,6 +87,7 @@ void OSystem_Win32::init() { // Initialize task bar manager _taskbarManager = new Win32TaskbarManager(); + ((Win32TaskbarManager *)_taskbarManager)->init(); // Invoke parent implementation of this method OSystem_SDL::init(); diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp index 7f76791dfa..1ddbde10bc 100644 --- a/backends/taskbar/win32/win32-taskbar.cpp +++ b/backends/taskbar/win32/win32-taskbar.cpp @@ -25,30 +25,160 @@ * https://code.google.com/p/dukto/ */ -#include "common/scummsys.h" +#ifdef WIN32 -#include "common/textconsole.h" +// Needed for taskbar functions +#include <SDKDDKVer.h> +#include <shlobj.h> #include "backends/taskbar/win32/win32-taskbar.h" +#include "common/config-manager.h" +#include "common/textconsole.h" + +#include <SDL_syswm.h> + +// System.Title property key, values taken from http://msdn.microsoft.com/en-us/library/bb787584.aspx +const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 }; + Win32TaskbarManager::Win32TaskbarManager() { + _taskbar = NULL; } Win32TaskbarManager::~Win32TaskbarManager() { + if (_taskbar) + _taskbar->Release(); + _taskbar = NULL; + + CoUninitialize(); +} + +void Win32TaskbarManager::init() { + // Do nothing if not running on Windows 7 of later + if (!isWin7OrLater()) + return; + + CoInitialize(NULL); + + // Try creating instance (on fail, _taskbar will contain NULL) + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, + 0, + CLSCTX_INPROC_SERVER, + IID_ITaskbarList3, + reinterpret_cast<void**> (&(_taskbar))); + + if (SUCCEEDED(hr)) { + // Initialize taskbar object + if (FAILED(_taskbar->HrInit())) { + _taskbar->Release(); + _taskbar = NULL; + } + } else { + warning("[Win32TaskbarManager::init] Cannot create taskbar instance"); + } } void Win32TaskbarManager::setOverlayIcon(const Common::String &name, const Common::String &description) { + if (_taskbar == NULL) + return; + warning("[Win32TaskbarManager::setOverlayIcon] Not implemented"); } -void Win32TaskbarManager::setProgressValue(int val, int max) { - warning("[Win32TaskbarManager::setProgressValue] Not implemented"); +void Win32TaskbarManager::setProgressValue(int completed, int total) { + if (_taskbar == NULL) + return; + + _taskbar->SetProgressValue(getHwnd(), completed, total); } void Win32TaskbarManager::setProgressState(TaskbarProgressState state) { - warning("[Win32TaskbarManager::setProgressState] Not implemented"); + if (_taskbar == NULL) + return; + + _taskbar->SetProgressState(getHwnd(), (TBPFLAG)state); } void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) { - warning("[Win32TaskbarManager::addRecent] Not implemented"); -}
\ No newline at end of file + if (_taskbar == NULL) + return; + + // ANSI version doesn't seem to work correctly with Win7 jump lists, so explicitly use Unicode interface. + IShellLinkW *link; + + // Get the ScummVM executable path. + WCHAR path[MAX_PATH]; + GetModuleFileNameW(NULL, path, MAX_PATH); + + // Create a shell link. + if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&link)))) { + // Convert game name and description to Unicode. + LPWSTR game = ansiToUnicode(name.c_str()); + LPWSTR desc = ansiToUnicode(description.c_str()); + + // Set link properties. + link->SetPath(path); + link->SetArguments(game); + link->SetIconLocation(path, 0); // There's no way to get a game-specific icon, is there? + + // The link's display name must be set via property store. + IPropertyStore* propStore; + HRESULT hr = link->QueryInterface(&propStore); + if (SUCCEEDED(hr)) { + PROPVARIANT pv; + pv.vt = VT_LPWSTR; + pv.pwszVal = desc; + + hr = propStore->SetValue(PKEY_Title, pv); + + propStore->Commit(); + propStore->Release(); + } + + // SHAddToRecentDocs will cause the games to be added to the Recent list, allowing the + // user to pin them. + SHAddToRecentDocs(SHARD_LINK, link); + link->Release(); + delete[] game; + delete[] desc; + } +} + +bool Win32TaskbarManager::isWin7OrLater() { + OSVERSIONINFOEX versionInfo; + DWORDLONG conditionMask = 0; + + ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX)); + versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + versionInfo.dwMajorVersion = 6; + versionInfo.dwMinorVersion = 1; + + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + + return VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask); +} + +LPWSTR Win32TaskbarManager::ansiToUnicode(const char *s) { + DWORD size = MultiByteToWideChar(0, 0, s, -1, NULL, 0); + + if (size > 0) { + LPWSTR result = new WCHAR[size]; + if (MultiByteToWideChar(0, 0, s, -1, result, size) != 0) + return result; + } + + return NULL; +} + +HWND Win32TaskbarManager::getHwnd() { + SDL_SysWMinfo wmi; + SDL_VERSION(&wmi.version); + + if(!SDL_GetWMInfo(&wmi)) + return NULL; + + return wmi.window; +} + +#endif diff --git a/backends/taskbar/win32/win32-taskbar.h b/backends/taskbar/win32/win32-taskbar.h index 20c1a8d383..d0871d36d2 100644 --- a/backends/taskbar/win32/win32-taskbar.h +++ b/backends/taskbar/win32/win32-taskbar.h @@ -28,18 +28,35 @@ #ifndef BACKEND_WIN32_TASKBAR_H #define BACKEND_WIN32_TASKBAR_H +#ifdef WIN32 + #include "common/str.h" #include "common/taskbar.h" +struct ITaskbarList3; + class Win32TaskbarManager : public Common::TaskbarManager { public: Win32TaskbarManager(); virtual ~Win32TaskbarManager(); + void init(); + virtual void setOverlayIcon(const Common::String &name, const Common::String &description); - virtual void setProgressValue(int val, int max); + virtual void setProgressValue(int completed, int total); virtual void setProgressState(TaskbarProgressState state); virtual void addRecent(const Common::String &name, const Common::String &description); + +private: + HWND _hwnd; + ITaskbarList3 *_taskbar; + + // Helper functions + bool isWin7OrLater(); + LPWSTR ansiToUnicode(const char *s); + HWND getHwnd(); }; +#endif + #endif // BACKEND_WIN32_TASKBAR_H diff --git a/common/taskbar.h b/common/taskbar.h index e29fcdcb36..ea1d218724 100644 --- a/common/taskbar.h +++ b/common/taskbar.h @@ -35,11 +35,11 @@ public: * Values representing the taskbar progress state */ enum TaskbarProgressState { - NoProgress = 0, - Indeterminate = 1, - Normal = 2, - Error = 4, - Paused = 8 + kTaskbarNoProgress = 0, + kTaskbarIndeterminate = 1, + kTaskbarNormal = 2, + kTaskbarError = 4, + kTaskbarPaused = 8 }; TaskbarManager() {} @@ -61,10 +61,10 @@ public: /** * Sets a progress value on the taskbar icon * - * @param val The current progress value - * @param max The maximum progress value + * @param completed The current progress value. + * @param total The maximum progress value. */ - virtual void setProgressValue(int val, int max) {} + virtual void setProgressValue(int completed, int total) {} /** * Sets the progress state on the taskbar icon |