aboutsummaryrefslogtreecommitdiff
path: root/backends/taskbar
diff options
context:
space:
mode:
Diffstat (limited to 'backends/taskbar')
-rw-r--r--backends/taskbar/macosx/dockplugin/dockplugin.m125
-rw-r--r--backends/taskbar/macosx/macosx-taskbar.h1
-rw-r--r--backends/taskbar/macosx/macosx-taskbar.mm67
-rw-r--r--backends/taskbar/win32/win32-taskbar.cpp44
-rw-r--r--backends/taskbar/win32/win32-taskbar.h2
5 files changed, 224 insertions, 15 deletions
diff --git a/backends/taskbar/macosx/dockplugin/dockplugin.m b/backends/taskbar/macosx/dockplugin/dockplugin.m
new file mode 100644
index 0000000000..9d864ef2a8
--- /dev/null
+++ b/backends/taskbar/macosx/dockplugin/dockplugin.m
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ */
+
+#include <Cocoa/Cocoa.h>
+
+@interface ScummVMDockTilePlugIn : NSObject <NSDockTilePlugIn> {
+ NSMenu *recentGamesMenu;
+}
+@end
+
+@interface StartGameMenuItem : NSMenuItem {
+ NSString *game;
+}
+- (IBAction) startGame;
+- (NSMenuItem*)initWithGame:(NSString *)gameId description:(NSString*)desc icon:(NSString*)iconFile;
+@end
+
+@implementation ScummVMDockTilePlugIn
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ recentGamesMenu = nil;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [recentGamesMenu release];
+ [super dealloc];
+}
+
+
+- (void)setDockTile:(NSDockTile *)dockTile {
+}
+
+- (NSMenu*)dockMenu {
+ // Get the list or recent games
+ CFPreferencesAppSynchronize(CFSTR("org.scummvm.scummvm"));
+ NSArray *array = CFPreferencesCopyAppValue(CFSTR("recentGames"), CFSTR("org.scummvm.scummvm"));
+ if (array == nil)
+ return nil;
+
+ // Create the menu
+ if (recentGamesMenu == nil)
+ recentGamesMenu = [[NSMenu alloc] init];
+ else
+ [recentGamesMenu removeAllItems];
+
+ NSEnumerator *enumerator = [array objectEnumerator];
+ NSDictionary *recentGame;
+ while (recentGame = [enumerator nextObject]) {
+ NSString *gameId = [recentGame valueForKey:@"game"];
+ NSString *desc = [recentGame valueForKey:@"description"];
+ NSString *iconFile = [recentGame valueForKey:@"icon"];
+
+ StartGameMenuItem *menuItem = [[StartGameMenuItem alloc] initWithGame:gameId description:desc icon:iconFile];
+ [recentGamesMenu addItem:menuItem];
+ [menuItem release];
+ }
+
+ return recentGamesMenu;
+}
+
+@end
+
+@implementation StartGameMenuItem
+
+- (NSMenuItem*)initWithGame:(NSString *)gameId description:(NSString*)desc icon:(NSString*)iconFile {
+ self = [super initWithTitle:(desc == nil ? gameId : desc) action:@selector(startGame) keyEquivalent:@""];
+ [self setTarget:self];
+
+ if (iconFile != nil) {
+ NSImage *image = [[NSImage alloc] initWithContentsOfFile:iconFile];
+ [self setImage:image];
+ [image release];
+ }
+
+ game = gameId;
+ [game retain];
+
+ return self;
+}
+
+- (void)dealloc {
+ [game release];
+ [super dealloc];
+}
+
+- (IBAction) startGame {
+ NSLog(@"Starting Game %@...", game);
+
+ NSString *scummVMPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"org.scummvm.scummvm"];
+ if (scummVMPath == nil) {
+ NSLog(@"Cannot find ScummVM.app!");
+ return;
+ }
+ // Start ScummVM.app with the game ID as argument
+ NSURL *url = [NSURL fileURLWithPath:scummVMPath];
+ NSMutableDictionary *args = [[NSMutableDictionary alloc] init];
+ [args setObject:[NSArray arrayWithObject:game] forKey:NSWorkspaceLaunchConfigurationArguments];
+ [[NSWorkspace sharedWorkspace] launchApplicationAtURL:url options:NSWorkspaceLaunchDefault configuration:args error:nil];
+ [args release];
+}
+
+@end
diff --git a/backends/taskbar/macosx/macosx-taskbar.h b/backends/taskbar/macosx/macosx-taskbar.h
index 5d5b9d02cd..55bb97a691 100644
--- a/backends/taskbar/macosx/macosx-taskbar.h
+++ b/backends/taskbar/macosx/macosx-taskbar.h
@@ -37,6 +37,7 @@ public:
virtual void setProgressValue(int completed, int total);
virtual void setProgressState(TaskbarProgressState state);
virtual void setCount(int count);
+ virtual void addRecent(const Common::String &name, const Common::String &description);
virtual void notifyError();
virtual void clearError();
diff --git a/backends/taskbar/macosx/macosx-taskbar.mm b/backends/taskbar/macosx/macosx-taskbar.mm
index ae087dfb85..c842eb8090 100644
--- a/backends/taskbar/macosx/macosx-taskbar.mm
+++ b/backends/taskbar/macosx/macosx-taskbar.mm
@@ -29,9 +29,6 @@
// NSDockTile was introduced with Mac OS X 10.5.
// Try provide backward compatibility by avoiding NSDockTile symbols.
-// TODO: Implement recent list, maybe as a custom menu on dock tile when app is not running
-// See Dock Tile plug-in at https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/CreatingaDockTilePlug-in/CreatingaDockTilePlug-in.html
-
#include "backends/taskbar/macosx/macosx-taskbar.h"
#include "common/config-manager.h"
#include "common/file.h"
@@ -39,6 +36,9 @@
#include <AppKit/NSApplication.h>
#include <AppKit/NSImage.h>
#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSUserDefaults.h>
#include <AppKit/NSImageView.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSBezierPath.h>
@@ -120,7 +120,7 @@ void MacOSXTaskbarManager::setOverlayIcon(const Common::String &name, const Comm
initOverlayIconView();
CFStringRef imageFile = CFStringCreateWithCString(0, path.c_str(), kCFStringEncodingASCII);
- NSImage* image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
+ NSImage *image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
[_overlayIconView setImage:image];
[image release];
CFRelease(imageFile);
@@ -234,5 +234,64 @@ return (path); \
return "";
}
+void MacOSXTaskbarManager::addRecent(const Common::String &name, const Common::String &description) {
+ //warning("[MacOSXTaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str());
+
+ if (_dockTile == nil)
+ return;
+
+ // Store the game, description and icon in user preferences.
+ // The NSDockTilePlugin will retrieve them there to list them in the dock tile menu.
+
+ CFStringRef gameName = CFStringCreateWithCString(0, name.c_str(), kCFStringEncodingASCII);
+ CFStringRef desc = CFStringCreateWithCString(0, description.c_str(), kCFStringEncodingASCII);
+
+ // First build the dictionary for this game.
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
+ [dict setObject:(NSString *)gameName forKey:@"game"];
+ [dict setObject:(NSString *)desc forKey:@"description"];
+
+ // Icon
+ Common::String iconPath = getIconPath(name);
+ if (!iconPath.empty()) {
+ CFStringRef icon = CFStringCreateWithCString(0, iconPath.c_str(), kCFStringEncodingASCII);
+ [dict setObject:(NSString *)icon forKey:@"icon"];
+ CFRelease(icon);
+ }
+
+ // Retrieve the current list of recent items and update it.
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ NSArray *oldArray = [defaults arrayForKey:@"recentGames"];
+ if (oldArray == nil) {
+ [defaults setObject:[NSArray arrayWithObject:dict] forKey:@"recentGames"];
+ } else {
+ NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:oldArray];
+ // Insert the new game at the start
+ [newArray insertObject:dict atIndex:0];
+ // If the game was already present in the array, remove it
+ for (unsigned int i = 1 ; i < [newArray count] ; ++i) {
+ NSDictionary *oldDict = [newArray objectAtIndex:i];
+ if (oldDict == nil)
+ continue;
+ NSString *oldGame = [oldDict valueForKey:@"game"];
+ if (oldGame != nil && [oldGame isEqualToString:(NSString*)gameName]) {
+ [newArray removeObjectAtIndex:i];
+ break;
+ }
+ }
+ // And make sure we limit the size of the array to 5 games
+ if ([newArray count] > 5)
+ [newArray removeLastObject];
+ [defaults setObject:newArray forKey:@"recentGames"];
+ [newArray release];
+ }
+
+ // Finally release the dictionary
+ [dict release];
+ CFRelease(gameName);
+ CFRelease(desc);
+}
+
+
#endif
diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp
index d45253c676..b2810e55b4 100644
--- a/backends/taskbar/win32/win32-taskbar.cpp
+++ b/backends/taskbar/win32/win32-taskbar.cpp
@@ -28,10 +28,39 @@
#if defined(WIN32) && defined(USE_TASKBAR)
+// HACK: To get __MINGW64_VERSION_foo defines we need to manually include
+// _mingw.h in this file because we do not include any system headers at this
+// point on purpose. The defines are required to detect whether this is a
+// classic MinGW toolchain or a MinGW-w64 based one.
+#if defined(__MINGW32__)
+#include <_mingw.h>
+#endif
+
// Needed for taskbar functions
-#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
+// HACK: MinGW-w64 based toolchains include the symbols we require in their
+// headers. The 32 bit incarnation only defines __MINGW32__. This leads to
+// build breakage due to clashes with our compat header. Luckily MinGW-w64
+// based toolchains define __MINGW64_VERSION_foo macros inside _mingw.h,
+// which is included from all system headers. Thus we abuse that to detect
+// them.
+#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
#include "backends/taskbar/win32/mingw-compat.h"
#else
+ // We use functionality introduced with Win7 in this file.
+ // To assure that including the respective system headers gives us all
+ // required definitions we set Win7 as minimum version we target.
+ // See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745%28v=vs.85%29.aspx#macros_for_conditional_declarations
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT _WIN32_WINNT_WIN7
+
+ // TODO: We might not need to include this file, the MSDN docs are
+ // not really helpful to decide whether we require it or not.
+ //
+ // Casing of the name is a bit of a mess. MinGW64 seems to use all
+ // lowercase, while MSDN docs suggest "SdkDdkVer.h". We are stuck with
+ // what MinGW64 uses...
+ #include <sdkddkver.h>
+
// We need certain functions that are excluded by default
#undef NONLS
#undef NOICONS
@@ -39,11 +68,6 @@
#if defined(ARRAYSIZE)
#undef ARRAYSIZE
#endif
-
- #if defined(_MSC_VER)
- // Default MSVC headers for ITaskbarList3 and IShellLink
- #include <SDKDDKVer.h>
- #endif
#endif
#include <shlobj.h>
@@ -61,7 +85,7 @@ const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0
Win32TaskbarManager::Win32TaskbarManager(SdlWindow *window) : _window(window), _taskbar(NULL), _count(0), _icon(NULL) {
// Do nothing if not running on Windows 7 or later
- if (!isWin7OrLater())
+ if (!confirmWindowsVersion(10, 0) && !confirmWindowsVersion(6, 1))
return;
CoInitialize(NULL);
@@ -376,14 +400,14 @@ BOOL VerifyVersionInfoFunc(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwType
return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask);
}
-bool Win32TaskbarManager::isWin7OrLater() {
+bool Win32TaskbarManager::confirmWindowsVersion(uint majorVersion, uint minorVersion) {
OSVERSIONINFOEX versionInfo;
DWORDLONG conditionMask = 0;
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- versionInfo.dwMajorVersion = 6;
- versionInfo.dwMinorVersion = 1;
+ versionInfo.dwMajorVersion = majorVersion;
+ versionInfo.dwMinorVersion = minorVersion;
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
diff --git a/backends/taskbar/win32/win32-taskbar.h b/backends/taskbar/win32/win32-taskbar.h
index a6d1b49213..a5c024b21b 100644
--- a/backends/taskbar/win32/win32-taskbar.h
+++ b/backends/taskbar/win32/win32-taskbar.h
@@ -64,7 +64,7 @@ private:
Common::String getIconPath(Common::String target);
// Helper functions
- bool isWin7OrLater();
+ bool confirmWindowsVersion(uint majorVersion, uint minorVersion);
LPWSTR ansiToUnicode(const char *s);
HWND getHwnd();
};