2 * Copyright (C) 2006, 2008 Apple Computer, Inc. All rights reserved.
3 * Copyright (C) 2009, 2011 Brent Fulgham. All rights reserved.
4 * Copyright (C) 2009, 2010, 2011 Appcelerator, Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "WinLauncher.h"
31 #include "DOMDefaultImpl.h"
32 #include "PrintWebUIDelegate.h"
33 #include <WebKit/WebKitCOMAPI.h>
43 #define MAX_LOADSTRING 100
44 #define URLBAR_HEIGHT 24
47 HINSTANCE hInst; // current instance
50 WNDPROC DefEditProc = 0;
51 WNDPROC DefWebKitProc = 0;
52 IWebView* gWebView = 0;
53 IWebViewPrivate* gWebViewPrivate = 0;
55 WinLauncherWebHost* gWebHost = 0;
56 PrintWebUIDelegate* gPrintDelegate = 0;
57 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
58 TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
60 // Support moving the transparent window
61 POINT s_windowPosition = { 100, 100 };
62 SIZE s_windowSize = { 800, 400 };
63 bool s_usesLayeredWebView = false;
64 bool s_fullDesktop = false;
66 // Forward declarations of functions included in this code module:
67 ATOM MyRegisterClass(HINSTANCE hInstance);
68 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
69 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
70 LRESULT CALLBACK MyEditProc(HWND, UINT, WPARAM, LPARAM);
72 static void loadURL(BSTR urlBStr);
74 static bool usesLayeredWebView()
76 return s_usesLayeredWebView;
79 static bool shouldUseFullDesktop()
84 class SimpleEventListener : public DOMEventListener {
86 SimpleEventListener(LPWSTR type)
88 wcsncpy_s(m_eventType, 100, type, 100);
92 virtual HRESULT STDMETHODCALLTYPE handleEvent(IDOMEvent* evt)
95 wcscpy_s(message, 255, m_eventType);
96 wcscat_s(message, 255, L" event fired!");
97 ::MessageBox(0, message, L"Event Handler", MB_OK);
102 wchar_t m_eventType[100];
105 HRESULT WinLauncherWebHost::updateAddressBar(IWebView* webView)
107 IWebFrame* mainFrame = 0;
108 IWebDataSource* dataSource = 0;
109 IWebMutableURLRequest* request = 0;
114 hr = webView->mainFrame(&mainFrame);
118 hr = mainFrame->dataSource(&dataSource);
119 if (FAILED(hr) || !dataSource)
120 hr = mainFrame->provisionalDataSource(&dataSource);
121 if (FAILED(hr) || !dataSource)
124 hr = dataSource->request(&request);
125 if (FAILED(hr) || !request)
128 hr = request->mainDocumentURL(&frameURL);
132 SendMessage(hURLBarWnd, (UINT)WM_SETTEXT, 0, (LPARAM)frameURL);
136 mainFrame->Release();
138 dataSource->Release();
141 SysFreeString(frameURL);
145 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::didFailProvisionalLoadWithError(IWebView*, IWebError *error, IWebFrame*)
147 BSTR errorDescription = 0;
148 HRESULT hr = error->localizedDescription(&errorDescription);
150 errorDescription = L"Failed to load page and to localize error description.";
152 ::MessageBoxW(0, static_cast<LPCWSTR>(errorDescription), L"Error", MB_APPLMODAL | MB_OK);
154 SysFreeString(errorDescription);
159 HRESULT STDMETHODCALLTYPE WinLauncherWebHost::QueryInterface(REFIID riid, void** ppvObject)
162 if (IsEqualGUID(riid, IID_IUnknown))
163 *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
164 else if (IsEqualGUID(riid, IID_IWebFrameLoadDelegate))
165 *ppvObject = static_cast<IWebFrameLoadDelegate*>(this);
167 return E_NOINTERFACE;
173 ULONG STDMETHODCALLTYPE WinLauncherWebHost::AddRef(void)
178 ULONG STDMETHODCALLTYPE WinLauncherWebHost::Release(void)
180 ULONG newRef = --m_refCount;
187 HRESULT WinLauncherWebHost::didFinishLoadForFrame(IWebView* webView, IWebFrame* frame)
189 IDOMDocument* doc = 0;
190 frame->DOMDocument(&doc);
192 IDOMElement* element = 0;
193 IDOMEventTarget* target = 0;
194 HRESULT hr = doc->getElementById(L"webkit logo", &element);
198 hr = element->QueryInterface(IID_IDOMEventTarget, reinterpret_cast<void**>(&target));
202 hr = target->addEventListener(L"click", new SimpleEventListener (L"webkit logo click"), FALSE);
217 static void resizeSubViews()
219 if (usesLayeredWebView() || !gViewWindow)
223 GetClientRect(hMainWnd, &rcClient);
224 MoveWindow(hURLBarWnd, 0, 0, rcClient.right, URLBAR_HEIGHT, TRUE);
225 MoveWindow(gViewWindow, 0, URLBAR_HEIGHT, rcClient.right, rcClient.bottom - URLBAR_HEIGHT, TRUE);
228 static void subclassForLayeredWindow()
230 hMainWnd = gViewWindow;
231 DefWebKitProc = reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hMainWnd, GWL_WNDPROC));
232 ::SetWindowLongPtr(hMainWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(WndProc));
235 static void computeFullDesktopFrame()
238 if (!::SystemParametersInfo(SPI_GETWORKAREA, 0, static_cast<void*>(&desktop), 0))
241 s_windowPosition.x = 0;
242 s_windowPosition.y = 0;
243 s_windowSize.cx = desktop.right - desktop.left;
244 s_windowSize.cy = desktop.bottom - desktop.top;
247 BOOL WINAPI DllMain(HINSTANCE dllInstance, DWORD reason, LPVOID)
249 if (reason == DLL_PROCESS_ATTACH)
255 extern "C" __declspec(dllexport) int WINAPI dllLauncherEntryPoint(HINSTANCE, HINSTANCE, LPTSTR, int nCmdShow)
257 #ifdef _CRTDBG_MAP_ALLOC
258 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
259 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
262 // TODO: Place code here.
266 INITCOMMONCONTROLSEX InitCtrlEx;
268 InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
269 InitCtrlEx.dwICC = 0x00004000; //ICC_STANDARD_CLASSES;
270 InitCommonControlsEx(&InitCtrlEx);
273 WCHAR** argv = CommandLineToArgvW(GetCommandLineW(), &argc);
274 for (int i = 1; i < argc; ++i) {
275 if (!wcsicmp(argv[i], L"--transparent"))
276 s_usesLayeredWebView = true;
277 else if (!wcsicmp(argv[i], L"--desktop"))
278 s_fullDesktop = true;
281 // Initialize global strings
282 LoadString(hInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
283 LoadString(hInst, IDC_WINLAUNCHER, szWindowClass, MAX_LOADSTRING);
284 MyRegisterClass(hInst);
286 if (shouldUseFullDesktop())
287 computeFullDesktopFrame();
292 if (usesLayeredWebView()) {
293 hURLBarWnd = CreateWindow(L"EDIT", L"Type URL Here",
294 WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL,
295 s_windowPosition.x, s_windowPosition.y + s_windowSize.cy, s_windowSize.cx, URLBAR_HEIGHT,
300 hMainWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
301 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, hInst, 0);
306 hURLBarWnd = CreateWindow(L"EDIT", 0,
307 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOVSCROLL,
313 ShowWindow(hMainWnd, nCmdShow);
314 UpdateWindow(hMainWnd);
317 DefEditProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hURLBarWnd, GWL_WNDPROC));
318 SetWindowLongPtr(hURLBarWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(MyEditProc));
319 SetFocus(hURLBarWnd);
321 RECT clientRect = { s_windowPosition.x, s_windowPosition.y, s_windowPosition.x + s_windowSize.cx, s_windowPosition.y + s_windowSize.cy };
323 IWebPreferences* tmpPreferences = 0;
324 IWebPreferences* standardPreferences = 0;
325 if (FAILED(WebKitCreateInstance(CLSID_WebPreferences, 0, IID_IWebPreferences, reinterpret_cast<void**>(&tmpPreferences))))
328 if (FAILED(tmpPreferences->standardPreferences(&standardPreferences)))
331 standardPreferences->setAcceleratedCompositingEnabled(TRUE);
333 HRESULT hr = WebKitCreateInstance(CLSID_WebView, 0, IID_IWebView, reinterpret_cast<void**>(&gWebView));
337 hr = gWebView->QueryInterface(IID_IWebViewPrivate, reinterpret_cast<void**>(&gWebViewPrivate));
341 gWebHost = new WinLauncherWebHost();
343 hr = gWebView->setFrameLoadDelegate(gWebHost);
347 gPrintDelegate = new PrintWebUIDelegate;
348 gPrintDelegate->AddRef();
349 hr = gWebView->setUIDelegate(gPrintDelegate);
353 hr = gWebView->setHostWindow(reinterpret_cast<OLE_HANDLE>(hMainWnd));
357 hr = gWebView->initWithFrame(clientRect, 0, 0);
362 hr = gWebView->mainFrame(&frame);
366 static BSTR defaultHTML = SysAllocString(TEXT("<p style=\"background-color: #00FF00\">Testing</p><img id=\"webkit logo\" src=\"http://webkit.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue; background: white;\" contenteditable=\"true\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>"));
367 frame->loadHTMLString(defaultHTML, 0);
370 hr = gWebViewPrivate->setTransparent(usesLayeredWebView());
374 hr = gWebViewPrivate->setUsesLayeredWindow(usesLayeredWebView());
378 hr = gWebViewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&gViewWindow));
379 if (FAILED(hr) || !gViewWindow)
382 if (usesLayeredWebView())
383 subclassForLayeredWindow();
387 ShowWindow(gViewWindow, nCmdShow);
388 UpdateWindow(gViewWindow);
390 hAccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDC_WINLAUNCHER));
392 // Main message loop:
393 while (GetMessage(&msg, NULL, 0, 0)) {
394 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
395 TranslateMessage(&msg);
396 DispatchMessage(&msg);
401 gPrintDelegate->Release();
403 gWebViewPrivate->Release();
405 if (standardPreferences)
406 standardPreferences->Release();
407 tmpPreferences->Release();
410 #ifdef _CRTDBG_MAP_ALLOC
411 _CrtDumpMemoryLeaks();
417 return static_cast<int>(msg.wParam);
420 ATOM MyRegisterClass(HINSTANCE hInstance)
424 wcex.cbSize = sizeof(WNDCLASSEX);
426 wcex.style = CS_HREDRAW | CS_VREDRAW;
427 wcex.lpfnWndProc = WndProc;
430 wcex.hInstance = hInstance;
431 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINLAUNCHER));
432 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
433 wcex.hbrBackground = 0;
434 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINLAUNCHER);
435 wcex.lpszClassName = szWindowClass;
436 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
438 return RegisterClassEx(&wcex);
441 static BOOL CALLBACK AbortProc(HDC hDC, int Error)
444 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
445 ::TranslateMessage(&msg);
446 ::DispatchMessage(&msg);
452 static HDC getPrinterDC()
455 memset(&pdlg, 0, sizeof(PRINTDLG));
456 pdlg.lStructSize = sizeof(PRINTDLG);
457 pdlg.Flags = PD_PRINTSETUP | PD_RETURNDC;
464 static void initDocStruct(DOCINFO* di, TCHAR* docname)
466 memset(di, 0, sizeof(DOCINFO));
467 di->cbSize = sizeof(DOCINFO);
468 di->lpszDocName = docname;
471 void PrintView(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
473 HDC printDC = getPrinterDC();
475 ::MessageBoxW(0, L"Error creating printing DC", L"Error", MB_APPLMODAL | MB_OK);
479 if (::SetAbortProc(printDC, AbortProc) == SP_ERROR) {
480 ::MessageBoxW(0, L"Error setting up AbortProc", L"Error", MB_APPLMODAL | MB_OK);
484 IWebFrame* frame = 0;
485 IWebFramePrivate* framePrivate = 0;
486 if (FAILED(gWebView->mainFrame(&frame)))
489 if (FAILED(frame->QueryInterface(&framePrivate)))
492 framePrivate->setInPrintingMode(TRUE, printDC);
495 framePrivate->getPrintedPageCount(printDC, &pageCount);
498 initDocStruct(&di, L"WebKit Doc");
499 ::StartDoc(printDC, &di);
501 // FIXME: Need CoreGraphics implementation
502 void* graphicsContext = 0;
503 for (size_t page = 1; page <= pageCount; ++page) {
504 ::StartPage(printDC);
505 framePrivate->spoolPages(printDC, page, page, graphicsContext);
509 framePrivate->setInPrintingMode(FALSE, printDC);
518 framePrivate->Release();
521 static const int dragBarHeight = 30;
523 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
525 WNDPROC parentProc = usesLayeredWebView() ? DefWebKitProc : DefWindowProc;
529 if (usesLayeredWebView()) {
531 ::GetWindowRect(hWnd, &window);
532 // For testing our transparent window, we need a region to use as a handle for
533 // dragging. The right way to do this would be to query the web view to see what's
534 // under the mouse. However, for testing purposes we just use an arbitrary
535 // 30 pixel band at the top of the view as an arbitrary gripping location.
537 // When we are within this bad, return HT_CAPTION to tell Windows we want to
538 // treat this region as if it were the title bar on a normal window.
539 int y = HIWORD(lParam);
541 if ((y > window.top) && (y < window.top + dragBarHeight))
544 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
546 int wmId = LOWORD(wParam);
547 int wmEvent = HIWORD(wParam);
548 // Parse the menu selections:
551 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
557 PrintView(hWnd, message, wParam, lParam);
560 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
568 if (!gWebView || usesLayeredWebView())
569 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
574 return CallWindowProc(parentProc, hWnd, message, wParam, lParam);
580 #define MAX_URL_LENGTH 1024
582 LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
586 if (wParam == 13) { // Enter Key
587 wchar_t strPtr[MAX_URL_LENGTH];
588 *((LPWORD)strPtr) = MAX_URL_LENGTH;
589 int strLen = SendMessage(hDlg, EM_GETLINE, 0, (LPARAM)strPtr);
591 BSTR bstr = SysAllocStringLen(strPtr, strLen);
597 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
600 return (LRESULT)CallWindowProc((WNDPROC)DefEditProc,hDlg,message,wParam,lParam);
606 // Message handler for about box.
607 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
609 UNREFERENCED_PARAMETER(lParam);
612 return (INT_PTR)TRUE;
615 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
616 EndDialog(hDlg, LOWORD(wParam));
617 return (INT_PTR)TRUE;
621 return (INT_PTR)FALSE;
624 static void loadURL(BSTR urlBStr)
626 IWebFrame* frame = 0;
627 IWebMutableURLRequest* request = 0;
629 static BSTR methodBStr = SysAllocString(TEXT("GET"));
631 if (urlBStr && urlBStr[0] && (PathFileExists(urlBStr) || PathIsUNC(urlBStr))) {
632 TCHAR fileURL[INTERNET_MAX_URL_LENGTH];
633 DWORD fileURLLength = sizeof(fileURL)/sizeof(fileURL[0]);
635 if (SUCCEEDED(UrlCreateFromPath(urlBStr, fileURL, &fileURLLength, 0)))
636 SysReAllocString(&urlBStr, fileURL);
639 HRESULT hr = gWebView->mainFrame(&frame);
643 hr = WebKitCreateInstance(CLSID_WebMutableURLRequest, 0, IID_IWebMutableURLRequest, (void**)&request);
647 hr = request->initWithURL(urlBStr, WebURLRequestUseProtocolCachePolicy, 60);
651 hr = request->setHTTPMethod(methodBStr);
655 hr = frame->loadRequest(request);
659 SetFocus(gViewWindow);