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