blob: dc43a684e5dd4ee2199063e2a64a87c4e9fc9a98 [file] [log] [blame]
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "StdAfx.h"
#include "BrowserWindow.h"
#include "MiniBrowser.h"
#include "Resource.h"
#include <assert.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <vector>
#include <wininet.h>
using namespace std;
BrowserWindow::BrowserWindow()
: m_window(0)
, m_rebarWindow(0)
, m_comboBoxWindow(0)
{
}
LRESULT CALLBACK BrowserWindow::BrowserWindowWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LONG_PTR longPtr = ::GetWindowLongPtr(window, 0);
if (BrowserWindow* browserView = reinterpret_cast<BrowserWindow*>(longPtr))
return browserView->wndProc(window, message, wParam, lParam);
if (message == WM_CREATE) {
LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
BrowserWindow* browserWindow = static_cast<BrowserWindow*>(createStruct->lpCreateParams);
browserWindow->m_window = window;
::SetWindowLongPtr(window, 0, (LONG_PTR)browserWindow);
browserWindow->onCreate(createStruct);
return 0;
}
return ::DefWindowProc(window, message, wParam, lParam);
}
LRESULT BrowserWindow::wndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = 0;
bool handled = true;
switch (message) {
case WM_ERASEBKGND:
lResult = 1;
break;
case WM_COMMAND:
lResult = onCommand(LOWORD(wParam), handled);
break;
case WM_SIZE:
onSize(LOWORD(lParam), HIWORD(lParam));
break;
case WM_DESTROY:
onDestroy();
break;
case WM_NCDESTROY:
onNCDestroy();
break;
default:
handled = false;
}
if (!handled)
lResult = ::DefWindowProc(window, message, wParam, lParam);
return lResult;
}
void BrowserWindow::createWindow(int x, int y, int width, int height)
{
assert(!m_window);
// Register the class.
WNDCLASSEX windowClass = { 0 };
windowClass.cbSize = sizeof(windowClass);
windowClass.style = 0;
windowClass.lpfnWndProc = BrowserWindowWndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = sizeof(this);
windowClass.hInstance = MiniBrowser::shared().instance();
windowClass.hIcon = 0;
windowClass.hCursor = ::LoadCursor(0, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
windowClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINFRAME);
windowClass.lpszClassName = L"MiniBrowser";
windowClass.hIconSm = 0;
::RegisterClassEx(&windowClass);
::CreateWindowW(L"MiniBrowser", L"MiniBrowser", WS_OVERLAPPEDWINDOW, x, y, width, height, 0, 0, MiniBrowser::shared().instance(), this);
}
void BrowserWindow::showWindow()
{
assert(m_window);
::ShowWindow(m_window, SW_SHOWNORMAL);
}
void BrowserWindow::goToURL(const std::wstring& url)
{
m_browserView.goToURL(url);
}
void BrowserWindow::onCreate(LPCREATESTRUCT createStruct)
{
// Register our window.
MiniBrowser::shared().registerWindow(this);
// Create the rebar control.
m_rebarWindow = ::CreateWindowEx(0, REBARCLASSNAME, 0, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN | RBS_VARHEIGHT | RBS_BANDBORDERS,
0, 0, 0, 0, m_window, 0, createStruct->hInstance, 0);
REBARINFO rebarInfo = { 0 };
rebarInfo.cbSize = sizeof(rebarInfo);
rebarInfo.fMask = 0;
::SendMessage(m_rebarWindow, RB_SETBARINFO, 0, (LPARAM)&rebarInfo);
// Create the combo box control.
m_comboBoxWindow = ::CreateWindowEx(0, L"combobox", 0, WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBS_AUTOHSCROLL | CBS_DROPDOWN,
0, 0, 0, 0, m_rebarWindow, 0, createStruct->hInstance, 0);
SendMessage(m_comboBoxWindow, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
REBARBANDINFO bandInfo;
bandInfo.cbSize = sizeof(bandInfo);
bandInfo.fMask = RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
bandInfo.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;
bandInfo.lpText = L"Address";
bandInfo.hwndChild = m_comboBoxWindow;
RECT comboBoxRect;
::GetWindowRect(m_comboBoxWindow, &comboBoxRect);
bandInfo.cx = 100;
bandInfo.cxMinChild = comboBoxRect.right - comboBoxRect.left;
bandInfo.cyMinChild = comboBoxRect.bottom - comboBoxRect.top;
// Add the band to the rebar.
int result = ::SendMessage(m_rebarWindow, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&bandInfo);
// Create the browser view.
RECT webViewRect = { 0, 0, 0, 0};
m_browserView.create(webViewRect, this);
}
void BrowserWindow::onDestroy()
{
MiniBrowser::shared().unregisterWindow(this);
// FIXME: Should we close the browser view here?
}
void BrowserWindow::onNCDestroy()
{
delete this;
}
void BrowserWindow::onSize(int width, int height)
{
RECT rebarRect;
::GetClientRect(m_rebarWindow, &rebarRect);
// Resize the rebar.
::MoveWindow(m_rebarWindow, 0, 0, width, rebarRect.bottom - rebarRect.top, true);
RECT webViewRect;
webViewRect.top = rebarRect.bottom;
webViewRect.left = 0;
webViewRect.right = width;
webViewRect.bottom = height;
m_browserView.setFrame(webViewRect);
}
LRESULT BrowserWindow::onCommand(int commandID, bool& handled)
{
switch (commandID) {
case ID_FILE_NEW_WINDOW:
MiniBrowser::shared().createNewWindow();
break;
case ID_FILE_CLOSE:
::PostMessage(m_window, WM_CLOSE, 0, 0);
break;
case ID_DEBUG_SHOW_WEB_VIEW: {
HMENU menu = ::GetMenu(m_window);
bool shouldHide = ::GetMenuState(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND) & MF_CHECKED;
::CheckMenuItem(menu, ID_DEBUG_SHOW_WEB_VIEW, MF_BYCOMMAND | (shouldHide ? MF_UNCHECKED : MF_CHECKED));
// Show or hide the web view.
HWND webViewWindow = WKViewGetWindow(m_browserView.webView());
::ShowWindow(webViewWindow, shouldHide ? SW_HIDE : SW_SHOW);
break;
}
default:
handled = false;
}
return 0;
}
bool BrowserWindow::handleMessage(const MSG* message)
{
if (message->hwnd != m_comboBoxWindow && !::IsChild(m_comboBoxWindow, message->hwnd))
return false;
// Look for a WM_KEYDOWN message.
if (message->message != WM_KEYDOWN)
return false;
// Look for the VK_RETURN key.
if (message->wParam != VK_RETURN)
return false;
std::vector<WCHAR> buffer;
int textLength = ::GetWindowTextLength(m_comboBoxWindow);
buffer.resize(textLength + 1);
::GetWindowText(m_comboBoxWindow, &buffer[0], buffer.size());
std::wstring url(&buffer[0], buffer.size() - 1);
if (url.find(L"http://"))
url = L"http://" + url;
m_browserView.goToURL(url);
// We handled this message.
return true;
}