diff options
author | Thierry Crozat | 2014-01-26 20:40:36 +0000 |
---|---|---|
committer | Thierry Crozat | 2014-02-23 21:54:47 +0000 |
commit | 6d7fcdd2b544fa4eb29988bd627af94aa8238d6c (patch) | |
tree | 0636a564e386edaff384bd9bdc47266bc8dbcd74 /backends/taskbar | |
parent | 6673472a2266373a96959c741dc922b40e975179 (diff) | |
download | scummvm-rg350-6d7fcdd2b544fa4eb29988bd627af94aa8238d6c.tar.gz scummvm-rg350-6d7fcdd2b544fa4eb29988bd627af94aa8238d6c.tar.bz2 scummvm-rg350-6d7fcdd2b544fa4eb29988bd627af94aa8238d6c.zip |
OSX: Implement TaskbarManager for Mac OS X
This implements count badge, progress bar, and icon overlay.
It uses the NSDockTile API which is available since OS X 10.5.
The code compiles and run on older system but without doing
anything.
Diffstat (limited to 'backends/taskbar')
-rw-r--r-- | backends/taskbar/macosx/macosx-taskbar.h | 57 | ||||
-rw-r--r-- | backends/taskbar/macosx/macosx-taskbar.mm | 238 |
2 files changed, 295 insertions, 0 deletions
diff --git a/backends/taskbar/macosx/macosx-taskbar.h b/backends/taskbar/macosx/macosx-taskbar.h new file mode 100644 index 0000000000..5d5b9d02cd --- /dev/null +++ b/backends/taskbar/macosx/macosx-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. + * + */ + +#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 notifyError(); + virtual void clearError(); + +private: + Common::String getIconPath(const Common::String&); + + void initApplicationIconView(); + void clearApplicationIconView(); + + void initOverlayIconView(); + void clearOverlayIconView(); + + double _progress; +}; + +#endif + +#endif // BACKEND_MACOSX_TASKBAR_H diff --git a/backends/taskbar/macosx/macosx-taskbar.mm b/backends/taskbar/macosx/macosx-taskbar.mm new file mode 100644 index 0000000000..ae087dfb85 --- /dev/null +++ b/backends/taskbar/macosx/macosx-taskbar.mm @@ -0,0 +1,238 @@ +/* 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. + * + */ + +// 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) + +// 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" + +#include <AppKit/NSApplication.h> +#include <AppKit/NSImage.h> +#include <Foundation/NSString.h> +#include <AppKit/NSImageView.h> +#include <AppKit/NSColor.h> +#include <AppKit/NSBezierPath.h> +#include <CoreFoundation/CFString.h> + +id _dockTile; +NSImageView *_applicationIconView; +NSImageView *_overlayIconView; + +// 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) { + if ([NSApp respondsToSelector:@selector(dockTile)]) + _dockTile = [NSApp dockTile]; + _applicationIconView = nil; + _overlayIconView = nil; +} + +MacOSXTaskbarManager::~MacOSXTaskbarManager() { + clearApplicationIconView(); +} + +void MacOSXTaskbarManager::initApplicationIconView() { + if (_dockTile == nil) + return; + if (_applicationIconView == nil) { + _applicationIconView = [[NSImageView alloc] init]; + [_applicationIconView setImage:[NSApp applicationIconImage]]; + [_dockTile performSelector:@selector(setContentView:) withObject:_applicationIconView]; + } +} + +void MacOSXTaskbarManager::clearApplicationIconView() { + if (_dockTile == nil) + return; + [_dockTile performSelector:@selector(setContentView:) withObject:nil]; + [_applicationIconView release]; + _applicationIconView = nil; +} + +void MacOSXTaskbarManager::initOverlayIconView() { + if (_dockTile == nil) + 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 (_dockTile == nil) + return; + + if (name.empty()) { + clearOverlayIconView(); + [_dockTile performSelector:@selector(display)]; + return; + } + + Common::String path = getIconPath(name); + if (path.empty()) + return; + + initOverlayIconView(); + + CFStringRef imageFile = CFStringCreateWithCString(0, path.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 (_dockTile == nil) + 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 (_dockTile == nil) + 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 (_dockTile == nil) + return; + + if (count > 0) + [_dockTile performSelector:@selector(setBadgeLabel:) withObject:[NSString stringWithFormat:@"%d", count]]; + else + [_dockTile performSelector:@selector(setBadgeLabel:) withObject:nil]; +} + +void MacOSXTaskbarManager::notifyError() { + if (_dockTile == nil) + 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 (_dockTile == nil) + return; + + clearOverlayIconView(); + [_dockTile performSelector:@selector(display)]; + return; +} + +Common::String MacOSXTaskbarManager::getIconPath(const 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 + ".png"); + TRY_ICON_PATH(iconsPath + "/" + ConfMan.get("gameid") + ".png"); + TRY_ICON_PATH(iconsPath + "/icons/" + target + ".png"); + TRY_ICON_PATH(iconsPath + "/icons/" + ConfMan.get("gameid") + ".png"); + } + + if (!extraPath.empty()) { + TRY_ICON_PATH(extraPath + "/" + target + ".png"); + TRY_ICON_PATH(extraPath + "/" + ConfMan.get("gameid") + ".png"); + TRY_ICON_PATH(extraPath + "/icons/" + target + ".png"); + TRY_ICON_PATH(extraPath + "/icons/" + ConfMan.get("gameid") + ".png"); + } + + return ""; +} + + +#endif |