From 46a32fe2299a9a9ada08575ca263447981d59c3f Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Tue, 30 Aug 2011 15:41:58 +0100 Subject: [PATCH] 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. --- cmake/modules/GenerateCppResourceFile.cmake | 8 +++--- src/CMakeLists.txt | 10 +++++-- src/UpdateDialogCocoa.h | 2 ++ src/UpdateDialogCocoa.mm | 30 ++++++++++++++++++++ src/resources/mac-dock.png | Bin 0 -> 15331 bytes 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/resources/mac-dock.png diff --git a/cmake/modules/GenerateCppResourceFile.cmake b/cmake/modules/GenerateCppResourceFile.cmake index d8207f5..3f830b2 100644 --- a/cmake/modules/GenerateCppResourceFile.cmake +++ b/cmake/modules/GenerateCppResourceFile.cmake @@ -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() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7752762..c349419 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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) diff --git a/src/UpdateDialogCocoa.h b/src/UpdateDialogCocoa.h index 6d3dde9..a1881d7 100644 --- a/src/UpdateDialogCocoa.h +++ b/src/UpdateDialogCocoa.h @@ -22,6 +22,8 @@ class UpdateDialogCocoa : public UpdateObserver static void releaseAutoreleasePool(void* data); private: + void enableDockIcon(); + UpdateDialogPrivate* d; }; diff --git a/src/UpdateDialogCocoa.mm b/src/UpdateDialogCocoa.mm index a5253fa..0f1758d 100644 --- a/src/UpdateDialogCocoa.mm +++ b/src/UpdateDialogCocoa.mm @@ -1,6 +1,7 @@ #include "UpdateDialogCocoa.h" #include +#include #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; diff --git a/src/resources/mac-dock.png b/src/resources/mac-dock.png new file mode 100644 index 0000000000000000000000000000000000000000..fc0b2e87794710af32256fdeaa6844f61356618b GIT binary patch literal 15331 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