diff options
Diffstat (limited to 'frontends/windows/corewindow.c')
-rw-r--r-- | frontends/windows/corewindow.c | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/frontends/windows/corewindow.c b/frontends/windows/corewindow.c new file mode 100644 index 000000000..d1d761d94 --- /dev/null +++ b/frontends/windows/corewindow.c @@ -0,0 +1,472 @@ +/* + * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file + * win32 generic core window interface. + * + * Provides interface for core renderers to a win32 api client area. + * + * This module is an object that must be encapsulated. Client users + * should embed a struct nsw32_corewindow at the beginning of their + * context for this display surface, fill in relevant data and then + * call nsw32_corewindow_init() + * + * The win32 core window structure requires the callback for draw, key + * and mouse operations. + */ + +#include <assert.h> +#include <string.h> +#include <math.h> +#include <windows.h> +#include <windowsx.h> + +#include "utils/log.h" +#include "utils/utils.h" +#include "utils/messages.h" +#include "utils/utf8.h" +#include "netsurf/keypress.h" +#include "netsurf/mouse.h" +#include "desktop/plot_style.h" + +#include "windows/windbg.h" +#include "windows/corewindow.h" +#include "windows/plot.h" + +static const char windowclassname_corewindow[] = "nswscorewindowwindow"; + +/** + * update the scrollbar visibility and size + */ +static void +update_scrollbars(struct nsw32_corewindow *nsw32_cw) +{ + RECT rc; + SCROLLINFO si; + + GetClientRect(nsw32_cw->hWnd, &rc); + + if (nsw32_cw->content_width > rc.right) { + /* content wider than window area */ + if (nsw32_cw->content_height > rc.bottom) { + /* content higher than window area */ + ShowScrollBar(nsw32_cw->hWnd, SB_BOTH, TRUE); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = nsw32_cw->content_width; + si.nPage = rc.right; + SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, TRUE); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = nsw32_cw->content_height; + si.nPage = rc.bottom; + SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, TRUE); + } else { + /* content shorter than window area */ + ShowScrollBar(nsw32_cw->hWnd, SB_VERT, FALSE); + ShowScrollBar(nsw32_cw->hWnd, SB_HORZ, TRUE); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = nsw32_cw->content_width; + si.nPage = rc.right; + SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, TRUE); + } + } else { + /* content narrower than window area */ + if (nsw32_cw->content_height > rc.bottom) { + /* content higher than window area */ + ShowScrollBar(nsw32_cw->hWnd, SB_HORZ, FALSE); + ShowScrollBar(nsw32_cw->hWnd, SB_VERT, TRUE); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = nsw32_cw->content_height; + si.nPage = rc.bottom; + SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, TRUE); + } else { + /* content shorter than window area */ + ShowScrollBar(nsw32_cw->hWnd, SB_BOTH, FALSE); + } + } + +} + + +/** + * Handle paint messages. + */ +static LRESULT +nsw32_corewindow_paint(struct nsw32_corewindow *nsw32_cw, HWND hwnd) +{ + struct rect clip; + PAINTSTRUCT ps; + SCROLLINFO si; /* scroll information */ + int scrollx; + int scrolly; + + /* get scroll positions */ + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + GetScrollInfo(hwnd, SB_HORZ, &si); + scrollx = si.nPos; + GetScrollInfo(hwnd, SB_VERT, &si); + scrolly = si.nPos; + + BeginPaint(hwnd, &ps); + + plot_hdc = ps.hdc; + + /* content clip rectangle setup */ + clip.x0 = ps.rcPaint.left + scrollx; + clip.y0 = ps.rcPaint.top + scrolly; + clip.x1 = ps.rcPaint.right + scrollx; + clip.y1 = ps.rcPaint.bottom + scrolly; + + nsw32_cw->draw(nsw32_cw, scrollx, scrolly, &clip); + + EndPaint(hwnd, &ps); + + return 0; +} + +static LRESULT +nsw32_corewindow_vscroll(struct nsw32_corewindow *nsw32_cw, + HWND hwnd, + WPARAM wparam) +{ + SCROLLINFO si; /* current scroll information */ + SCROLLINFO usi; /* updated scroll infomation for scrollwindowex */ + + LOG("VSCROLL"); + + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + GetScrollInfo(hwnd, SB_VERT, &si); + usi = si; + + switch (LOWORD(wparam)) { + case SB_TOP: + usi.nPos = si.nMin; + break; + + case SB_BOTTOM: + usi.nPos = si.nMax; + break; + + case SB_LINEUP: + usi.nPos -= 30; + break; + + case SB_LINEDOWN: + usi.nPos += 30; + break; + + case SB_PAGEUP: + usi.nPos -= si.nPage; + break; + + case SB_PAGEDOWN: + usi.nPos += si.nPage; + break; + + case SB_THUMBTRACK: + usi.nPos = si.nTrackPos; + break; + + default: + break; + } + + if (usi.nPos < si.nMin) { + usi.nPos = si.nMin; + } + if (usi.nPos > si.nMax) { + usi.nPos = si.nMax; + } + + SetScrollInfo(hwnd, SB_VERT, &usi, TRUE); + + ScrollWindowEx(hwnd, + 0, + si.nPos - usi.nPos, + NULL, + NULL, + NULL, + NULL, + SW_INVALIDATE); + + /** + * /todo win32 corewindow vertical scrolling needs us to + * compute scroll values and call scrollwindowex() + */ + + return 0; +} + +static LRESULT +nsw32_corewindow_mousedown(struct nsw32_corewindow *nsw32_cw, + int x, int y, + browser_mouse_state button) +{ + nsw32_cw->mouse(nsw32_cw, button, x, y); + return 0; +} + +static LRESULT +nsw32_corewindow_mouseup(struct nsw32_corewindow *nsw32_cw, + int x, int y, + browser_mouse_state button) +{ + nsw32_cw->mouse(nsw32_cw, button, x, y); + return 0; +} + +static LRESULT +nsw32_corewindow_close(struct nsw32_corewindow *nsw32_cw) +{ + nsw32_cw->close(nsw32_cw); + return 0; +} + +/** + * callback for hotlist window win32 events + * + * \param hwnd The win32 window handle + * \param msg The win32 message identifier + * \param wparam The w win32 parameter + * \param lparam The l win32 parameter + */ +static LRESULT CALLBACK +nsw32_window_corewindow_event_callback(HWND hwnd, + UINT msg, + WPARAM wparam, + LPARAM lparam) +{ + struct nsw32_corewindow *nsw32_cw; + + nsw32_cw = GetProp(hwnd, TEXT("CoreWnd")); + if (nsw32_cw != NULL) { + switch (msg) { + case WM_PAINT: /* redraw the exposed part of the window */ + return nsw32_corewindow_paint(nsw32_cw, hwnd); + + case WM_SIZE: + update_scrollbars(nsw32_cw); + break; + + case WM_VSCROLL: + return nsw32_corewindow_vscroll(nsw32_cw, hwnd, wparam); + + case WM_LBUTTONDOWN: + return nsw32_corewindow_mousedown(nsw32_cw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_1); + + case WM_RBUTTONDOWN: + return nsw32_corewindow_mousedown(nsw32_cw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_PRESS_2); + + case WM_LBUTTONUP: + return nsw32_corewindow_mouseup(nsw32_cw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_CLICK_1); + + case WM_RBUTTONUP: + return nsw32_corewindow_mouseup(nsw32_cw, + GET_X_LPARAM(lparam), + GET_Y_LPARAM(lparam), + BROWSER_MOUSE_CLICK_2); + + case WM_CLOSE: + return nsw32_corewindow_close(nsw32_cw); + } + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +/** + * callback from core to request a redraw + */ +static void +nsw32_cw_redraw_request(struct core_window *cw, const struct rect *r) +{ + struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw; + RECT wr; + + wr.left = r->x0; + wr.top = r->y0; + wr.right = r->x1; + wr.bottom = r->y1; + + RedrawWindow(nsw32_cw->hWnd, &wr, NULL, RDW_INVALIDATE | RDW_NOERASE); +} + + +/** + * Callback from the core to update the content area size + */ +static void +nsw32_cw_update_size(struct core_window *cw, int width, int height) +{ + struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw; + + nsw32_cw->content_width = width; + nsw32_cw->content_height = height; + LOG("new content size w:%d h:%d", width, height); + + update_scrollbars(nsw32_cw); +} + + +static void +nsw32_cw_scroll_visible(struct core_window *cw, const struct rect *r) +{ + /** /todo call setscroll apropriately */ +} + + +static void +nsw32_cw_get_window_dimensions(struct core_window *cw, int *width, int *height) +{ + struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw; + + RECT rc; + GetClientRect(nsw32_cw->hWnd, &rc); + *width = rc.right; + *height = rc.bottom; +} + + +static void +nsw32_cw_drag_status(struct core_window *cw, core_window_drag_status ds) +{ + struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw; + nsw32_cw->drag_staus = ds; +} + + +struct core_window_callback_table nsw32_cw_cb_table = { + .redraw_request = nsw32_cw_redraw_request, + .update_size = nsw32_cw_update_size, + .scroll_visible = nsw32_cw_scroll_visible, + .get_window_dimensions = nsw32_cw_get_window_dimensions, + .drag_status = nsw32_cw_drag_status +}; + +/* exported function documented nsw32/corewindow.h */ +nserror +nsw32_corewindow_init(HINSTANCE hInstance, + HWND hWndParent, + struct nsw32_corewindow *nsw32_cw) +{ + DWORD dwStyle; + + /* setup the core window callback table */ + nsw32_cw->cb_table = &nsw32_cw_cb_table; + + /* start with the content area being as small as possible */ + nsw32_cw->content_width = -1; + nsw32_cw->content_height = -1; + + if (hWndParent != NULL) { + dwStyle = WS_CHILDWINDOW | + WS_VISIBLE | + CS_DBLCLKS; + } else { + dwStyle = WS_OVERLAPPEDWINDOW | + WS_HSCROLL | + WS_VSCROLL | + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | + CS_DBLCLKS; + } + + LOG("creating hInstance %p core window", hInstance); + nsw32_cw->hWnd = CreateWindowEx(0, + windowclassname_corewindow, + nsw32_cw->title, + dwStyle, + CW_USEDEFAULT, + CW_USEDEFAULT, + 500, + 400, + hWndParent, + NULL, + hInstance, + NULL); + if (nsw32_cw->hWnd == NULL) { + LOG("Window create failed"); + return NSERROR_NOMEM; + } + + SetProp(nsw32_cw->hWnd, TEXT("CoreWnd"), (HANDLE)nsw32_cw); + + /* zero scroll offsets */ + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = 0; + SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, FALSE); + SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, FALSE); + + return NSERROR_OK; +} + +/* exported interface documented in nsw32/corewindow.h */ +nserror nsw32_corewindow_fini(struct nsw32_corewindow *nsw32_cw) +{ + return NSERROR_OK; +} + + +/* exported interface documented in windows/corewindow.h */ +nserror nsw32_create_corewindow_class(HINSTANCE hInstance) +{ + nserror ret = NSERROR_OK; + WNDCLASSEX wc; + + /* drawable area */ + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = nsw32_window_corewindow_event_callback; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = (HBRUSH)(COLOR_MENU + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = windowclassname_corewindow; + wc.hIconSm = NULL; + + if (RegisterClassEx(&wc) == 0) { + win_perror("CorewindowClass"); + ret = NSERROR_INIT_FAILED; + } + + return ret; +} |