]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/win32/libwin32/trayMonitor.cpp
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / libwin32 / trayMonitor.cpp
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /* 
20  * 
21  *  Kern Sibbald, August 2007
22  *
23  * This is a generic tray monitor routine, which is used by all three
24  *  of the daemons. Each one compiles it with slightly different
25  *  #defines.
26  *
27  */
28
29 #include "bacula.h"
30 #include "jcr.h"
31 #include "win32.h"
32
33 trayMonitor::trayMonitor()
34 {
35
36 // m_tbcreated_msg = RegisterWindowMessage("TaskbarCreated");
37    
38    /* Create a window to handle tray icon messages */
39    WNDCLASSEX trayclass;
40
41    trayclass.cbSize         = sizeof(trayclass);
42    trayclass.style          = 0;
43    trayclass.lpfnWndProc    = trayMonitor::trayWinProc;
44    trayclass.cbClsExtra     = 0;
45    trayclass.cbWndExtra     = 0;
46    trayclass.hInstance      = appInstance;
47    trayclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
48    trayclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
49    trayclass.hbrBackground  = (HBRUSH)GetStockObject(WHITE_BRUSH);
50    trayclass.lpszMenuName   = NULL;
51    trayclass.lpszClassName  = APP_NAME;
52    trayclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
53
54    RegisterClassEx(&trayclass);
55
56    m_hwnd = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
57                 CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
58                 NULL, NULL, appInstance, NULL);
59    if (!m_hwnd) {
60       PostQuitMessage(0);
61       return;
62    }
63
64    /* Save our class pointer */
65    SetWindowLong(m_hwnd, GWL_USERDATA, (LPARAM)this);
66
67
68    // Load the icons for the tray
69    m_idle_icon    = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_IDLE));
70    m_running_icon = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_RUNNING));
71    m_error_icon   = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_JOB_ERROR));
72    m_warn_icon    = LoadIcon(appInstance, MAKEINTRESOURCE(IDI_JOB_WARNING));
73
74    /* Load the menu */
75    m_hmenu = LoadMenu(appInstance, MAKEINTRESOURCE(IDR_TRAYMENU));
76    m_visible = false;
77    m_installed = false;
78
79    /* Install the icon in the tray */
80    install();
81
82    /* Timer to trigger icon updating */
83    SetTimer(m_hwnd, 1, 5000, NULL);
84 }
85
86 trayMonitor::~trayMonitor()
87 {
88    /* Remove the icon from the tray */
89    sendMessage(NIM_DELETE, 0);
90         
91    if (m_hmenu) {
92       DestroyMenu(m_hmenu);
93       m_hmenu = NULL;
94    }
95 }
96
97 void trayMonitor::install()
98 {
99    m_installed = true;
100    sendMessage(NIM_ADD, bacstat);
101 }
102
103 void trayMonitor::update(int bacstat)
104 {
105    if (!m_installed) {
106       install();
107    }
108    (void)bac_status(NULL, 0);
109    sendMessage(NIM_MODIFY, bacstat);
110 }
111
112 void trayMonitor::sendMessage(DWORD msg, int bacstat)
113 {
114    struct s_last_job *job;
115    
116    // Create the tray icon message
117    m_nid.hWnd = m_hwnd;
118    m_nid.cbSize = sizeof(m_nid);
119    m_nid.uID = IDI_BACULA;                  // never changes after construction
120    switch (bacstat) {
121    case 0:
122       m_nid.hIcon = m_idle_icon;
123       break;
124    case JS_Running:
125       m_nid.hIcon = m_running_icon;
126       break;
127    case JS_ErrorTerminated:
128       m_nid.hIcon = m_error_icon;
129       break;
130    default:
131       if (last_jobs->size() > 0) {
132          job = (struct s_last_job *)last_jobs->last();
133          if (job->Errors) {
134             m_nid.hIcon = m_warn_icon;
135          } else {
136             m_nid.hIcon = m_idle_icon;
137          }
138       } else {
139          m_nid.hIcon = m_idle_icon;
140       }
141       break;
142    }
143
144    m_nid.uFlags = NIF_ICON | NIF_MESSAGE;
145    m_nid.uCallbackMessage = WM_TRAYNOTIFY;
146
147
148    /* Use the resource string as tip */
149    if (LoadString(appInstance, IDI_BACULA, m_nid.szTip, sizeof(m_nid.szTip))) {
150        m_nid.uFlags |= NIF_TIP;
151    }
152
153    /* Add the Bacula status to the tip string */
154    if (m_nid.uFlags & NIF_TIP) {
155        bac_status(m_nid.szTip, sizeof(m_nid.szTip));
156    }
157
158    if (Shell_NotifyIcon(msg, &m_nid)) {
159       EnableMenuItem(m_hmenu, ID_CLOSE, MF_ENABLED);
160    }
161 }
162
163 /*
164  * This is the windows call back for our tray window
165  */
166 LRESULT CALLBACK trayMonitor::trayWinProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
167 {
168    HMENU menu;
169    trayMonitor *mon = (trayMonitor *)GetWindowLong(hwnd, GWL_USERDATA);
170
171    switch (iMsg) {
172
173    /* Every five seconds, a timer message causes the icon to update */
174    case WM_TIMER:
175       if (isAService()) {
176          mon->install();
177       }
178       mon->update(bacstat);
179       break;
180
181    case WM_CREATE:
182       return 0;
183
184    case WM_COMMAND:
185       /* User has clicked an item on the tray monitor menu */
186       switch (LOWORD(wParam)) {
187       case ID_STATUS:
188          /* show the dialog box */
189          mon->m_status.show(true);
190          mon->update(bacstat);
191          break;
192
193       case ID_ABOUT:
194          /* Show the About box */
195          mon->m_about.show(true);
196          break;
197
198       /* This is turned off now */
199 #ifdef xxx
200       case ID_CLOSE:
201          /* User selected Close from the tray menu */
202          PostMessage(hwnd, WM_CLOSE, 0, 0);
203          break;
204 #endif
205
206       }
207       return 0;
208
209    /* Our special command to check for mouse events */
210    case WM_TRAYNOTIFY:
211       /* Right button click pops up the menu */
212       if (lParam == WM_RBUTTONUP) {
213          POINT mouse;
214          /* Get the menu and pop it up */
215          menu = GetSubMenu(mon->m_hmenu, 0);
216          if (!menu) {
217              return 0;
218          }
219
220          /* The first menu item (Status) is the default */
221          SetMenuDefaultItem(menu, 0, TRUE);
222          GetCursorPos(&mouse);
223          SetForegroundWindow(mon->m_nid.hWnd);  /* display the menu */
224
225          /* Open the menu at the mouse position */
226          TrackPopupMenu(menu, 0, mouse.x, mouse.y, 0, mon->m_nid.hWnd, NULL);
227
228       /* Left double click brings up status dialog directly */
229       } else if (lParam == WM_LBUTTONDBLCLK) {
230          mon->m_status.show(true);
231          mon->update(bacstat);
232       }
233       return 0;
234
235    case WM_CLOSE:
236       if (isAService()) {
237           mon->sendMessage(NIM_DELETE, 0);
238       }
239       terminate_app(0);
240       break;
241
242    case WM_DESTROY:
243       /* zap everything */
244       PostQuitMessage(0);
245       return 0;
246
247    case WM_QUERYENDSESSION:
248       if (!isAService() || lParam == 0) {
249          PostQuitMessage(0);
250          return TRUE;
251       }
252       return TRUE;
253
254     default:
255        /* Need to redraw tray icon */
256 //     if (iMsg == mon->m_tbcreated_msg) {
257 //        mon->install();    
258 //     }
259        break;
260    }
261
262    return DefWindowProc(hwnd, iMsg, wParam, lParam);
263 }