aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStéphane Marks2025-11-20 12:54:40 -0500
committerMichael Albinus2025-12-21 12:55:10 +0100
commitf5f2306fc1d4370730fdcdd91c8acdf0d7930487 (patch)
tree01f1ed23cf987c424dc3eb54948a19deef7ee81b /src
parent28a2a7d811a9d99de7103a3be4e1dd3e3a59c813 (diff)
downloademacs-f5f2306fc1d4370730fdcdd91c8acdf0d7930487.tar.gz
emacs-f5f2306fc1d4370730fdcdd91c8acdf0d7930487.zip
System GUI taskbar and progress reporter hooks (bug#79859)
Implement system GUI taskbar/dock/launcher icon badge, icon progress indicator, icon attention alert features for D-Bus platforms (tested on KDE and GNOME), NS (macOS/GNUstep), MS-Windows. Add 'progress-reporter-update-functions' abnormal hook to facilitate taskbar progress display, and other custom progress reporters. The default function list is 'progress-reporter-echo-area' which is backward compatible. * lisp/subr.el (progress-reporter-update-functions): New defvar. (progress-reporter-echo-area): New defun. (progress-reporter-do-update): Run progress-reporter-update-functions for both numerical and pulsing reporters. (progress-reporter-done): Run progress-reporter-done-functions. * lisp/system-taskbar.el: New file. * src/nsfns.m (Fns_badge, Fns_progress_indicator) (Fns_request_user_attention): New function. (syms_of_nsfns): Add defsubr Sns_badge, Sns_request_user_attention, Sns_progress_indicator. Add DEFSYM Qinformational, Qcritical. * src/w32fns.c (rgb_list_to_colorref, Fw32_badge) (Fw32_request_user_attention, Fw32_progress_indicator): New function. (syms_of_w32fns): Add defsubr Sw32_badge, Sw32_progress_indicator, Sw32_request_user_attention. Add DEFSYM Qinformational, Qcritical. * doc/emacs/frames.texi: User documentation. * doc/lispref/os.texi: Programmer documentation. * etc/NEWS: Announce system-taskbar-mode. Announce progress reporter callback enhancements.
Diffstat (limited to 'src')
-rw-r--r--src/nsfns.m128
-rw-r--r--src/w32fns.c327
2 files changed, 455 insertions, 0 deletions
diff --git a/src/nsfns.m b/src/nsfns.m
index 3528c4acd50..2b94b32e59c 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -3674,6 +3674,129 @@ DEFUN ("ns-show-character-palette",
3674 return Qnil; 3674 return Qnil;
3675} 3675}
3676 3676
3677DEFUN ("ns-badge", Fns_badge, Sns_badge, 1, 1, 0,
3678 doc: /* Set the app icon badge to BADGE.
3679BADGE should be a string short enough to display nicely in the short
3680space intended for badges.
3681If BADGE is nil, clear the app badge. */)
3682 (Lisp_Object badge)
3683{
3684 block_input ();
3685 if (NILP (badge))
3686 [[NSApp dockTile] setBadgeLabel: nil];
3687 else
3688 {
3689 CHECK_STRING (badge);
3690 [[NSApp dockTile] setBadgeLabel:
3691 [NSString stringWithUTF8String: SSDATA (badge)]];
3692 }
3693 unblock_input ();
3694 return Qnil;
3695}
3696
3697/* Use -1 to indicate no active request. */
3698static NSInteger ns_request_user_attention_id = -1;
3699
3700DEFUN ("ns-request-user-attention",
3701 Fns_request_user_attention,
3702 Sns_request_user_attention,
3703 1, 1, 0,
3704 doc: /* Bounce the app dock icon to request user attention.
3705If URGENCY nil, cancel the outstanding request, if any.
3706If URGENCY is the symbol `informational', bouncing lasts a few seconds.
3707If URGENCY is the symbol `critical', bouncing lasts until Emacs is
3708focused. */)
3709 (Lisp_Object urgency)
3710{
3711 block_input ();
3712 if (ns_request_user_attention_id != -1)
3713 {
3714 [NSApp cancelUserAttentionRequest: ns_request_user_attention_id];
3715 ns_request_user_attention_id = -1;
3716 }
3717 if (!NILP (urgency) && SYMBOLP (urgency))
3718 {
3719 if (EQ (urgency, Qinformational))
3720 ns_request_user_attention_id = [NSApp requestUserAttention:
3721 NSInformationalRequest];
3722 else if (EQ (urgency, Qcritical))
3723 ns_request_user_attention_id = [NSApp requestUserAttention:
3724 NSCriticalRequest];
3725 }
3726 unblock_input ();
3727 return Qnil;
3728}
3729
3730DEFUN ("ns-progress-indicator",
3731 Fns_progress_indicator,
3732 Sns_progress_indicator,
3733 1, 1, 0,
3734 doc: /* Bounce the app dock icon to request user attention.
3735PROGRESS is a float between 0.0 and 1.0.
3736If PROGRESS is nil, remove the progress indicator. */)
3737 (Lisp_Object progress)
3738{
3739 block_input ();
3740 NSDockTile *dock_tile = [NSApp dockTile];
3741 /* Use NSLevelIndicator with reliable redraws, not NSProgressIndicator. */
3742 NSLevelIndicator *level_indicator;
3743 /* Reuse the indicator subview or create one. */
3744 if (dock_tile.contentView
3745 && [[dock_tile.contentView subviews] count] > 0
3746 && [[[dock_tile.contentView subviews] lastObject]
3747 isKindOfClass:[NSLevelIndicator class]])
3748 level_indicator =
3749 (NSLevelIndicator *)[[[dock_tile contentView] subviews] lastObject];
3750 else
3751 {
3752 if (!dock_tile.contentView)
3753 {
3754 NSImageView* image_view = [[NSImageView alloc] init];
3755 [image_view setImage: [NSApp applicationIconImage]];
3756 [dock_tile setContentView: image_view];
3757 }
3758 /* Set width to the width of the application icon, and height to
3759 % of the icon height to respect scaled icons. */
3760 float width = [[NSApp applicationIconImage] size].width;
3761 float height = 0.10 * [[NSApp applicationIconImage] size].height;
3762 level_indicator =
3763 [[NSLevelIndicator alloc] initWithFrame:
3764 NSMakeRect (0.0, 0.0,
3765 width, height)];
3766 [level_indicator setWantsLayer: YES]; /* Performance. */
3767 [level_indicator setEnabled: NO]; /* Ignore mouse input. */
3768 [level_indicator setLevelIndicatorStyle:
3769 NSLevelIndicatorStyleContinuousCapacity];
3770 /* Match NSProgressIndicator color. */
3771 [level_indicator setFillColor: [NSColor controlAccentColor]];
3772 [level_indicator setMinValue: 0.0];
3773 [level_indicator setMaxValue: 1.0];
3774 /* The contentView takes ownership. */
3775 [dock_tile.contentView addSubview: level_indicator];
3776 }
3777 double progress_value;
3778 BOOL hide = (NILP (progress)
3779 || (!NILP (progress) && !(FLOATP (progress))));
3780 if (!hide)
3781 {
3782 progress_value = XFLOAT_DATA (progress);
3783 hide = (progress_value < 0.0 || progress_value > 1.0);
3784 }
3785 if (hide)
3786 {
3787 [level_indicator setDoubleValue: 0.0];
3788 [level_indicator setHidden: YES];
3789 }
3790 else
3791 {
3792 [level_indicator setDoubleValue: progress_value];
3793 [level_indicator setHidden: NO];
3794 }
3795 [dock_tile display];
3796 unblock_input ();
3797 return Qnil;
3798}
3799
3677#ifdef NS_IMPL_COCOA 3800#ifdef NS_IMPL_COCOA
3678 3801
3679DEFUN ("ns-send-items", 3802DEFUN ("ns-send-items",
@@ -3957,6 +4080,9 @@ The default value is t. */);
3957 defsubr (&Sns_set_mouse_absolute_pixel_position); 4080 defsubr (&Sns_set_mouse_absolute_pixel_position);
3958 defsubr (&Sns_mouse_absolute_pixel_position); 4081 defsubr (&Sns_mouse_absolute_pixel_position);
3959 defsubr (&Sns_show_character_palette); 4082 defsubr (&Sns_show_character_palette);
4083 defsubr (&Sns_badge);
4084 defsubr (&Sns_request_user_attention);
4085 defsubr (&Sns_progress_indicator);
3960#ifdef NS_IMPL_COCOA 4086#ifdef NS_IMPL_COCOA
3961 defsubr (&Sns_send_items); 4087 defsubr (&Sns_send_items);
3962#endif 4088#endif
@@ -4023,4 +4149,6 @@ The default value is t. */);
4023 DEFSYM (Qassq_delete_all, "assq-delete-all"); 4149 DEFSYM (Qassq_delete_all, "assq-delete-all");
4024 DEFSYM (Qrun_at_time, "run-at-time"); 4150 DEFSYM (Qrun_at_time, "run-at-time");
4025 DEFSYM (Qx_hide_tip, "x-hide-tip"); 4151 DEFSYM (Qx_hide_tip, "x-hide-tip");
4152 DEFSYM (Qinformational, "informational");
4153 DEFSYM (Qcritical, "critical");
4026} 4154}
diff --git a/src/w32fns.c b/src/w32fns.c
index f7bf6110991..b1f5799d1c5 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -35,7 +35,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
35#include <c-ctype.h> 35#include <c-ctype.h>
36 36
37#define COBJMACROS /* Ask for C definitions for COM. */ 37#define COBJMACROS /* Ask for C definitions for COM. */
38#if !defined MINGW_W64 && !defined CYGWIN
39# define INITGUID
40#endif
41#include <initguid.h>
38#include <shlobj.h> 42#include <shlobj.h>
43#include <shobjidl.h>
39#include <oleidl.h> 44#include <oleidl.h>
40#include <objidl.h> 45#include <objidl.h>
41#include <ole2.h> 46#include <ole2.h>
@@ -232,6 +237,8 @@ typedef struct Emacs_GESTURECONFIG
232typedef BOOL (WINAPI * SetGestureConfig_proc) (HWND, DWORD, UINT, 237typedef BOOL (WINAPI * SetGestureConfig_proc) (HWND, DWORD, UINT,
233 Emacs_PGESTURECONFIG, UINT); 238 Emacs_PGESTURECONFIG, UINT);
234 239
240typedef BOOL (WINAPI * FlashWindowEx_Proc) (PFLASHWINFO pfwi);
241
235static TrackMouseEvent_Proc track_mouse_event_fn = NULL; 242static TrackMouseEvent_Proc track_mouse_event_fn = NULL;
236static ImmGetCompositionString_Proc get_composition_string_fn = NULL; 243static ImmGetCompositionString_Proc get_composition_string_fn = NULL;
237static ImmGetContext_Proc get_ime_context_fn = NULL; 244static ImmGetContext_Proc get_ime_context_fn = NULL;
@@ -254,6 +261,7 @@ static WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn
254static WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL; 261static WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL;
255static RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL; 262static RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL;
256static SetGestureConfig_proc SetGestureConfig_fn = NULL; 263static SetGestureConfig_proc SetGestureConfig_fn = NULL;
264static FlashWindowEx_Proc flash_window_ex_fn = NULL;
257 265
258extern AppendMenuW_Proc unicode_append_menu; 266extern AppendMenuW_Proc unicode_append_menu;
259 267
@@ -11008,6 +11016,313 @@ Return -1 if the required system API is not available or fails. */)
11008 11016
11009#endif 11017#endif
11010 11018
11019
11020#ifdef WINDOWSNT
11021
11022/***********************************************************************
11023 Taskbar Indicators
11024 ***********************************************************************/
11025
11026#ifndef MINGW_W64
11027 /* mingw.org's MinGW doesn't have this stuff. */
11028 DEFINE_GUID(CLSID_TaskbarList, 0x56fdf344, 0xfd6d, 0x11d0, 0x95,0x8a, 0x00,0x60,0x97,0xc9,0xa0,0x90);
11029 DEFINE_GUID(IID_ITaskbarList3, 0xea1afb91, 0x9e28, 0x4b86, 0x90,0xe9, 0x9e,0x9f,0x8a,0x5e,0xef,0xaf);
11030#endif
11031
11032DEFUN ("w32-badge",
11033 Fw32_badge,
11034 Sw32_badge,
11035 3, 3, 0,
11036 doc: /* Display a taskbar icon overlay image on the selected frame.
11037BADGE is a string. If BADGE is nil, remove the overlay. Do nothing if
11038Windows does not support the ITaskbarList3 interface and return nil,
11039otherwise return t. Do nothing if the selected frame is not (yet)
11040associated with a window handle. BACKGROUND and FOREGROUND are RGB
11041triplet strings of the form \"#RRGGBB\". */)
11042 (Lisp_Object badge, Lisp_Object background, Lisp_Object foreground)
11043{
11044 struct frame *sf = SELECTED_FRAME ();
11045 HWND hwnd = NULL;
11046
11047 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
11048 hwnd = FRAME_W32_WINDOW (sf);
11049
11050 if (hwnd == NULL)
11051 return Qnil;
11052
11053 CoInitialize (NULL);
11054 ITaskbarList3 *task_bar_list = NULL;
11055 HRESULT r = CoCreateInstance(&CLSID_TaskbarList,
11056 NULL,
11057 CLSCTX_INPROC_SERVER,
11058 &IID_ITaskbarList3,
11059 (void **)&task_bar_list);
11060 if (r != S_OK)
11061 return Qnil;
11062
11063 if (!NILP (badge) && STRINGP (badge)
11064 && STRINGP (background) && STRINGP (foreground))
11065 {
11066 COLORREF bg_rgb;
11067 COLORREF fg_rgb;
11068 unsigned short r, g, b;
11069 if (parse_color_spec (SSDATA (background), &r, &g, &b))
11070 bg_rgb = RGB (r, b, b);
11071 else
11072 return Qnil;
11073 if (parse_color_spec (SSDATA (foreground), &r, &g, &b))
11074 fg_rgb = RGB (r, b, b);
11075 else
11076 return Qnil;
11077
11078 /* Prepare a string for drawing and as alt-text. */
11079 Lisp_Object badge_utf8 = ENCODE_UTF_8 (badge);
11080 int wide_len = pMultiByteToWideChar (CP_UTF8, 0,
11081 SSDATA (badge_utf8),
11082 -1, NULL, 0);
11083 wchar_t *badge_w = alloca ((wide_len + 1) * sizeof (wchar_t));
11084 pMultiByteToWideChar (CP_UTF8, 0, SSDATA (badge_utf8), -1,
11085 (LPWSTR) badge_w,
11086 wide_len);
11087
11088 /* Use the small icon size Windows suggests to not hard code 16x16. */
11089 int icon_width = GetSystemMetrics (SM_CXSMICON);
11090 int icon_height = GetSystemMetrics (SM_CXSMICON);
11091
11092 HDC hwnd_dc = GetDC (hwnd);
11093 HDC dc = CreateCompatibleDC (hwnd_dc);
11094
11095 BITMAPV5HEADER bi;
11096 memset (&bi, 0, sizeof (bi));
11097 bi.bV5Size = sizeof (bi);
11098 bi.bV5Width = icon_width;
11099 bi.bV5Height = -icon_height; /* Negative for a top-down DIB. */
11100 bi.bV5Planes = 1;
11101 bi.bV5BitCount = 32;
11102 bi.bV5Compression = BI_BITFIELDS; /* Enable the masks below. */
11103 bi.bV5RedMask = 0x00FF0000;
11104 bi.bV5GreenMask = 0x0000FF00;
11105 bi.bV5BlueMask = 0x000000FF;
11106 bi.bV5AlphaMask = 0xFF000000;
11107
11108 DWORD *bitmap_pixels;
11109 HBITMAP bitmap = CreateDIBSection (dc, (BITMAPINFO *) &bi,
11110 DIB_RGB_COLORS,
11111 (void **) &bitmap_pixels,
11112 NULL, 0);
11113 HGDIOBJ old_bitmap = SelectObject(dc, bitmap);
11114
11115 /* Draw a circle filled with bg. */
11116 HBRUSH bg_brush = CreateSolidBrush (bg_rgb);
11117 HGDIOBJ old_brush = SelectObject (dc, bg_brush);
11118 Ellipse (dc, 0, 0, icon_width, icon_height);
11119 SelectObject (dc, old_brush);
11120 DeleteObject (bg_brush);
11121
11122 /* Derive a font scaled to fit the icon. First find the system's
11123 base font. Then scale it to fit icon_height. */
11124 HFONT base_font;
11125 BOOL clean_up_base_font = FALSE;
11126 if (system_parameters_info_w_fn)
11127 {
11128 NONCLIENTMETRICS ncm;
11129 memset (&ncm, 0, sizeof (ncm));
11130 ncm.cbSize = sizeof (ncm);
11131 SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof (ncm), &ncm, 0);
11132 base_font = CreateFontIndirect (&ncm.lfSmCaptionFont);
11133 clean_up_base_font = TRUE;
11134 }
11135 else
11136 base_font = (HFONT) GetStockObject (DEFAULT_GUI_FONT);
11137 if (clean_up_base_font)
11138 DeleteObject (base_font);
11139
11140 LOGFONT lf;
11141 GetObject (base_font, sizeof (lf), &lf);
11142 lf.lfWeight = FW_BOLD;
11143 lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
11144 /* ClearType quality needs opqaue, but we draw transparent. */
11145 lf.lfQuality = ANTIALIASED_QUALITY;
11146 /* Negative lfHeight indicates pixel units vs. positive in points.
11147 Use the LOGPIXELSY px/in of the primary monitor. */
11148 lf.lfHeight = -MulDiv(icon_height / 2, /* Fit ~3 chars. */
11149 72,
11150 GetDeviceCaps (GetDC (NULL), LOGPIXELSY));
11151 /* Ensure lfHeight pixel interpretation. */
11152 int old_map_mode = SetMapMode (dc, MM_TEXT);
11153 HFONT scaled_font = CreateFontIndirect (&lf);
11154 HGDIOBJ old_font = SelectObject (dc, scaled_font);
11155 SetMapMode (dc, old_map_mode);
11156
11157 /* Draw badge text. */
11158 SetBkMode (dc, TRANSPARENT);
11159 SetTextColor (dc, fg_rgb);
11160 RECT rect;
11161 rect.left = rect.top = 0;
11162 rect.right = icon_width;
11163 rect.bottom = icon_height;
11164 DrawText (dc, SSDATA (badge_utf8),
11165 -1, /* Indicate null-terminated string. */
11166 &rect,
11167 DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP);
11168 SelectObject (dc, old_font);
11169 DeleteObject (scaled_font);
11170
11171 /* Make the circle and its text opaque by setting the alpha
11172 channel on each pixel falling within the circle. */
11173 int circle_center_x = icon_width / 2;
11174 int circle_center_y = icon_height / 2;
11175 int circle_radius = (icon_width < icon_height
11176 ? icon_width
11177 : icon_height) / 2 - 2;
11178 int circle_radius_sq = circle_radius * circle_radius;
11179 DWORD *pixel;
11180 for (int y = 0; y < icon_height; ++y)
11181 for (int x = 0; x < icon_width; ++x)
11182 {
11183 int dx = x - circle_center_x;
11184 int dy = y - circle_center_y;
11185 if (dx * dx + dy * dy <= circle_radius_sq)
11186 {
11187 pixel = bitmap_pixels + (y * icon_width + x);
11188 *pixel |= 0xff000000; /* Flip the 0xAARRGGBB alpha channel. */
11189 }
11190 }
11191
11192 /* Dummy monochrome bitmap mask, ignored when the color bitmap has
11193 an alpha channel, but needed to satisfy CreateIconIndirect. */
11194 HBITMAP mask_bitmap = CreateBitmap (icon_width, icon_height, 1, 1, NULL);
11195
11196 /* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createiconindirect
11197 hbmMask and hbmColor members of the ICONINFO structure should
11198 not already be selected into a device context. */
11199 SelectObject (dc, old_bitmap);
11200
11201 ICONINFO icon_info;
11202 memset (&icon_info, 0, sizeof (icon_info));
11203 icon_info.fIcon = TRUE;
11204 icon_info.hbmMask = mask_bitmap;
11205 icon_info.hbmColor = bitmap;
11206
11207 HICON icon = CreateIconIndirect (&icon_info);
11208 task_bar_list->lpVtbl->SetOverlayIcon (task_bar_list, hwnd, icon, badge_w);
11209
11210 DestroyIcon (icon);
11211 DeleteObject (mask_bitmap);
11212 DeleteObject (bitmap);
11213 DeleteDC (dc);
11214 ReleaseDC (hwnd, hwnd_dc);
11215 }
11216 else
11217 task_bar_list->lpVtbl->SetOverlayIcon (task_bar_list, hwnd, NULL, NULL);
11218
11219 task_bar_list->lpVtbl->Release(task_bar_list);
11220 return Qt;
11221}
11222
11223DEFUN ("w32-request-user-attention",
11224 Fw32_request_user_attention,
11225 Sw32_request_user_attention,
11226 1, 1, 0,
11227 doc: /* Flash the selected frame's taskbar icon and/or its window.
11228If URGENCY is nil, cancel the request, if any. If URGENCY is the symbol
11229`informational', flash the taskbar icon. If URGENCY is the symbol
11230`critical', flash the taskbar icon and the frame. Windows stops
11231flashing if the user focuses the frame. Do nothing if Windows does not
11232support FlashWindowEx and return nil, otherwise return t. Do nothing if
11233the frame is not (yet) associated with a window handle. */)
11234 (Lisp_Object urgency)
11235{
11236 if (flash_window_ex_fn == NULL)
11237 return Qnil;
11238
11239 struct frame *sf = SELECTED_FRAME ();
11240 HWND hwnd = NULL;
11241
11242 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
11243 hwnd = FRAME_W32_WINDOW (sf);
11244
11245 if (hwnd == NULL)
11246 return Qnil;
11247
11248 FLASHWINFO flash_info;
11249 flash_info.cbSize = sizeof(flash_info);
11250 flash_info.uCount = 0;
11251 flash_info.dwTimeout = 0;
11252 flash_info.hwnd = hwnd;
11253 if (!NILP (urgency) && SYMBOLP (urgency))
11254 {
11255 /* The intended caller, 'system-taskbar-attention', has an
11256 optional timer to clear the attention indicator so this will
11257 flash until cleared via the timer, or the window comes to the
11258 foreground. For informational attention, flash the tray icon.
11259 For critical attention, flash the tray icon and the window. */
11260 if (EQ (urgency, Qinformational))
11261 flash_info.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
11262 else if (EQ (urgency, Qcritical))
11263 flash_info.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
11264 }
11265 else
11266 flash_info.dwFlags = FLASHW_STOP;
11267
11268 flash_window_ex_fn (&flash_info);
11269 return Qt;
11270}
11271
11272DEFUN ("w32-progress-indicator",
11273 Fw32_progress_indicator,
11274 Sw32_progress_indicator,
11275 1, 1, 0,
11276 doc: /* Show a progress bar on the selected frame's taskbar icon.
11277PROGRESS is a float in the range 0.0 to 1.0. If PROGRESS is nil, remove
11278the progress indicator. Do nothing if Windows does not support the
11279ITaskbarList3 interface and return nil, otherwise return t. Do nothing
11280if the selected frame is not (yet) associated with a window handle */)
11281 (Lisp_Object progress)
11282{
11283 struct frame *sf = SELECTED_FRAME ();
11284 HWND hwnd = NULL;
11285
11286 if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
11287 hwnd = FRAME_W32_WINDOW (sf);
11288
11289 if (hwnd == NULL)
11290 return Qnil;
11291
11292 CoInitialize (NULL);
11293 ITaskbarList3 *task_bar_list = NULL;
11294 HRESULT r = CoCreateInstance(&CLSID_TaskbarList,
11295 NULL,
11296 CLSCTX_INPROC_SERVER,
11297 &IID_ITaskbarList3,
11298 (void **)&task_bar_list);
11299 if (r != S_OK)
11300 return Qnil;
11301
11302 /* Scale task bar progress from 0.0-1.0 to 0-100. */
11303 ULONGLONG adj_progress = 0;
11304 if (!NILP (progress) && FLOATP (progress))
11305 adj_progress = (ULONGLONG) (100.0 *
11306 XFLOAT_DATA (progress));
11307 if (adj_progress > 0)
11308 {
11309 task_bar_list->lpVtbl->SetProgressState (task_bar_list,
11310 hwnd, TBPF_NORMAL);
11311 task_bar_list->lpVtbl->SetProgressValue (task_bar_list,
11312 hwnd, adj_progress, 100);
11313 }
11314 else
11315 {
11316 task_bar_list->lpVtbl->SetProgressState (task_bar_list,
11317 hwnd, TBPF_NOPROGRESS);
11318 }
11319
11320 task_bar_list->lpVtbl->Release(task_bar_list);
11321 return Qt;
11322}
11323
11324#endif /* WINDOWSNT */
11325
11011/*********************************************************************** 11326/***********************************************************************
11012 Initialization 11327 Initialization
11013 ***********************************************************************/ 11328 ***********************************************************************/
@@ -11509,6 +11824,15 @@ keys when IME input is received. */);
11509 DEFSYM (Qcapslock, "capslock"); 11824 DEFSYM (Qcapslock, "capslock");
11510 DEFSYM (Qkp_numlock, "kp-numlock"); 11825 DEFSYM (Qkp_numlock, "kp-numlock");
11511 DEFSYM (Qscroll, "scroll"); 11826 DEFSYM (Qscroll, "scroll");
11827
11828 #ifdef WINDOWSNT
11829 /* Taskbar indicators support. */
11830 defsubr (&Sw32_badge);
11831 defsubr (&Sw32_progress_indicator);
11832 defsubr (&Sw32_request_user_attention);
11833 DEFSYM (Qinformational, "informational");
11834 DEFSYM (Qcritical, "critical");
11835 #endif
11512} 11836}
11513 11837
11514 11838
@@ -11797,6 +12121,9 @@ globals_of_w32fns (void)
11797 SetGestureConfig_fn 12121 SetGestureConfig_fn
11798 = (SetGestureConfig_proc) get_proc_addr (user32_lib, 12122 = (SetGestureConfig_proc) get_proc_addr (user32_lib,
11799 "SetGestureConfig"); 12123 "SetGestureConfig");
12124 flash_window_ex_fn
12125 = (FlashWindowEx_Proc) get_proc_addr (user32_lib,
12126 "FlashWindowEx");
11800 12127
11801 { 12128 {
11802 HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); 12129 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");