Display an icon for the updater in the dock on Mac when the update dialog is being shown

* Embed the app icon in the updater executable on Mac and
   use it as the application's icon.

 * Transform the application from a background to a foreground app when the
   Mac dialog is shown, so that the dock icon is shown.

 * Forcibly give focus to the updater application so that the progress window
   gains focus when it is shown.

There is a remaining glitch with the application where the icon briefly transforms
back from the app icon to the terminal icon as the application shuts
down.  This presumably happens because the custom icon set on the NSApplication
is reset before the dock icon disappears.
This commit is contained in:
Robert Knight 2011-08-30 15:41:58 +01:00
parent b33170c408
commit 46a32fe229
5 changed files with 44 additions and 6 deletions

View file

@ -14,8 +14,8 @@
#
# INPUT_FILE_TARGET : The name of the target which generates INPUT_FILE
#
function (generate_cpp_resource_file INPUT_FILE CPP_FILE INPUT_FILE_TARGET)
add_custom_command(OUTPUT ${CPP_FILE}
COMMAND xxd -i ${INPUT_FILE} ${CPP_FILE}
DEPENDS ${INPUT_FILE_TARGET})
function (generate_cpp_resource_file TARGET_NAME INPUT_DIR INPUT_FILE CPP_FILE)
add_custom_command(OUTPUT ${CPP_FILE} COMMAND cd ${INPUT_DIR} && xxd -i ${INPUT_FILE} ${CPP_FILE}
DEPENDS ${INPUT_DIR}/${INPUT_FILE})
add_custom_target(${TARGET_NAME} ALL DEPENDS ${CPP_FILE})
endfunction()

View file

@ -36,8 +36,13 @@ set (SOURCES
)
if (APPLE)
set(SOURCES ${SOURCES} StandardDirs.mm UpdateDialogCocoa.mm)
set(MAC_DOCK_ICON_CPP_FILE ${CMAKE_CURRENT_BINARY_DIR}/mac_dock_icon.cpp)
generate_cpp_resource_file(resource_macdockicon
${CMAKE_CURRENT_SOURCE_DIR}/resources
mac-dock.png ${MAC_DOCK_ICON_CPP_FILE})
set(SOURCES ${SOURCES} StandardDirs.mm UpdateDialogCocoa.mm mac_dock_icon.cpp)
endif()
if (WIN32)
set(SOURCES ${SOURCES} UpdateDialogWin32.cpp)
endif()
@ -65,7 +70,8 @@ if (ENABLE_GTK)
# GTK libraries are available
set(GTK_UPDATER_LIB libupdatergtk.so)
set(GTK_BIN_CPP_FILE ${CMAKE_CURRENT_BINARY_DIR}/libupdatergtk.cpp)
generate_cpp_resource_file(${GTK_UPDATER_LIB} ${GTK_BIN_CPP_FILE} updatergtk)
generate_cpp_resource_file(resource_updatergtk ${CMAKE_CURRENT_BINARY_DIR} ${GTK_UPDATER_LIB} ${GTK_BIN_CPP_FILE})
add_dependencies(resource_updatergtk updatergtk)
set(SOURCES ${SOURCES} UpdateDialogGtkWrapper.cpp ${GTK_BIN_CPP_FILE})
set(HEADERS ${HEADERS} UpdateDialogGtkWrapper.h)

View file

@ -22,6 +22,8 @@ class UpdateDialogCocoa : public UpdateObserver
static void releaseAutoreleasePool(void* data);
private:
void enableDockIcon();
UpdateDialogPrivate* d;
};

View file

@ -1,6 +1,7 @@
#include "UpdateDialogCocoa.h"
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#include "AppInfo.h"
#include "Log.h"
@ -89,8 +90,37 @@ UpdateDialogCocoa::~UpdateDialogCocoa()
[d->pool release];
}
extern unsigned char mac_dock_png[];
extern unsigned int mac_dock_png_len;
void UpdateDialogCocoa::enableDockIcon()
{
// convert the application to a foreground application and in
// the process, enable the dock icon
// the reverse transformation is not possible, according to
// http://stackoverflow.com/questions/2832961/is-it-possible-to-hide-the-dock-icon-programmatically
ProcessSerialNumber psn;
GetCurrentProcess(&psn);
TransformProcessType(&psn,kProcessTransformToForegroundApplication);
// loading the icon for the app has to be done after
// changing the process type
NSData* iconData = [NSData dataWithBytes:mac_dock_png length:mac_dock_png_len];
NSImage* iconImage = [[NSImage alloc] initWithData: iconData];
[NSApp setApplicationIconImage:iconImage];
[iconImage release];
}
void UpdateDialogCocoa::init()
{
enableDockIcon();
// make the updater the active application. This does not
// happen automatically because the updater starts as a
// background application
[NSApp activateIgnoringOtherApps:YES];
d->delegate = [[UpdateDialogDelegate alloc] init];
d->delegate->dialog = d;

BIN
src/resources/mac-dock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB