/toolkit/mozapps/update/updater/progressui_win.cpp

http://github.com/zpao/v8monkey · C++ · 308 lines · 194 code · 46 blank · 68 comment · 25 complexity · 2106c899bf03533df9e26096f4dec709 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim:set ts=2 sw=2 sts=2 et cindent: */
  3. /* ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is mozilla.org code.
  17. *
  18. * The Initial Developer of the Original Code is Google Inc.
  19. * Portions created by the Initial Developer are Copyright (C) 2005
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Darin Fisher <darin@meer.net>
  24. * Masayuki Nakano <masayuki@d-toybox.com>
  25. * Robert Strong <robert.bugzilla@gmail.com>
  26. *
  27. * Alternatively, the contents of this file may be used under the terms of
  28. * either the GNU General Public License Version 2 or later (the "GPL"), or
  29. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  30. * in which case the provisions of the GPL or the LGPL are applicable instead
  31. * of those above. If you wish to allow use of your version of this file only
  32. * under the terms of either the GPL or the LGPL, and not to allow others to
  33. * use your version of this file under the terms of the MPL, indicate your
  34. * decision by deleting the provisions above and replace them with the notice
  35. * and other provisions required by the GPL or the LGPL. If you do not delete
  36. * the provisions above, a recipient may use your version of this file under
  37. * the terms of any one of the MPL, the GPL or the LGPL.
  38. *
  39. * ***** END LICENSE BLOCK ***** */
  40. #include <stdio.h>
  41. #include <windows.h>
  42. #include <commctrl.h>
  43. #include <process.h>
  44. #include <io.h>
  45. #include "resource.h"
  46. #include "progressui.h"
  47. #include "readstrings.h"
  48. #include "errors.h"
  49. #define TIMER_ID 1
  50. #define TIMER_INTERVAL 100
  51. #define RESIZE_WINDOW(hwnd, extrax, extray) \
  52. { \
  53. RECT windowSize; \
  54. GetWindowRect(hwnd, &windowSize); \
  55. SetWindowPos(hwnd, 0, 0, 0, windowSize.right - windowSize.left + extrax, \
  56. windowSize.bottom - windowSize.top + extray, \
  57. SWP_NOMOVE | SWP_NOZORDER); \
  58. }
  59. #define MOVE_WINDOW(hwnd, dx, dy) \
  60. { \
  61. RECT rc; \
  62. POINT pt; \
  63. GetWindowRect(hwnd, &rc); \
  64. pt.x = rc.left; \
  65. pt.y = rc.top; \
  66. ScreenToClient(GetParent(hwnd), &pt); \
  67. SetWindowPos(hwnd, 0, pt.x + dx, pt.y + dy, 0, 0, \
  68. SWP_NOSIZE | SWP_NOZORDER); \
  69. }
  70. static float sProgress; // between 0 and 100
  71. static BOOL sQuit = FALSE;
  72. static BOOL sIndeterminate = FALSE;
  73. static StringTable sUIStrings;
  74. static BOOL
  75. GetStringsFile(WCHAR filename[MAX_PATH])
  76. {
  77. if (!GetModuleFileNameW(NULL, filename, MAX_PATH))
  78. return FALSE;
  79. WCHAR *dot = wcsrchr(filename, '.');
  80. if (!dot || wcsicmp(dot + 1, L"exe"))
  81. return FALSE;
  82. wcscpy(dot + 1, L"ini");
  83. return TRUE;
  84. }
  85. static void
  86. UpdateDialog(HWND hDlg)
  87. {
  88. int pos = int(sProgress + 0.5f);
  89. HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
  90. SendMessage(hWndPro, PBM_SETPOS, pos, 0L);
  91. }
  92. // The code in this function is from MSDN:
  93. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/usingdialogboxes.asp
  94. static void
  95. CenterDialog(HWND hDlg)
  96. {
  97. RECT rc, rcOwner, rcDlg;
  98. // Get the owner window and dialog box rectangles.
  99. HWND desktop = GetDesktopWindow();
  100. GetWindowRect(desktop, &rcOwner);
  101. GetWindowRect(hDlg, &rcDlg);
  102. CopyRect(&rc, &rcOwner);
  103. // Offset the owner and dialog box rectangles so that
  104. // right and bottom values represent the width and
  105. // height, and then offset the owner again to discard
  106. // space taken up by the dialog box.
  107. OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
  108. OffsetRect(&rc, -rc.left, -rc.top);
  109. OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
  110. // The new position is the sum of half the remaining
  111. // space and the owner's original position.
  112. SetWindowPos(hDlg,
  113. HWND_TOP,
  114. rcOwner.left + (rc.right / 2),
  115. rcOwner.top + (rc.bottom / 2),
  116. 0, 0, // ignores size arguments
  117. SWP_NOSIZE);
  118. }
  119. static void
  120. InitDialog(HWND hDlg)
  121. {
  122. WCHAR szwTitle[MAX_TEXT_LEN];
  123. WCHAR szwInfo[MAX_TEXT_LEN];
  124. MultiByteToWideChar(CP_UTF8, 0, sUIStrings.title, -1, szwTitle,
  125. sizeof(szwTitle)/sizeof(szwTitle[0]));
  126. MultiByteToWideChar(CP_UTF8, 0, sUIStrings.info, -1, szwInfo,
  127. sizeof(szwInfo)/sizeof(szwInfo[0]));
  128. SetWindowTextW(hDlg, szwTitle);
  129. SetWindowTextW(GetDlgItem(hDlg, IDC_INFO), szwInfo);
  130. // Set dialog icon
  131. HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_DIALOG));
  132. if (hIcon)
  133. SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
  134. HWND hWndPro = GetDlgItem(hDlg, IDC_PROGRESS);
  135. SendMessage(hWndPro, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
  136. if (sIndeterminate) {
  137. LONG_PTR val = GetWindowLongPtr(hWndPro, GWL_STYLE);
  138. SetWindowLongPtr(hWndPro, GWL_STYLE, val|PBS_MARQUEE);
  139. SendMessage(hWndPro,(UINT) PBM_SETMARQUEE,(WPARAM) TRUE,(LPARAM)50 );
  140. }
  141. // Resize the dialog to fit all of the text if necessary.
  142. RECT infoSize, textSize;
  143. HWND hWndInfo = GetDlgItem(hDlg, IDC_INFO);
  144. // Get the control's font for calculating the new size for the control
  145. HDC hDCInfo = GetDC(hWndInfo);
  146. HFONT hInfoFont, hOldFont;
  147. hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0);
  148. if (hInfoFont)
  149. hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont);
  150. // Measure the space needed for the text on a single line. DT_CALCRECT means
  151. // nothing is drawn.
  152. if (DrawText(hDCInfo, szwInfo, -1, &textSize,
  153. DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE)) {
  154. GetClientRect(hWndInfo, &infoSize);
  155. SIZE extra;
  156. // Calculate the additional space needed for the text by subtracting from
  157. // the rectangle returned by DrawText the existing client rectangle's width
  158. // and height.
  159. extra.cx = (textSize.right - textSize.left) - \
  160. (infoSize.right - infoSize.left);
  161. extra.cy = (textSize.bottom - textSize.top) - \
  162. (infoSize.bottom - infoSize.top);
  163. if (extra.cx < 0)
  164. extra.cx = 0;
  165. if (extra.cy < 0)
  166. extra.cy = 0;
  167. if ((extra.cx > 0) || (extra.cy > 0)) {
  168. RESIZE_WINDOW(hDlg, extra.cx, extra.cy);
  169. RESIZE_WINDOW(hWndInfo, extra.cx, extra.cy);
  170. RESIZE_WINDOW(hWndPro, extra.cx, 0);
  171. MOVE_WINDOW(hWndPro, 0, extra.cy);
  172. }
  173. }
  174. if (hOldFont)
  175. SelectObject(hDCInfo, hOldFont);
  176. ReleaseDC(hWndInfo, hDCInfo);
  177. CenterDialog(hDlg); // make dialog appear in the center of the screen
  178. SetTimer(hDlg, TIMER_ID, TIMER_INTERVAL, NULL);
  179. }
  180. // Message handler for update dialog.
  181. static LRESULT CALLBACK
  182. DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  183. {
  184. switch (message)
  185. {
  186. case WM_INITDIALOG:
  187. InitDialog(hDlg);
  188. return TRUE;
  189. case WM_TIMER:
  190. if (sQuit) {
  191. EndDialog(hDlg, 0);
  192. } else {
  193. UpdateDialog(hDlg);
  194. }
  195. return TRUE;
  196. case WM_COMMAND:
  197. return TRUE;
  198. }
  199. return FALSE;
  200. }
  201. int
  202. InitProgressUI(int *argc, NS_tchar ***argv)
  203. {
  204. return 0;
  205. }
  206. /**
  207. * Initializes the progress UI strings
  208. *
  209. * @return 0 on success, -1 on error
  210. */
  211. int
  212. InitProgressUIStrings() {
  213. // If we do not have updater.ini, then we should not bother showing UI.
  214. WCHAR filename[MAX_PATH];
  215. if (!GetStringsFile(filename)) {
  216. return -1;
  217. }
  218. if (_waccess(filename, 04)) {
  219. return -1;
  220. }
  221. // If the updater.ini doesn't have the required strings, then we should not
  222. // bother showing UI.
  223. if (ReadStrings(filename, &sUIStrings) != OK) {
  224. return -1;
  225. }
  226. return 0;
  227. }
  228. int
  229. ShowProgressUI(bool indeterminate, bool initUIStrings)
  230. {
  231. sIndeterminate = indeterminate;
  232. if (!indeterminate) {
  233. // Only show the Progress UI if the process is taking a significant amount of
  234. // time where a significant amount of time is defined as .5 seconds after
  235. // ShowProgressUI is called sProgress is less than 70.
  236. Sleep(500);
  237. if (sQuit || sProgress > 70.0f)
  238. return 0;
  239. }
  240. if (initUIStrings && InitProgressUIStrings() == -1) {
  241. return -1;
  242. }
  243. INITCOMMONCONTROLSEX icc = {
  244. sizeof(INITCOMMONCONTROLSEX),
  245. ICC_PROGRESS_CLASS
  246. };
  247. InitCommonControlsEx(&icc);
  248. DialogBox(GetModuleHandle(NULL),
  249. MAKEINTRESOURCE(IDD_DIALOG), NULL,
  250. (DLGPROC) DialogProc);
  251. return 0;
  252. }
  253. void
  254. QuitProgressUI()
  255. {
  256. sQuit = TRUE;
  257. }
  258. void
  259. UpdateProgressUI(float progress)
  260. {
  261. sProgress = progress; // 32-bit writes are atomic
  262. }