diff options
-rw-r--r-- | backends/module.mk | 6 | ||||
-rw-r--r-- | backends/platform/sdl/posix/posix.cpp | 11 | ||||
-rw-r--r-- | backends/platform/sdl/sdl.cpp | 21 | ||||
-rw-r--r-- | backends/platform/sdl/sdl.h | 4 | ||||
-rw-r--r-- | backends/platform/sdl/win32/win32.cpp | 8 | ||||
-rw-r--r-- | backends/taskbar/unity/unity-taskbar.cpp | 110 | ||||
-rw-r--r-- | backends/taskbar/unity/unity-taskbar.h | 57 | ||||
-rw-r--r-- | backends/taskbar/win32/mingw-compat.h | 142 | ||||
-rw-r--r-- | backends/taskbar/win32/win32-taskbar.cpp | 272 | ||||
-rw-r--r-- | backends/taskbar/win32/win32-taskbar.h | 66 | ||||
-rw-r--r-- | common/system.cpp | 9 | ||||
-rw-r--r-- | common/system.h | 24 | ||||
-rw-r--r-- | common/taskbar.h | 133 | ||||
-rwxr-xr-x | configure | 75 | ||||
-rw-r--r-- | devtools/create_project/create_project.cpp | 6 | ||||
-rw-r--r-- | gui/massadd.cpp | 23 | ||||
-rw-r--r-- | gui/massadd.h | 1 |
17 files changed, 961 insertions, 7 deletions
diff --git a/backends/module.mk b/backends/module.mk index 8063bcf619..e568002d40 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -75,7 +75,8 @@ MODULE_OBJS += \ fs/posix/posix-fs.o \ fs/posix/posix-fs-factory.o \ plugins/posix/posix-provider.o \ - saves/posix/posix-saves.o + saves/posix/posix-saves.o \ + taskbar/unity/unity-taskbar.o endif ifdef MACOSX @@ -89,7 +90,8 @@ MODULE_OBJS += \ fs/windows/windows-fs.o \ fs/windows/windows-fs-factory.o \ midi/windows.o \ - plugins/win32/win32-provider.o + plugins/win32/win32-provider.o \ + taskbar/win32/win32-taskbar.o endif ifdef AMIGAOS diff --git a/backends/platform/sdl/posix/posix.cpp b/backends/platform/sdl/posix/posix.cpp index d757186134..05c779a4e0 100644 --- a/backends/platform/sdl/posix/posix.cpp +++ b/backends/platform/sdl/posix/posix.cpp @@ -33,6 +33,7 @@ #include "backends/platform/sdl/posix/posix.h" #include "backends/saves/posix/posix-saves.h" #include "backends/fs/posix/posix-fs-factory.h" +#include "backends/taskbar/unity/unity-taskbar.h" #include <errno.h> #include <sys/stat.h> @@ -49,6 +50,11 @@ void OSystem_POSIX::init() { // Initialze File System Factory _fsFactory = new POSIXFilesystemFactory(); +#if defined(USE_TASKBAR) && defined(USE_TASKBAR_UNITY) + // Initialize taskbar manager + _taskbarManager = new UnityTaskbarManager(); +#endif + // Invoke parent implementation of this method OSystem_SDL::init(); } @@ -60,6 +66,11 @@ void OSystem_POSIX::initBackend() { // Invoke parent implementation of this method OSystem_SDL::initBackend(); + +#if defined(USE_TASKBAR) && defined(USE_TASKBAR_UNITY) + // Register the taskbar manager as an event source (this is necessary for the glib event loop to be run) + _eventManager->getEventDispatcher()->registerSource((UnityTaskbarManager *)_taskbarManager, false); +#endif } bool OSystem_POSIX::hasFeature(Feature f) { diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index ecaeabf4e1..3f85b1a564 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -31,6 +31,7 @@ #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" #include "common/EventRecorder.h" +#include "common/taskbar.h" #include "common/textconsole.h" #include "backends/saves/default/default-saves.h" @@ -125,6 +126,11 @@ void OSystem_SDL::init() { if (_timerManager == 0) _timerManager = new SdlTimerManager(); +#if defined(USE_TASKBAR) + if (_taskbarManager == 0) + _taskbarManager = new Common::TaskbarManager(); +#endif + #ifdef USE_OPENGL // Setup a list with both SDL and OpenGL graphics modes setupGraphicsModes(); @@ -205,6 +211,21 @@ void OSystem_SDL::initBackend() { } +#if defined(USE_TASKBAR) +void OSystem_SDL::engineInit() { + // Add the started engine to the list of recent tasks + _taskbarManager->addRecent(ConfMan.getActiveDomainName(), ConfMan.get("description")); + + // Set the overlay icon the current running engine + _taskbarManager->setOverlayIcon(ConfMan.getActiveDomainName(), ConfMan.get("description")); +} + +void OSystem_SDL::engineDone() { + // Remove overlay icon + _taskbarManager->setOverlayIcon("", ""); +} +#endif + void OSystem_SDL::initSDL() { // Check if SDL has not been initialized if (!_initedSDL) { diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 707ad8bc55..395b2b3aac 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -54,6 +54,10 @@ public: // Override functions from ModularBackend and OSystem virtual void initBackend(); +#if defined(USE_TASKBAR) + virtual void engineInit(); + virtual void engineDone(); +#endif virtual Common::HardwareKeySet *getHardwareKeySet(); virtual void quit(); virtual void fatalError(); diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp index 432f7077ae..5b02a20abc 100644 --- a/backends/platform/sdl/win32/win32.cpp +++ b/backends/platform/sdl/win32/win32.cpp @@ -36,6 +36,7 @@ #include "backends/platform/sdl/win32/win32.h" #include "backends/fs/windows/windows-fs-factory.h" +#include "backends/taskbar/win32/win32-taskbar.h" #include "common/memstream.h" @@ -81,9 +82,14 @@ void OSystem_Win32::init() { } #endif - // Initialze File System Factory + // Initialize File System Factory _fsFactory = new WindowsFilesystemFactory(); +#if defined(USE_TASKBAR) + // Initialize taskbar manager + _taskbarManager = new Win32TaskbarManager(); +#endif + // Invoke parent implementation of this method OSystem_SDL::init(); } diff --git a/backends/taskbar/unity/unity-taskbar.cpp b/backends/taskbar/unity/unity-taskbar.cpp new file mode 100644 index 0000000000..49c56b746d --- /dev/null +++ b/backends/taskbar/unity/unity-taskbar.cpp @@ -0,0 +1,110 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" + +#if defined(UNIX) && defined(USE_TASKBAR) && defined(USE_TASKBAR_UNITY) + +#include "backends/taskbar/unity/unity-taskbar.h" + +#include "common/textconsole.h" + +UnityTaskbarManager::UnityTaskbarManager() { + g_type_init(); + + _loop = g_main_loop_new(NULL, FALSE); + + _launcher = unity_launcher_entry_get_for_desktop_id("scummvm.desktop"); +} + +UnityTaskbarManager::~UnityTaskbarManager() { + g_main_loop_unref(_loop); + _loop = NULL; +} + +void UnityTaskbarManager::setProgressValue(int completed, int total) { + if (_launcher == NULL) + return; + + double percentage = (double)completed / (double)total; + unity_launcher_entry_set_progress(_launcher, percentage); + unity_launcher_entry_set_progress_visible(_launcher, TRUE); +} + +void UnityTaskbarManager::setProgressState(TaskbarProgressState state) { + if (_launcher == NULL) + return; + + switch (state) { + default: + warning("[UnityTaskbarManager::setProgressState] Unknown state / Not implemented (%d)", state); + // fallback to noprogress state + + case kTaskbarNoProgress: + unity_launcher_entry_set_progress_visible(_launcher, FALSE); + break; + + // Unity only support two progress states as of 3.0: visible or not visible + // We show progress in all of those states + case kTaskbarIndeterminate: + case kTaskbarNormal: + case kTaskbarError: + case kTaskbarPaused: + unity_launcher_entry_set_progress_visible(_launcher, TRUE); + break; + } +} + +void UnityTaskbarManager::addRecent(const Common::String &name, const Common::String &description) { + warning("[UnityTaskbarManager::addRecent] Not implemented"); +} + +void UnityTaskbarManager::setCount(int count) { + if (_launcher == NULL) + return; + + unity_launcher_entry_set_count(_launcher, count); + + unity_launcher_entry_set_count_visible(_launcher, (count == 0) ? FALSE : TRUE); +} + +// Unity requires the glib event loop to the run to function properly +// as events are sent asynchronously +bool UnityTaskbarManager::pollEvent(Common::Event &event) { + if (!_loop) + return false; + + // Get context + GMainContext *context = g_main_loop_get_context(_loop); + if (!context) + return false; + + // Dispatch events + g_main_context_iteration(context, FALSE); + + return false; +} + +#endif diff --git a/backends/taskbar/unity/unity-taskbar.h b/backends/taskbar/unity/unity-taskbar.h new file mode 100644 index 0000000000..9f14b44d8f --- /dev/null +++ b/backends/taskbar/unity/unity-taskbar.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKEND_UNITY_TASKBAR_H +#define BACKEND_UNITY_TASKBAR_H + +#if defined(UNIX) && defined(USE_TASKBAR) && defined(USE_TASKBAR_UNITY) + +#include "common/events.h" +#include "common/str.h" +#include "common/taskbar.h" + +#include <unity.h> + +class UnityTaskbarManager : public Common::TaskbarManager, public Common::EventSource { +public: + UnityTaskbarManager(); + virtual ~UnityTaskbarManager(); + + virtual void setProgressValue(int completed, int total); + virtual void setProgressState(TaskbarProgressState state); + virtual void addRecent(const Common::String &name, const Common::String &description); + virtual void setCount(int count); + + // Implementation of the EventSource interface + virtual bool pollEvent(Common::Event &event); + +private: + GMainLoop *_loop; + UnityLauncherEntry *_launcher; +}; + +#endif + +#endif // BACKEND_UNITY_TASKBAR_H diff --git a/backends/taskbar/win32/mingw-compat.h b/backends/taskbar/win32/mingw-compat.h new file mode 100644 index 0000000000..06968b62ff --- /dev/null +++ b/backends/taskbar/win32/mingw-compat.h @@ -0,0 +1,142 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// TODO: Remove header when the latest changes to the Windows SDK have been integrated into MingW +// For reference, the interface definitions here are imported the SDK headers and from the +// EcWin7 project (https://code.google.com/p/dukto/) + +#ifndef BACKEND_WIN32_TASKBAR_MINGW_H +#define BACKEND_WIN32_TASKBAR_MINGW_H + +#if defined(WIN32) +#if defined(__GNUC__) +#ifdef __MINGW32__ + +#ifdef _WIN32_WINNT + #undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0501 +#include <windows.h> +#include <commctrl.h> +#include <initguid.h> +#include <shlwapi.h> +#define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK + +// Taskbar GUID definitions +DEFINE_GUID(CLSID_TaskbarList,0x56fdf344,0xfd6d,0x11d0,0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90); +DEFINE_GUID(IID_ITaskbarList3,0xea1afb91,0x9e28,0x4b86,0x90,0xE9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf); +DEFINE_GUID(IID_IPropertyStore,0x886d8eeb,0x8cf2,0x4446,0x8d,0x02,0xcd,0xba,0x1d,0xbd,0xcf,0x99); + +// Property key +typedef struct _tagpropertykey { + GUID fmtid; + DWORD pid; +} PROPERTYKEY; + +#define REFPROPERTYKEY const PROPERTYKEY & + +typedef struct tagPROPVARIANT PROPVARIANT; +#define REFPROPVARIANT const PROPVARIANT & + +// Property store +DECLARE_INTERFACE_(IPropertyStore, IUnknown) { + STDMETHOD (GetCount) (DWORD *cProps) PURE; + STDMETHOD (GetAt) (DWORD iProp, PROPERTYKEY *pkey) PURE; + STDMETHOD (GetValue) (REFPROPERTYKEY key, PROPVARIANT *pv) PURE; + STDMETHOD (SetValue) (REFPROPERTYKEY key, REFPROPVARIANT propvar) PURE; + STDMETHOD (Commit) (void) PURE; +}; +typedef IPropertyStore *LPIPropertyStore; + +// Mingw-specific defines for taskbar integration +typedef enum THUMBBUTTONMASK { + THB_BITMAP = 0x1, + THB_ICON = 0x2, + THB_TOOLTIP = 0x4, + THB_FLAGS = 0x8 +} THUMBBUTTONMASK; + +typedef enum THUMBBUTTONFLAGS { + THBF_ENABLED = 0, + THBF_DISABLED = 0x1, + THBF_DISMISSONCLICK = 0x2, + THBF_NOBACKGROUND = 0x4, + THBF_HIDDEN = 0x8, + THBF_NONINTERACTIVE = 0x10 +} THUMBBUTTONFLAGS; + +typedef struct THUMBBUTTON { + THUMBBUTTONMASK dwMask; + UINT iId; + UINT iBitmap; + HICON hIcon; + WCHAR szTip[260]; + THUMBBUTTONFLAGS dwFlags; +} THUMBBUTTON; +typedef struct THUMBBUTTON *LPTHUMBBUTTON; + +typedef enum TBPFLAG { + TBPF_NOPROGRESS = 0, + TBPF_INDETERMINATE = 0x1, + TBPF_NORMAL = 0x2, + TBPF_ERROR = 0x4, + TBPF_PAUSED = 0x8 +} TBPFLAG; + +// Taskbar interface +DECLARE_INTERFACE_(ITaskbarList3, IUnknown) { + // IUnknown + STDMETHOD(QueryInterface) (THIS_ REFIID riid, void **ppv) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + // ITaskbarList + STDMETHOD(HrInit) (THIS) PURE; + STDMETHOD(AddTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(DeleteTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(ActivateTab) (THIS_ HWND hwnd) PURE; + STDMETHOD(SetActiveAlt) (THIS_ HWND hwnd) PURE; + STDMETHOD (MarkFullscreenWindow) (THIS_ HWND hwnd, int fFullscreen) PURE; + // ITaskbarList3 + STDMETHOD (SetProgressValue) (THIS_ HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) PURE; + STDMETHOD (SetProgressState) (THIS_ HWND hwnd, TBPFLAG tbpFlags) PURE; + STDMETHOD (RegisterTab) (THIS_ HWND hwndTab, HWND hwndMDI) PURE; + STDMETHOD (UnregisterTab) (THIS_ HWND hwndTab) PURE; + STDMETHOD (SetTabOrder) (THIS_ HWND hwndTab, HWND hwndInsertBefore) PURE; + STDMETHOD (SetTabActive) (THIS_ HWND hwndTab, HWND hwndMDI, DWORD dwReserved) PURE; + STDMETHOD (ThumbBarAddButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE; + STDMETHOD (ThumbBarUpdateButtons) (THIS_ HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) PURE; + STDMETHOD (ThumbBarSetImageList) (THIS_ HWND hwnd, HIMAGELIST himl) PURE; + STDMETHOD (SetOverlayIcon) (THIS_ HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE; + STDMETHOD (SetThumbnailTooltip) (THIS_ HWND hwnd, LPCWSTR pszTip) PURE; + STDMETHOD (SetThumbnailClip) (THIS_ HWND hwnd, RECT *prcClip) PURE; +}; + +typedef ITaskbarList3 *LPITaskbarList3; + +#endif // __MINGW32__ +#endif // __GNUC__ +#endif // WIN32 + +#endif // BACKEND_WIN32_TASKBAR_MINGW_H diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp new file mode 100644 index 0000000000..0cfd81e3f2 --- /dev/null +++ b/backends/taskbar/win32/win32-taskbar.cpp @@ -0,0 +1,272 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// We cannot use common/scummsys.h directly as it will include +// windows.h and we need to do it by hand to allow excluded functions +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#if defined(WIN32) && defined(USE_TASKBAR) + +// Needed for taskbar functions +#if defined(__GNUC__) +#ifdef __MINGW32__ + #include "backends/taskbar/win32/mingw-compat.h" +#else + #error Only compilation with MingW is supported +#endif +#else + // We need certain functions that are excluded by default + #undef NONLS + #undef NOICONS + #include <windows.h> + #if defined(ARRAYSIZE) + #undef ARRAYSIZE + #endif + + // Default MSVC headers for ITaskbarList3 and IShellLink + #include <SDKDDKVer.h> +#endif +#include <shlobj.h> + +// For HWND +#include <SDL_syswm.h> + +#include "common/scummsys.h" + +#include "backends/taskbar/win32/win32-taskbar.h" + +#include "common/config-manager.h" +#include "common/textconsole.h" +#include "common/file.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() { + // Do nothing if not running on Windows 7 or 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"); + } +} + +Win32TaskbarManager::~Win32TaskbarManager() { + if (_taskbar) + _taskbar->Release(); + _taskbar = NULL; + + CoUninitialize(); +} + +void Win32TaskbarManager::setOverlayIcon(const Common::String &name, const Common::String &description) { + //warning("[Win32TaskbarManager::setOverlayIcon] Setting overlay icon to: %s (%s)", name.c_str(), description.c_str()); + + if (_taskbar == NULL) + return; + + if (name.empty()) { + _taskbar->SetOverlayIcon(getHwnd(), NULL, L""); + return; + } + + // Compute full icon path + Common::String path = getIconPath(name); + if (path.empty()) + return; + + HICON pIcon = (HICON)::LoadImage(NULL, path.c_str(), IMAGE_ICON, 16, 16, LR_LOADFROMFILE); + if (!pIcon) { + warning("[Win32TaskbarManager::setOverlayIcon] Cannot load icon!"); + return; + } + + // Sets the overlay icon + LPWSTR desc = ansiToUnicode(description.c_str()); + _taskbar->SetOverlayIcon(getHwnd(), pIcon, desc); + + DestroyIcon(pIcon); + + delete[] desc; +} + +void Win32TaskbarManager::setProgressValue(int completed, int total) { + if (_taskbar == NULL) + return; + + _taskbar->SetProgressValue(getHwnd(), completed, total); +} + +void Win32TaskbarManager::setProgressState(TaskbarProgressState state) { + if (_taskbar == NULL) + return; + + _taskbar->SetProgressState(getHwnd(), (TBPFLAG)state); +} + +void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) { + //warning("[Win32TaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str()); + + 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_IShellLinkW, reinterpret_cast<void**> (&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); + + Common::String iconPath = getIconPath(name); + if (iconPath.empty()) { + link->SetIconLocation(path, 0); // No game-specific icon available + } else { + LPWSTR icon = ansiToUnicode(iconPath.c_str()); + + link->SetIconLocation(icon, 0); + + delete[] icon; + } + + // The link's display name must be set via property store. + IPropertyStore* propStore; + HRESULT hr = link->QueryInterface(IID_IPropertyStore, reinterpret_cast<void**> (&(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; + } +} + +Common::String Win32TaskbarManager::getIconPath(Common::String target) { + // We first try to look for a iconspath configuration variable then + // fallback to the extra path + // + // Icons can be either in a subfolder named "icons" or directly in the path + + Common::String iconsPath = ConfMan.get("iconspath"); + Common::String extraPath = ConfMan.get("extrapath"); + +#define TRY_ICON_PATH(path) { \ + Common::FSNode node((path)); \ + if (node.exists()) \ + return (path); \ +} + + if (!iconsPath.empty()) { + TRY_ICON_PATH(iconsPath + "/" + target + ".ico"); + TRY_ICON_PATH(iconsPath + "/" + ConfMan.get("gameid") + ".ico"); + TRY_ICON_PATH(iconsPath + "/icons/" + target + ".ico"); + TRY_ICON_PATH(iconsPath + "/icons/" + ConfMan.get("gameid") + ".ico"); + } + + if (!extraPath.empty()) { + TRY_ICON_PATH(extraPath + "/" + target + ".ico"); + TRY_ICON_PATH(extraPath + "/" + ConfMan.get("gameid") + ".ico"); + TRY_ICON_PATH(extraPath + "/icons/" + target + ".ico"); + TRY_ICON_PATH(extraPath + "/icons/" + ConfMan.get("gameid") + ".ico"); + } + + return ""; +} + +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 new file mode 100644 index 0000000000..3415a79bd7 --- /dev/null +++ b/backends/taskbar/win32/win32-taskbar.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKEND_WIN32_TASKBAR_H +#define BACKEND_WIN32_TASKBAR_H + +#if defined(WIN32) && defined(USE_TASKBAR) + +#include "common/str.h" +#include "common/taskbar.h" + +struct ITaskbarList3; + +class Win32TaskbarManager : public Common::TaskbarManager { +public: + Win32TaskbarManager(); + virtual ~Win32TaskbarManager(); + + virtual void setOverlayIcon(const Common::String &name, const Common::String &description); + virtual void setProgressValue(int completed, int total); + virtual void setProgressState(TaskbarProgressState state); + virtual void addRecent(const Common::String &name, const Common::String &description); + +private: + ITaskbarList3 *_taskbar; + + /** + * Get the path to an icon for the game + * + * @param target The game target + * + * @return The icon path (or "" if no icon was found) + */ + Common::String getIconPath(Common::String target); + + // Helper functions + bool isWin7OrLater(); + LPWSTR ansiToUnicode(const char *s); + HWND getHwnd(); +}; + +#endif + +#endif // BACKEND_WIN32_TASKBAR_H diff --git a/common/system.cpp b/common/system.cpp index 1645a6be10..8d5bfd39cd 100644 --- a/common/system.cpp +++ b/common/system.cpp @@ -27,6 +27,7 @@ #include "common/fs.h" #include "common/savefile.h" #include "common/str.h" +#include "common/taskbar.h" #include "common/textconsole.h" #include "backends/audiocd/default/default-audiocd.h" @@ -40,6 +41,9 @@ OSystem::OSystem() { _eventManager = 0; _timerManager = 0; _savefileManager = 0; +#if defined(USE_TASKBAR) + _taskbarManager = 0; +#endif _fsFactory = 0; } @@ -53,6 +57,11 @@ OSystem::~OSystem() { delete _timerManager; _timerManager = 0; +#if defined(USE_TASKBAR) + delete _taskbarManager; + _taskbarManager = 0; +#endif + delete _savefileManager; _savefileManager = 0; diff --git a/common/system.h b/common/system.h index 3e740ff0c1..15fbe386b1 100644 --- a/common/system.h +++ b/common/system.h @@ -42,6 +42,9 @@ struct Rect; class SaveFileManager; class SearchSet; class String; +#if defined(USE_TASKBAR) +class TaskbarManager; +#endif class TimerManager; class SeekableReadStream; class WriteStream; @@ -149,6 +152,15 @@ protected: */ Common::SaveFileManager *_savefileManager; +#if defined(USE_TASKBAR) + /** + * No default value is provided for _savefileManager by OSystem. + * + * @note _savefileManager is deleted by the OSystem destructor. + */ + Common::TaskbarManager *_taskbarManager; +#endif + /** * No default value is provided for _fsFactory by OSystem. * @@ -1047,6 +1059,18 @@ public: return _savefileManager; } +#if defined(USE_TASKBAR) + /** + * Returns the TaskbarManager, used to handle progress bars, + * icon overlay, tasks and recent items list on the taskbar. + * + * @return the TaskbarManager for the current architecture + */ + virtual Common::TaskbarManager *getTaskbarManager() { + return _taskbarManager; + } +#endif + /** * Returns the FilesystemFactory object, depending on the current architecture. * diff --git a/common/taskbar.h b/common/taskbar.h new file mode 100644 index 0000000000..023227e5e0 --- /dev/null +++ b/common/taskbar.h @@ -0,0 +1,133 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef COMMON_TASKBAR_MANAGER_H +#define COMMON_TASKBAR_MANAGER_H + +#include "common/scummsys.h" +#include "common/str.h" + +#if defined(USE_TASKBAR) + +namespace Common { + +/** + * The TaskbarManager allows interaction with the ScummVM application icon: + * - in the taskbar on Windows 7 and later + * - in the launcher for Unity + * - in the dock on MacOSX + * - ... + * + * This allows GUI code and engines to display a progress bar, an overlay icon and/or count + * associated with the ScummVM icon as well as add the started engine to the recent items + * list (so that the user can start the engine directly in one click). + * + * Examples of use: + * - Track search progress and found engines when running the Mass Add dialog + * - Add an entry to the recent items when starting an engine + * - Show the current running engine icon as an overlay + * + * @note functionality will vary between supported platforms (due to API limitations) + * and some of the methods will just be no-ops or approximate the functionality + * as best as possible + */ +class TaskbarManager { +public: + /** + * Values representing the taskbar progress state + */ + enum TaskbarProgressState { + kTaskbarNoProgress = 0, + kTaskbarIndeterminate = 1, + kTaskbarNormal = 2, + kTaskbarError = 4, + kTaskbarPaused = 8 + }; + + TaskbarManager() {} + virtual ~TaskbarManager() {} + + /** + * Sets an overlay icon on the taskbar icon + * + * When an empty name is given, no icon is shown + * and the current overlay icon (if any) is removed + * + * @param name Path to the icon + * @param description The description + * + * @note on Windows, the icon should be an ICO file + */ + virtual void setOverlayIcon(const String &name, const String &description) {} + + /** + * Sets a progress value on the taskbar icon + * + * @param completed The current progress value. + * @param total The maximum progress value. + */ + virtual void setProgressValue(int completed, int total) {} + + /** + * Sets the progress state on the taskbar icon + * + * State can be any of the following: + * - NoProgress: disable display of progress state + * - Indeterminate + * - Normal + * - Error + * - Paused + * + * @param state The progress state + */ + virtual void setProgressState(TaskbarProgressState state) {} + + /** + * Sets the count number associated with the icon as an overlay + * + * @param count The count + * + * @note Setting a count of 0 will hide the count + */ + virtual void setCount(int count) {} + + /** + * Adds an engine to the recent items list + * + * Path is automatically set to the current executable path, + * an icon name is generated (with fallback to default icon) + * and the command line is set to start the engine on click. + * + * @param name The target name. + * @param description The description. + */ + virtual void addRecent(const String &name, const String &description) {} + +}; + +} // End of namespace Common + +#endif + +#endif // COMMON_TASKBAR_MANAGER_H @@ -142,6 +142,8 @@ _fluidsynth=auto _opengl=auto _opengles=auto _readline=auto +_taskbar=yes +_libunity=auto # Default option behaviour yes/no _debug_build=auto _release_build=auto @@ -767,6 +769,7 @@ Optional Features: --disable-scalers exclude scalers --disable-hq-scalers exclude HQ2x and HQ3x scalers --disable-translation don't build support for translated messages + --disable-taskbar don't build support for taskbar and launcher integration --enable-text-console use text console instead of graphical console --enable-verbose-build enable regular echoing of commands during build process @@ -816,6 +819,9 @@ Optional Libraries: --with-readline-prefix=DIR Prefix where readline is installed (optional) --disable-readline disable readline support in text console [autodetect] + --with-libunity-prefix=DIR Prefix where libunity is installed (optional) + --disable-libunity disable Unity launcher integration [autodetect] + Some influential environment variables: LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> @@ -863,6 +869,10 @@ for ac_option in $@; do --disable-fluidsynth) _fluidsynth=no ;; --enable-readline) _readline=yes ;; --disable-readline) _readline=no ;; + --enable-taskbar) _taskbar=yes ;; + --disable-taskbar) _taskbar=no ;; + --enable-libunity) _libunity=yes ;; + --disable-libunity) _libunity=no ;; --enable-opengl) _opengl=yes ;; --disable-opengl) _opengl=no ;; --enable-verbose-build) _verbose_build=yes ;; @@ -938,6 +948,11 @@ for ac_option in $@; do READLINE_CFLAGS="-I$arg/include" READLINE_LIBS="-L$arg/lib" ;; + --with-libunity-prefix=*) + arg=`echo $ac_option | cut -d '=' -f 2` + LIBUNITY_CFLAGS="-I$arg/include" + LIBUNITY_LIBS="-L$arg/lib" + ;; --with-opengl-prefix=*) arg=`echo $ac_option | cut -d '=' -f 2` OPENGL_CFLAGS="-I$arg/include" @@ -2966,6 +2981,43 @@ define_in_config_h_if_yes "$_readline" 'USE_READLINE' define_in_config_h_if_yes "$_text_console" 'USE_TEXT_CONSOLE_FOR_DEBUGGER' # +# Check for Unity if taskbar integration is enabled +# +echocheck "libunity" +if test "$_unix" = no || test "$_taskbar" = no; then + _libunity=no +else +if test "$_libunity" = auto ; then + case $_host_os in + mingw*) + # pkgconfig and unity are not supported on mingw + _libunity=no + ;; + *) + # Unity has a lots of dependencies, update the libs and cflags var with them + LIBUNITY_LIBS="$LIBUNITY_LIBS $(pkg-config --libs unity = 3.8.4)" + LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS $(pkg-config --cflags unity = 3.8.4)" + _libunity=no + cat > $TMPC << EOF +#include <unity.h> +int main(void) { + unity_launcher_entry_get_for_desktop_id("scummvm.desktop"); + return 0; +} +EOF + cc_check $LIBUNITY_CFLAGS $LIBUNITY_LIBS -lunity && _libunity=yes + ;; + esac +fi +if test "$_libunity" = yes ; then + LIBS="$LIBS $LIBUNITY_LIBS -lunity" + INCLUDES="$INCLUDES $LIBUNITY_CFLAGS" +fi +define_in_config_h_if_yes "$_libunity" 'USE_TASKBAR_UNITY' +fi +echo "$_libunity" + +# # Check for OpenGL (ES) # echocheck "OpenGL" @@ -3141,6 +3193,29 @@ EOF fi # +# Check whether to build taskbar integration support +# +echo_n "Building taskbar integration support... " +define_in_config_if_yes $_taskbar 'USE_TASKBAR' +if test "$_taskbar" = yes; then + case $_host_os in + mingw*) + LIBS="$LIBS -lole32 -luuid" + echo "win32" + ;; + *) + if test "$_unity" = yes; then + echo "unity" + else + echo "$_taskbar" + fi + ;; + esac +else + echo "$_taskbar" +fi + +# # Figure out installation directories # test "x$prefix" = xNONE && prefix=/usr/local diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp index 29bc5bfcd5..35d08561bf 100644 --- a/devtools/create_project/create_project.cpp +++ b/devtools/create_project/create_project.cpp @@ -364,6 +364,11 @@ int main(int argc, char *argv[]) { provider = new CreateProjectTool::CodeBlocksProvider(globalWarnings, projectWarnings); + + // Those libraries are automatically added by MSVC, but we need to add them manually with mingw + setup.libraries.push_back("ole32"); + setup.libraries.push_back("uuid"); + break; case kProjectMSVC: @@ -774,6 +779,7 @@ const Feature s_features[] = { { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" }, { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling. { "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" }, + { "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" }, { "translation", "USE_TRANSLATION", "", true, "Translation support" }, { "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"}, { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there diff --git a/gui/massadd.cpp b/gui/massadd.cpp index b0adce3f47..70580e8b9c 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -24,6 +24,7 @@ #include "common/config-manager.h" #include "common/debug.h" #include "common/system.h" +#include "common/taskbar.h" #include "common/translation.h" #include "gui/launcher.h" // For addGameToConf() @@ -60,6 +61,7 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) : Dialog("MassAdd"), _dirsScanned(0), _oldGamesCount(0), + _dirTotal(0), _okButton(0), _dirProgressText(0), _gameProgressText(0) { @@ -69,14 +71,14 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) // The dir we start our scan at _scanStack.push(startDir); -// Removed for now... Why would you put a title on mass add dialog called "Mass Add Dialog"? -// new StaticTextWidget(this, "massadddialog_caption", "Mass Add Dialog"); + // Removed for now... Why would you put a title on mass add dialog called "Mass Add Dialog"? + // new StaticTextWidget(this, "massadddialog_caption", "Mass Add Dialog"); _dirProgressText = new StaticTextWidget(this, "MassAdd.DirProgressText", - _("... progress ...")); + _("... progress ...")); _gameProgressText = new StaticTextWidget(this, "MassAdd.GameProgressText", - _("... progress ...")); + _("... progress ...")); _dirProgressText->setAlign(Graphics::kTextAlignCenter); _gameProgressText->setAlign(Graphics::kTextAlignCenter); @@ -130,6 +132,12 @@ struct GameDescLess { void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { +#if defined(USE_TASKBAR) + // Remove progress bar and count from taskbar + g_system->getTaskbarManager()->setProgressState(Common::TaskbarManager::kTaskbarNoProgress); + g_system->getTaskbarManager()->setCount(0); +#endif + // FIXME: It's a really bad thing that we use two arbitrary constants if (cmd == kOkCmd) { // Sort the detected games. This is not strictly necessary, but nice for @@ -226,10 +234,17 @@ void MassAddDialog::handleTickle() { for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) { if (file->isDirectory()) { _scanStack.push(*file); + + _dirTotal++; } } _dirsScanned++; + +#if defined(USE_TASKBAR) + g_system->getTaskbarManager()->setProgressValue(_dirsScanned, _dirTotal); + g_system->getTaskbarManager()->setCount(_games.size()); +#endif } diff --git a/gui/massadd.h b/gui/massadd.h index 15cef7ba68..7350213835 100644 --- a/gui/massadd.h +++ b/gui/massadd.h @@ -60,6 +60,7 @@ private: int _dirsScanned; int _oldGamesCount; + int _dirTotal; Widget *_okButton; StaticTextWidget *_dirProgressText; |