2
* Copyright (c) 2004 Massachusetts Institute of Technology
2
* Copyright (c) 2005 Massachusetts Institute of Technology
4
4
* Permission is hereby granted, free of charge, to any person
5
5
* obtaining a copy of this software and associated documentation
50
52
BOOL notifier_ready = FALSE;
54
khm_boolean notifier_modal_loop = FALSE;
52
56
khui_alert * current_alert = NULL;
58
khui_alert * alert_queue[KHUI_ALERT_QUEUE_MAX];
59
khm_int32 alert_queue_head = 0;
60
khm_int32 alert_queue_tail = 0;
62
int iid_normal = IDI_NOTIFY_NONE;
64
#define is_alert_queue_empty() (alert_queue_head == alert_queue_tail)
65
#define is_alert_queue_full() (((alert_queue_tail + 1) % KHUI_ALERT_QUEUE_MAX) == alert_queue_head)
68
add_to_alert_queue(khui_alert * a) {
69
if (is_alert_queue_full()) return;
70
alert_queue[alert_queue_tail++] = a;
72
alert_queue_tail %= KHUI_ALERT_QUEUE_MAX;
76
del_from_alert_queue(void) {
79
if (is_alert_queue_empty()) return NULL;
80
a = alert_queue[alert_queue_head++];
81
alert_queue_head %= KHUI_ALERT_QUEUE_MAX;
87
peek_alert_queue(void) {
88
if (is_alert_queue_empty()) return NULL;
89
return alert_queue[alert_queue_head];
93
check_for_queued_alerts(void) {
94
if (!is_alert_queue_empty()) {
97
a = peek_alert_queue();
103
if (a->severity == KHERR_ERROR)
105
else if (a->severity == KHERR_WARNING)
108
res = OIC_INFORMATION;
110
hi = LoadImage(0, MAKEINTRESOURCE(res),
111
IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
114
khm_statusbar_set_part(KHUI_SBPART_NOTICE,
119
khm_statusbar_set_part(KHUI_SBPART_NOTICE,
55
125
/* forward dcls */
63
133
alert_show_normal(khui_alert * a);
136
alert_enqueue(khui_alert * a);
138
/* These are defined for APPVER >= 0x501. We are defining them here
139
so that we can build with APPVER = 0x500 and use the same binaries
142
#ifndef NIN_BALLOONSHOW
143
#define NIN_BALLOONSHOW (WM_USER + 2)
146
#ifndef NIN_BALLOONHIDE
147
#define NIN_BALLOONHIDE (WM_USER + 3)
150
#ifndef NIN_BALLOONTIMEOUT
151
#define NIN_BALLOONTIMEOUT (WM_USER + 4)
154
#ifndef NIN_BALLOONUSERCLICK
155
#define NIN_BALLOONUSERCLICK (WM_USER + 5)
65
159
/**********************************************************************
67
161
***********************************************************************
87
181
if(m->type == KMSG_ALERT) {
88
182
/* handle notifier messages */
89
183
switch(m->subtype) {
91
rv = alert_show((khui_alert *) m->vparam);
92
khui_alert_release((khui_alert *) m->vparam);
184
case KMSG_ALERT_SHOW:
185
rv = alert_show((khui_alert *) m->vparam);
186
khui_alert_release((khui_alert *) m->vparam);
189
case KMSG_ALERT_QUEUE:
190
rv = alert_enqueue((khui_alert *) m->vparam);
191
khui_alert_release((khui_alert *) m->vparam);
194
case KMSG_ALERT_CHECK_QUEUE:
195
check_for_queued_alerts();
198
case KMSG_ALERT_SHOW_QUEUED:
199
if (current_alert == NULL) {
202
a = del_from_alert_queue();
205
check_for_queued_alerts();
206
khui_alert_release(a);
211
case KMSG_ALERT_SHOW_MODAL:
215
a = (khui_alert *) m->vparam;
216
a->flags |= KHUI_ALERT_FLAG_MODAL;
218
khui_alert_release(a);
220
if (KHM_SUCCEEDED(rv)) {
221
notifier_modal_loop = TRUE;
223
khm_message_loop_int(¬ifier_modal_loop);
95
228
} else if (m->type == KMSG_CRED &&
96
229
m->subtype == KMSG_CRED_ROOTDELTA) {
97
231
KillTimer(hwnd, KHUI_REFRESH_TIMER_ID);
98
232
SetTimer(hwnd, KHUI_REFRESH_TIMER_ID,
99
233
KHUI_REFRESH_TIMEOUT,
103
238
return kmq_wm_end(m, rv);
145
280
if ((current_alert->flags & KHUI_ALERT_FLAG_DEFACTION) &&
146
281
current_alert->n_alert_commands > 0) {
147
282
PostMessage(khm_hwnd_main, WM_COMMAND,
148
MAKEWPARAM(current_alert->alert_commands[0], 0),
283
MAKEWPARAM(current_alert->alert_commands[0],
150
} else if (current_alert->flags & KHUI_ALERT_FLAG_REQUEST_WINDOW) {
286
} else if (current_alert->flags &
287
KHUI_ALERT_FLAG_REQUEST_WINDOW) {
151
288
khm_show_main_window();
152
289
alert_show_normal(current_alert);
155
292
/* fallthrough */
293
case NIN_BALLOONHIDE:
156
294
case NIN_BALLOONTIMEOUT:
157
khui_notify_icon_change(KHERR_NONE);
295
khm_notify_icon_change(KHERR_NONE);
158
296
if (current_alert) {
159
297
khui_alert_release(current_alert);
160
298
current_alert = NULL;
316
454
a->flags |= KHUI_ALERT_FLAG_DISPLAY_BALLOON;
456
#if (_WIN32_IE >= 0x0501)
318
457
current_alert = a;
319
458
khui_alert_hold(a);
321
khui_notify_icon_balloon(a->severity,
461
khm_notify_icon_balloon(a->severity,
340
480
title = a->title;
342
482
/* if we don't have any commands, we just add a "close" button */
343
if(a->n_alert_commands == 0) {
483
if (a->n_alert_commands == 0) {
344
484
khui_alert_add_command(a, KHUI_PACTION_CLOSE);
487
/* if there are other alerts queued up, we should add a 'Next
488
alert...' button that when clicked, would show the next queued
489
alert. However, we only do this if the current alert doesn't
490
actually require a command response. Otherwise, clicking the
491
'next' button will be the equivalent of cancelling out of the
492
alert without selecting any of the commands. */
493
if (!is_alert_queue_empty() &&
494
a->n_alert_commands == 1 &&
495
a->alert_commands[0] == KHUI_PACTION_CLOSE) {
497
khui_alert_add_command(a, KHUI_PACTION_NEXT);
347
500
/* we don't need to keep track of the window handle
348
501
because the window procedure adds it to the dialog
349
502
list automatically */
352
505
CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,
353
506
MAKEINTATOM(atom_alerter),
355
WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN |
508
WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,
357
509
0, 0, 300, 300, // bogus values
515
ShowWindow(hwa, SW_SHOW);
363
517
return KHM_ERROR_SUCCESS;
367
521
alert_show(khui_alert * a) {
522
/* is there an alert already? If so, we just enqueue the message
525
return alert_enqueue(a);
368
528
/* the window has already been shown */
369
529
if((a->flags & KHUI_ALERT_FLAG_DISPLAY_WINDOW) ||
370
530
((a->flags & KHUI_ALERT_FLAG_DISPLAY_BALLOON) &&
381
541
/* depending on the state of the main window, we
382
542
need to either show a window or a balloon */
383
if(khm_is_main_window_active() &&
384
!(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON))
543
if ((a->flags & KHUI_ALERT_FLAG_MODAL) ||
544
(khm_is_main_window_active() &&
545
!(a->flags & KHUI_ALERT_FLAG_REQUEST_BALLOON)))
385
546
return alert_show_normal(a);
387
548
return alert_show_minimized(a);
552
alert_enqueue(khui_alert * a) {
553
if (is_alert_queue_full())
554
return KHM_ERROR_NO_RESOURCES;
556
add_to_alert_queue(a);
557
check_for_queued_alerts();
559
return KHM_ERROR_SUCCESS;
390
562
/* the alerter window is actually a dialog */
391
563
static LRESULT CALLBACK
392
564
alerter_wnd_proc(HWND hwnd,
598
772
khui_alert_lock(d->alert);
599
773
d->alert->flags &= ~KHUI_ALERT_FLAG_DISPLAY_WINDOW;
774
if (d->alert->flags & KHUI_ALERT_FLAG_MODAL)
775
notifier_modal_loop = FALSE;
600
776
khui_alert_unlock(d->alert);
602
778
khui_alert_release(d->alert);
604
780
DeleteObject(d->hfont);
608
khui_notify_icon_change(KHERR_NONE);
784
khm_notify_icon_change(KHERR_NONE);
718
894
CopyRect(&ro, &r);
720
896
// adjust for icon and padding
721
r.left += SM_CXICON + d->dx_suggest_pad * 2;
897
r.left += GetSystemMetrics(SM_CXSMICON) + d->dx_suggest_pad * 2;
722
898
r.top += d->dx_suggest_pad;
723
899
r.right -= d->dx_suggest_pad;
724
900
r.bottom -= d->dx_suggest_pad;
749
925
MAKEINTRESOURCE(OIC_INFORMATION),
751
SM_CXICON, SM_CYICON,
927
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
754
930
assert(h_sug_ico != NULL);
757
933
ro.left + d->dx_suggest_pad,
758
934
ro.top + d->dx_suggest_pad,
760
SM_CXICON, SM_CYICON,
936
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
857
1038
//return DefWindowProc(hwnd, uMsg, wParam, lParam);
860
ATOM khui_register_alerter_wnd_class(void)
1041
ATOM khm_register_alerter_wnd_class(void)
864
1045
ZeroMemory(&wcx, sizeof(wcx));
866
1047
wcx.cbSize = sizeof(wcx);
867
wcx.style = CS_DROPSHADOW | CS_OWNDC;
1050
#if(_WIN32_WINNT >= 0x0501)
1051
((IS_COMMCTL6())? CS_DROPSHADOW: 0) |
868
1054
wcx.lpfnWndProc = alerter_wnd_proc;
869
1055
wcx.cbClsExtra = 0;
870
1056
wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
897
1083
ni.hWnd = hwnd_notifier;
898
1084
ni.uID = KHUI_NOTIFY_ICON_ID;
899
1085
ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
900
ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_NOTIFY_NONE));
1086
ni.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(iid_normal));
901
1087
ni.uCallbackMessage = KHUI_WM_NOTIFIER;
902
1088
LoadString(khm_hInstance, IDS_NOTIFY_PREFIX, buf, ARRAYLENGTH(buf));
903
1089
StringCbCopy(ni.szTip, sizeof(ni.szTip), buf);
970
1156
DestroyIcon(ni.hIcon);
973
void khui_notify_icon_change(khm_int32 severity) {
1159
void khm_notify_icon_expstate(enum khm_notif_expstate expseverity) {
1162
if (expseverity == KHM_NOTIF_OK)
1163
new_iid = IDI_APPICON_OK;
1164
else if (expseverity == KHM_NOTIF_WARN)
1165
new_iid = IDI_APPICON_WARN;
1166
else if (expseverity == KHM_NOTIF_EXP)
1167
new_iid = IDI_APPICON_EXP;
1169
new_iid = IDI_NOTIFY_NONE;
1171
if (iid_normal == new_iid)
1174
iid_normal = new_iid;
1176
if (current_alert == NULL)
1177
khm_notify_icon_change(KHERR_NONE);
1180
void khm_notify_icon_change(khm_int32 severity) {
974
1181
NOTIFYICONDATA ni;
975
1182
wchar_t buf[256];
1021
1228
**********************************************************************/
1023
void khui_init_notifier(void)
1230
void khm_init_notifier(void)
1025
if(!khui_register_notifier_wnd_class())
1232
if(!khm_register_notifier_wnd_class())
1028
if(!khui_register_alerter_wnd_class())
1235
if(!khm_register_alerter_wnd_class())
1031
1238
hwnd_notifier = CreateWindowEx(0,
1053
1260
khm_timer_init();
1262
khm_addr_change_notifier_init();
1056
void khui_exit_notifier(void)
1265
void khm_exit_notifier(void)
1267
khm_addr_change_notifier_exit();
1058
1269
khm_timer_exit();
1060
1271
if(hwnd_notifier != NULL) {
1061
khui_notify_icon_remove();
1272
khm_notify_icon_remove();
1062
1273
kmq_unsubscribe_hwnd(KMSG_ALERT, hwnd_notifier);
1063
1274
kmq_unsubscribe_hwnd(KMSG_CRED, hwnd_notifier);
1064
1275
DestroyWindow(hwnd_notifier);