Initial commit
This commit is contained in:
125
backends/taskbar/macosx/dockplugin/dockplugin.m
Normal file
125
backends/taskbar/macosx/dockplugin/dockplugin.m
Normal file
@@ -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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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.app"));
|
||||
NSArray *array = CFPreferencesCopyAppValue(CFSTR("recentGames"), CFSTR("org.scummvm.app"));
|
||||
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];
|
||||
}
|
||||
|
||||
CFRelease(array);
|
||||
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.app"];
|
||||
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
|
||||
55
backends/taskbar/macosx/macosx-taskbar.h
Normal file
55
backends/taskbar/macosx/macosx-taskbar.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_MACOSX_TASKBAR_H
|
||||
#define BACKEND_MACOSX_TASKBAR_H
|
||||
|
||||
#if defined(MACOSX) && defined(USE_TASKBAR)
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/taskbar.h"
|
||||
|
||||
class MacOSXTaskbarManager : public Common::TaskbarManager {
|
||||
public:
|
||||
MacOSXTaskbarManager();
|
||||
virtual ~MacOSXTaskbarManager();
|
||||
|
||||
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 setCount(int count);
|
||||
virtual void addRecent(const Common::String &name, const Common::String &description);
|
||||
virtual void notifyError();
|
||||
virtual void clearError();
|
||||
|
||||
private:
|
||||
void initApplicationIconView();
|
||||
void clearApplicationIconView();
|
||||
|
||||
void initOverlayIconView();
|
||||
void clearOverlayIconView();
|
||||
|
||||
double _progress;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BACKEND_MACOSX_TASKBAR_H
|
||||
280
backends/taskbar/macosx/macosx-taskbar.mm
Normal file
280
backends/taskbar/macosx/macosx-taskbar.mm
Normal file
@@ -0,0 +1,280 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable symbol overrides so that we can use system headers
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(MACOSX) && defined(USE_TASKBAR)
|
||||
|
||||
#include "backends/taskbar/macosx/macosx-taskbar.h"
|
||||
#include "backends/platform/sdl/macosx/macosx-compat.h"
|
||||
#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>
|
||||
#include <CoreFoundation/CFString.h>
|
||||
|
||||
// NSDockTile was introduced with Mac OS X 10.5.
|
||||
// The following makes it possible to compile this feature with the 10.4
|
||||
// SDK (by avoiding any NSDockTile symbol), while letting the same build
|
||||
// use this feature at run-time on 10.5+.
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
|
||||
typedef id NSDockTilePtr;
|
||||
@interface NSApplication(MissingFunction)
|
||||
- (NSDockTilePtr)dockTile;
|
||||
@end
|
||||
#else
|
||||
#include <AppKit/NSDockTile.h>
|
||||
typedef NSDockTile * NSDockTilePtr;
|
||||
#endif
|
||||
|
||||
NSDockTilePtr _dockTile;
|
||||
NSImageView *_applicationIconView;
|
||||
NSImageView *_overlayIconView;
|
||||
|
||||
BOOL hasDockTile() {
|
||||
if (_dockTile != nil)
|
||||
return YES;
|
||||
if ([NSApp respondsToSelector:@selector(dockTile)])
|
||||
_dockTile = [NSApp dockTile];
|
||||
return _dockTile != nil;
|
||||
}
|
||||
|
||||
// Using a NSProgressIndicator as a sub-view of the NSDockTile view does not work properly.
|
||||
// The progress indicator is grayed out and display no progress. So instead the bar is drawn
|
||||
// manually, which is a bit more work :(
|
||||
|
||||
MacOSXTaskbarManager::MacOSXTaskbarManager() : _progress(-1.0) {
|
||||
_dockTile = nil;
|
||||
_applicationIconView = nil;
|
||||
_overlayIconView = nil;
|
||||
}
|
||||
|
||||
MacOSXTaskbarManager::~MacOSXTaskbarManager() {
|
||||
clearApplicationIconView();
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::initApplicationIconView() {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
if (_applicationIconView == nil) {
|
||||
_applicationIconView = [[NSImageView alloc] init];
|
||||
[_applicationIconView setImage:[NSApp applicationIconImage]];
|
||||
[_dockTile performSelector:@selector(setContentView:) withObject:_applicationIconView];
|
||||
}
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::clearApplicationIconView() {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
[_dockTile performSelector:@selector(setContentView:) withObject:nil];
|
||||
[_applicationIconView release];
|
||||
_applicationIconView = nil;
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::initOverlayIconView() {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
if (_overlayIconView == nil) {
|
||||
const double overlaySize = 0.75;
|
||||
initApplicationIconView();
|
||||
NSSize size = [_applicationIconView frame].size;
|
||||
_overlayIconView = [[NSImageView alloc] initWithFrame:NSMakeRect(size.width * (1.0-overlaySize), 0.0f, size.width * overlaySize, size.height * overlaySize)];
|
||||
[_overlayIconView setImageAlignment:NSImageAlignBottomRight];
|
||||
[_applicationIconView addSubview:_overlayIconView];
|
||||
[_overlayIconView release];
|
||||
}
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::clearOverlayIconView() {
|
||||
if (_progress < 0.0)
|
||||
clearApplicationIconView();
|
||||
else
|
||||
[_overlayIconView removeFromSuperview];
|
||||
_overlayIconView = nil;
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::setOverlayIcon(const Common::String &name, const Common::String &description) {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
if (name.empty()) {
|
||||
clearOverlayIconView();
|
||||
[_dockTile performSelector:@selector(display)];
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Path path = getIconPath(name, ".png");
|
||||
if (path.empty())
|
||||
return;
|
||||
|
||||
initOverlayIconView();
|
||||
|
||||
CFStringRef imageFile = CFStringCreateWithCString(0, path.toString(Common::Path::kNativeSeparator).c_str(), kCFStringEncodingASCII);
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
|
||||
[_overlayIconView setImage:image];
|
||||
[image release];
|
||||
CFRelease(imageFile);
|
||||
|
||||
[_dockTile performSelector:@selector(display)];
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::setProgressValue(int completed, int total) {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
if (total > 0)
|
||||
_progress = (double)completed / (double)total;
|
||||
else if (_progress < 0)
|
||||
_progress = 0.0;
|
||||
|
||||
NSImage *mainIcon = [[NSApp applicationIconImage] copy];
|
||||
double barSize = [mainIcon size].width;
|
||||
double progressSize = barSize * _progress;
|
||||
[mainIcon lockFocus];
|
||||
[[NSColor colorWithDeviceRed:(40.0/255.0) green:(120.0/255.0) blue:(255.0/255.0) alpha:0.78] set];
|
||||
[NSBezierPath fillRect:NSMakeRect(0, 0, progressSize, 11)];
|
||||
[[NSColor colorWithDeviceRed:(241.0/255.0) green:(241.0/255.0) blue:(241.0/255.0) alpha:0.78] set];
|
||||
[NSBezierPath fillRect:NSMakeRect(progressSize, 0, barSize-progressSize, 11)];
|
||||
[mainIcon unlockFocus];
|
||||
|
||||
initApplicationIconView();
|
||||
[_applicationIconView setImage:mainIcon];
|
||||
[mainIcon release];
|
||||
|
||||
[_dockTile performSelector:@selector(display)];
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::setProgressState(TaskbarProgressState state) {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
// Only support two states: visible and not visible.
|
||||
if (state == kTaskbarNoProgress) {
|
||||
_progress = -1.0;
|
||||
if (_overlayIconView == nil)
|
||||
clearApplicationIconView();
|
||||
else if (_applicationIconView != nil)
|
||||
[_applicationIconView setImage:[NSApp applicationIconImage]];
|
||||
return;
|
||||
}
|
||||
|
||||
setProgressValue(-1, -1);
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::setCount(int count) {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
if (count > 0)
|
||||
[_dockTile performSelector:@selector(setBadgeLabel:) withObject:[NSString stringWithFormat:@"%d", count]];
|
||||
else
|
||||
[_dockTile performSelector:@selector(setBadgeLabel:) withObject:nil];
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::notifyError() {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
// NSImageNameCaution was introduced in 10.6.
|
||||
// For compatibility with older systems we should use something else (e.g. overlay label
|
||||
// or our own icon).
|
||||
//initOverlayIconView();
|
||||
//[_overlayIconView setImage:[NSImage imageNamed:NSImageNameCaution]];
|
||||
//[_dockTile performSelector:@selector(display)];
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::clearError() {
|
||||
if (!hasDockTile())
|
||||
return;
|
||||
|
||||
clearOverlayIconView();
|
||||
[_dockTile performSelector:@selector(display)];
|
||||
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 (!hasDockTile())
|
||||
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::Path iconPath = getIconPath(name, ".png");
|
||||
if (!iconPath.empty()) {
|
||||
CFStringRef icon = CFStringCreateWithCString(0, iconPath.toString(Common::Path::kNativeSeparator).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 objectForKey:@"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
|
||||
117
backends/taskbar/unity/unity-taskbar.cpp
Normal file
117
backends/taskbar/unity/unity-taskbar.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(POSIX) && defined(USE_TASKBAR) && defined(USE_UNITY)
|
||||
|
||||
#define GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "backends/taskbar/unity/unity-taskbar.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include <unity.h>
|
||||
|
||||
UnityTaskbarManager::UnityTaskbarManager() {
|
||||
/*
|
||||
* Deprecated in Glib >= 2.36.0
|
||||
*/
|
||||
if (!glib_check_version(2, 36, 0)) {
|
||||
g_type_init();
|
||||
}
|
||||
|
||||
_loop = g_main_loop_new(NULL, FALSE);
|
||||
|
||||
_launcher = unity_launcher_entry_get_for_desktop_id("org.scummvm.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);
|
||||
// fall through
|
||||
|
||||
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
|
||||
54
backends/taskbar/unity/unity-taskbar.h
Normal file
54
backends/taskbar/unity/unity-taskbar.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_UNITY_TASKBAR_H
|
||||
#define BACKEND_UNITY_TASKBAR_H
|
||||
|
||||
#if defined(POSIX) && defined(USE_TASKBAR) && defined(USE_UNITY)
|
||||
|
||||
#include "common/events.h"
|
||||
#include "common/str.h"
|
||||
#include "common/taskbar.h"
|
||||
|
||||
typedef struct _GMainLoop GMainLoop;
|
||||
typedef struct _UnityLauncherEntry UnityLauncherEntry;
|
||||
|
||||
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
|
||||
150
backends/taskbar/win32/mingw-compat.h
Normal file
150
backends/taskbar/win32/mingw-compat.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// 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://github.com/colomboe/EcWin7)
|
||||
|
||||
#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>
|
||||
#include <shlguid.h>
|
||||
#define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK
|
||||
|
||||
extern const GUID CLSID_ShellLink;
|
||||
|
||||
// Shard enumeration value
|
||||
#define SHARD_LINK 0x00000006
|
||||
|
||||
// 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;
|
||||
|
||||
private:
|
||||
~IPropertyStore();
|
||||
};
|
||||
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;
|
||||
|
||||
private:
|
||||
~ITaskbarList3();
|
||||
};
|
||||
|
||||
typedef ITaskbarList3 *LPITaskbarList3;
|
||||
|
||||
#endif // __MINGW32__
|
||||
#endif // __GNUC__
|
||||
#endif // WIN32
|
||||
|
||||
#endif // BACKEND_WIN32_TASKBAR_MINGW_H
|
||||
343
backends/taskbar/win32/win32-taskbar.cpp
Normal file
343
backends/taskbar/win32/win32-taskbar.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// For _tcscpy
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
|
||||
|
||||
// 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)
|
||||
|
||||
// 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
|
||||
// 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://docs.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers#macros-for-conditional-declarations
|
||||
#include <sdkddkver.h>
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WIN7
|
||||
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "backends/taskbar/win32/win32-taskbar.h"
|
||||
#include "backends/platform/sdl/win32/win32-window.h"
|
||||
#include "backends/platform/sdl/win32/win32_wrapper.h"
|
||||
|
||||
#include "common/textconsole.h"
|
||||
|
||||
// System.Title property key, values taken from https://docs.microsoft.com/en-us/windows/win32/properties/props-system-title
|
||||
const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 };
|
||||
|
||||
Win32TaskbarManager::Win32TaskbarManager(SdlWindow_Win32 *window) : _window(window), _taskbar(nullptr), _count(0), _icon(nullptr) {
|
||||
CoInitialize(nullptr);
|
||||
|
||||
// Do nothing if not running on Windows 7 or later
|
||||
if (!Win32::confirmWindowsVersion(6, 1))
|
||||
return;
|
||||
|
||||
// Try creating instance (on fail, _taskbar will contain NULL)
|
||||
HRESULT hr = CoCreateInstance(CLSID_TaskbarList,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_ITaskbarList3,
|
||||
reinterpret_cast<void **> (&(_taskbar)));
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Initialize taskbar object
|
||||
if (FAILED(_taskbar->HrInit())) {
|
||||
_taskbar->Release();
|
||||
_taskbar = nullptr;
|
||||
}
|
||||
} else {
|
||||
warning("[Win32TaskbarManager::init] Cannot create taskbar instance");
|
||||
}
|
||||
}
|
||||
|
||||
Win32TaskbarManager::~Win32TaskbarManager() {
|
||||
if (_taskbar)
|
||||
_taskbar->Release();
|
||||
_taskbar = nullptr;
|
||||
|
||||
if (_icon)
|
||||
DestroyIcon(_icon);
|
||||
|
||||
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 == nullptr)
|
||||
return;
|
||||
|
||||
if (name.empty()) {
|
||||
_taskbar->SetOverlayIcon(_window->getHwnd(), nullptr, L"");
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute full icon path
|
||||
Common::Path iconPath = getIconPath(name, ".ico");
|
||||
if (iconPath.empty())
|
||||
return;
|
||||
|
||||
TCHAR *tIconPath = Win32::stringToTchar(iconPath.toString(Common::Path::kNativeSeparator));
|
||||
HICON pIcon = (HICON)::LoadImage(nullptr, tIconPath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
|
||||
free(tIconPath);
|
||||
if (!pIcon) {
|
||||
warning("[Win32TaskbarManager::setOverlayIcon] Cannot load icon!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Sets the overlay icon
|
||||
LPWSTR desc = Win32::ansiToUnicode(description.c_str());
|
||||
_taskbar->SetOverlayIcon(_window->getHwnd(), pIcon, desc);
|
||||
|
||||
DestroyIcon(pIcon);
|
||||
|
||||
free(desc);
|
||||
}
|
||||
|
||||
void Win32TaskbarManager::setProgressValue(int completed, int total) {
|
||||
if (_taskbar == nullptr)
|
||||
return;
|
||||
|
||||
_taskbar->SetProgressValue(_window->getHwnd(), completed, total);
|
||||
}
|
||||
|
||||
void Win32TaskbarManager::setProgressState(TaskbarProgressState state) {
|
||||
if (_taskbar == nullptr)
|
||||
return;
|
||||
|
||||
_taskbar->SetProgressState(_window->getHwnd(), (TBPFLAG)state);
|
||||
}
|
||||
|
||||
void Win32TaskbarManager::setCount(int count) {
|
||||
if (_taskbar == nullptr)
|
||||
return;
|
||||
|
||||
if (count == 0) {
|
||||
_taskbar->SetOverlayIcon(_window->getHwnd(), nullptr, L"");
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: This isn't really nice and could use a cleanup.
|
||||
// The only good thing is that it doesn't use GDI+
|
||||
// and thus does not have a dependency on it,
|
||||
// with the downside of being a lot more ugly.
|
||||
// Maybe replace it by a Graphic::Surface, use
|
||||
// ScummVM font drawing and extract the contents at
|
||||
// the end?
|
||||
|
||||
if (_count != count || _icon == nullptr) {
|
||||
// Cleanup previous icon
|
||||
_count = count;
|
||||
if (_icon)
|
||||
DestroyIcon(_icon);
|
||||
|
||||
Common::String countString = (count < 100 ? Common::String::format("%d", count) : "9+");
|
||||
|
||||
// Create transparent background
|
||||
BITMAPV5HEADER bi;
|
||||
ZeroMemory(&bi, sizeof(BITMAPV5HEADER));
|
||||
bi.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi.bV5Width = 16;
|
||||
bi.bV5Height = 16;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_RGB;
|
||||
// Set 32 BPP alpha format
|
||||
bi.bV5RedMask = 0x00FF0000;
|
||||
bi.bV5GreenMask = 0x0000FF00;
|
||||
bi.bV5BlueMask = 0x000000FF;
|
||||
bi.bV5AlphaMask = 0xFF000000;
|
||||
|
||||
// Get DC
|
||||
HDC hdc;
|
||||
hdc = GetDC(nullptr);
|
||||
HDC hMemDC = CreateCompatibleDC(hdc);
|
||||
ReleaseDC(nullptr, hdc);
|
||||
|
||||
// Create a bitmap mask
|
||||
HBITMAP hBitmapMask = CreateBitmap(16, 16, 1, 1, nullptr);
|
||||
|
||||
// Create the DIB section with an alpha channel
|
||||
void *lpBits;
|
||||
HBITMAP hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, nullptr, 0);
|
||||
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
|
||||
|
||||
// Load the icon background
|
||||
HICON hIconBackground = LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(1002 /* IDI_COUNT */));
|
||||
DrawIconEx(hMemDC, 0, 0, hIconBackground, 16, 16, 0, nullptr, DI_NORMAL);
|
||||
DeleteObject(hIconBackground);
|
||||
|
||||
// Draw the count
|
||||
LOGFONT lFont;
|
||||
memset(&lFont, 0, sizeof(LOGFONT));
|
||||
lFont.lfHeight = 10;
|
||||
lFont.lfWeight = FW_BOLD;
|
||||
lFont.lfItalic = 1;
|
||||
_tcscpy(lFont.lfFaceName, TEXT("Arial"));
|
||||
|
||||
HFONT hFont = CreateFontIndirect(&lFont);
|
||||
SelectObject(hMemDC, hFont);
|
||||
|
||||
RECT rect;
|
||||
SetRect(&rect, 4, 4, 12, 12);
|
||||
SetTextColor(hMemDC, RGB(48, 48, 48));
|
||||
SetBkMode(hMemDC, TRANSPARENT);
|
||||
TCHAR *tCountString = Win32::stringToTchar(countString);
|
||||
DrawText(hMemDC, tCountString, -1, &rect, DT_NOCLIP|DT_CENTER);
|
||||
free(tCountString);
|
||||
|
||||
// Set the text alpha to fully opaque (we consider the data inside the text rect)
|
||||
DWORD *lpdwPixel = (DWORD *)lpBits;
|
||||
for (int x = 3; x < 12; x++) {
|
||||
for(int y = 3; y < 12; y++) {
|
||||
unsigned char *p = (unsigned char *)(lpdwPixel + x * 16 + y);
|
||||
|
||||
if (p[0] != 0 && p[1] != 0 && p[2] != 0)
|
||||
p[3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup DC
|
||||
DeleteObject(hFont);
|
||||
SelectObject(hMemDC, hOldBitmap);
|
||||
DeleteDC(hMemDC);
|
||||
|
||||
// Prepare our new icon
|
||||
ICONINFO ii;
|
||||
ii.fIcon = FALSE;
|
||||
ii.xHotspot = 0;
|
||||
ii.yHotspot = 0;
|
||||
ii.hbmMask = hBitmapMask;
|
||||
ii.hbmColor = hBitmap;
|
||||
|
||||
_icon = CreateIconIndirect(&ii);
|
||||
|
||||
DeleteObject(hBitmap);
|
||||
DeleteObject(hBitmapMask);
|
||||
|
||||
if (!_icon) {
|
||||
warning("[Win32TaskbarManager::setCount] Cannot create icon for count");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the overlay icon
|
||||
LPWSTR desc = Win32::ansiToUnicode(Common::String::format("Found games: %d", count).c_str());
|
||||
_taskbar->SetOverlayIcon(_window->getHwnd(), _icon, desc);
|
||||
free(desc);
|
||||
}
|
||||
|
||||
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 == nullptr)
|
||||
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(nullptr, path, MAX_PATH);
|
||||
|
||||
// Create a shell link.
|
||||
if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC, IID_IShellLinkW, reinterpret_cast<void **> (&link)))) {
|
||||
// Convert game name and description to Unicode.
|
||||
LPWSTR game = Win32::ansiToUnicode(name.c_str());
|
||||
LPWSTR desc = Win32::ansiToUnicode(description.c_str());
|
||||
|
||||
// Set link properties.
|
||||
link->SetPath(path);
|
||||
link->SetArguments(game);
|
||||
|
||||
Common::Path iconPath = getIconPath(name, ".ico");
|
||||
if (iconPath.empty()) {
|
||||
link->SetIconLocation(path, 0); // No game-specific icon available
|
||||
} else {
|
||||
LPWSTR icon = Win32::ansiToUnicode(iconPath.toString(Common::Path::kNativeSeparator).c_str());
|
||||
|
||||
link->SetIconLocation(icon, 0);
|
||||
|
||||
free(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();
|
||||
free(game);
|
||||
free(desc);
|
||||
}
|
||||
}
|
||||
|
||||
void Win32TaskbarManager::notifyError() {
|
||||
setProgressState(Common::TaskbarManager::kTaskbarError);
|
||||
setProgressValue(1, 1);
|
||||
}
|
||||
|
||||
void Win32TaskbarManager::clearError() {
|
||||
setProgressState(kTaskbarNoProgress);
|
||||
}
|
||||
|
||||
#endif
|
||||
58
backends/taskbar/win32/win32-taskbar.h
Normal file
58
backends/taskbar/win32/win32-taskbar.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_WIN32_TASKBAR_H
|
||||
#define BACKEND_WIN32_TASKBAR_H
|
||||
|
||||
#if defined(WIN32) && defined(USE_TASKBAR)
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/taskbar.h"
|
||||
|
||||
class SdlWindow_Win32;
|
||||
struct ITaskbarList3;
|
||||
|
||||
class Win32TaskbarManager final : public Common::TaskbarManager {
|
||||
public:
|
||||
Win32TaskbarManager(SdlWindow_Win32 *window);
|
||||
virtual ~Win32TaskbarManager();
|
||||
|
||||
void setOverlayIcon(const Common::String &name, const Common::String &description) override;
|
||||
void setProgressValue(int completed, int total) override;
|
||||
void setProgressState(TaskbarProgressState state) override;
|
||||
void setCount(int count) override;
|
||||
void addRecent(const Common::String &name, const Common::String &description) override;
|
||||
void notifyError() override;
|
||||
void clearError() override;
|
||||
|
||||
private:
|
||||
SdlWindow_Win32 *_window;
|
||||
|
||||
ITaskbarList3 *_taskbar;
|
||||
|
||||
// Count handling
|
||||
HICON _icon;
|
||||
int _count;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BACKEND_WIN32_TASKBAR_H
|
||||
Reference in New Issue
Block a user