NetSurf
corewindow.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * win32 generic core window implementation.
22 *
23 * Provides interface for core renderers to a win32 api client area.
24 *
25 * This module is an object that must be encapsulated. Client users
26 * should embed a struct nsw32_corewindow at the beginning of their
27 * context for this display surface, fill in relevant data and then
28 * call nsw32_corewindow_init()
29 *
30 * The win32 core window structure requires the callback for draw, key
31 * and mouse operations.
32 */
33
34#include <assert.h>
35#include <string.h>
36#include <math.h>
37#include <windows.h>
38#include <windowsx.h>
39
40#include "utils/log.h"
41#include "utils/messages.h"
42#include "utils/utf8.h"
43#include "netsurf/types.h"
44#include "netsurf/keypress.h"
45#include "netsurf/mouse.h"
46
47#include "windows/windbg.h"
48#include "windows/corewindow.h"
49#include "windows/plot.h"
50
51static const char windowclassname_corewindow[] = "nswscorewindowwindow";
52
53/**
54 * update the scrollbar visibility and size
55 */
56static void
58{
59 RECT rc;
60 SCROLLINFO si;
61
62 GetClientRect(nsw32_cw->hWnd, &rc);
63
64 if (nsw32_cw->content_width > rc.right) {
65 /* content wider than window area */
66 if (nsw32_cw->content_height > rc.bottom) {
67 /* content higher than window area */
68 ShowScrollBar(nsw32_cw->hWnd, SB_BOTH, TRUE);
69 si.cbSize = sizeof(SCROLLINFO);
70 si.fMask = SIF_RANGE | SIF_PAGE;
71 si.nMin = 0;
72 si.nMax = nsw32_cw->content_width;
73 si.nPage = rc.right;
74 SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, TRUE);
75 si.cbSize = sizeof(SCROLLINFO);
76 si.fMask = SIF_RANGE | SIF_PAGE;
77 si.nMin = 0;
78 si.nMax = nsw32_cw->content_height;
79 si.nPage = rc.bottom;
80 SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, TRUE);
81 } else {
82 /* content shorter than window area */
83 ShowScrollBar(nsw32_cw->hWnd, SB_VERT, FALSE);
84 ShowScrollBar(nsw32_cw->hWnd, SB_HORZ, TRUE);
85 si.cbSize = sizeof(SCROLLINFO);
86 si.fMask = SIF_RANGE | SIF_PAGE;
87 si.nMin = 0;
88 si.nMax = nsw32_cw->content_width;
89 si.nPage = rc.right;
90 SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, TRUE);
91 }
92 } else {
93 /* content narrower than window area */
94 if (nsw32_cw->content_height > rc.bottom) {
95 /* content higher than window area */
96 ShowScrollBar(nsw32_cw->hWnd, SB_HORZ, FALSE);
97 ShowScrollBar(nsw32_cw->hWnd, SB_VERT, TRUE);
98 si.cbSize = sizeof(SCROLLINFO);
99 si.fMask = SIF_RANGE | SIF_PAGE;
100 si.nMin = 0;
101 si.nMax = nsw32_cw->content_height;
102 si.nPage = rc.bottom;
103 SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, TRUE);
104 } else {
105 /* content shorter than window area */
106 ShowScrollBar(nsw32_cw->hWnd, SB_BOTH, FALSE);
107 }
108 }
109
110}
111
112
113/**
114 * Handle paint messages.
115 */
116static LRESULT
117nsw32_corewindow_paint(struct nsw32_corewindow *nsw32_cw, HWND hwnd)
118{
119 struct rect clip;
120 PAINTSTRUCT ps;
121 SCROLLINFO si; /* scroll information */
122 int scrollx;
123 int scrolly;
124
125 /* get scroll positions */
126 si.cbSize = sizeof(si);
127 si.fMask = SIF_POS;
128 GetScrollInfo(hwnd, SB_HORZ, &si);
129 scrollx = si.nPos;
130 GetScrollInfo(hwnd, SB_VERT, &si);
131 scrolly = si.nPos;
132
133 BeginPaint(hwnd, &ps);
134
135 plot_hdc = ps.hdc;
136
137 /* content clip rectangle setup */
138 clip.x0 = ps.rcPaint.left + scrollx;
139 clip.y0 = ps.rcPaint.top + scrolly;
140 clip.x1 = ps.rcPaint.right + scrollx;
141 clip.y1 = ps.rcPaint.bottom + scrolly;
142
143 nsw32_cw->draw(nsw32_cw, scrollx, scrolly, &clip);
144
145 EndPaint(hwnd, &ps);
146
147 return 0;
148}
149
150static LRESULT
152 HWND hwnd,
153 WPARAM wparam)
154{
155 SCROLLINFO si; /* current scroll information */
156 SCROLLINFO usi; /* updated scroll infomation for scrollwindowex */
157
158 NSLOG(netsurf, INFO, "VSCROLL");
159
160 si.cbSize = sizeof(si);
161 si.fMask = SIF_ALL;
162 GetScrollInfo(hwnd, SB_VERT, &si);
163 usi = si;
164
165 switch (LOWORD(wparam)) {
166 case SB_TOP:
167 usi.nPos = si.nMin;
168 break;
169
170 case SB_BOTTOM:
171 usi.nPos = si.nMax;
172 break;
173
174 case SB_LINEUP:
175 usi.nPos -= 30;
176 break;
177
178 case SB_LINEDOWN:
179 usi.nPos += 30;
180 break;
181
182 case SB_PAGEUP:
183 usi.nPos -= si.nPage;
184 break;
185
186 case SB_PAGEDOWN:
187 usi.nPos += si.nPage;
188 break;
189
190 case SB_THUMBTRACK:
191 usi.nPos = si.nTrackPos;
192 break;
193
194 default:
195 break;
196 }
197
198 if (usi.nPos < si.nMin) {
199 usi.nPos = si.nMin;
200 }
201 if (usi.nPos > si.nMax) {
202 usi.nPos = si.nMax;
203 }
204
205 SetScrollInfo(hwnd, SB_VERT, &usi, TRUE);
206
207 ScrollWindowEx(hwnd,
208 0,
209 si.nPos - usi.nPos,
210 NULL,
211 NULL,
212 NULL,
213 NULL,
214 SW_INVALIDATE);
215
216 /**
217 * /todo win32 corewindow vertical scrolling needs us to
218 * compute scroll values and call scrollwindowex()
219 */
220
221 return 0;
222}
223
224
225static LRESULT
227 HWND hwnd,
228 WPARAM wparam)
229{
230 SCROLLINFO si; /* current scroll information */
231 SCROLLINFO usi; /* updated scroll infomation for scrollwindowex */
232
233 NSLOG(netsurf, INFO, "VSCROLL");
234
235 si.cbSize = sizeof(si);
236 si.fMask = SIF_ALL;
237 GetScrollInfo(hwnd, SB_HORZ, &si);
238 usi = si;
239
240 switch (LOWORD(wparam)) {
241 case SB_LINELEFT:
242 usi.nPos -= 30;
243 break;
244
245 case SB_LINERIGHT:
246 usi.nPos += 30;
247 break;
248
249 case SB_PAGELEFT:
250 usi.nPos -= si.nPage;
251 break;
252
253 case SB_PAGERIGHT:
254 usi.nPos += si.nPage;
255 break;
256
257 case SB_THUMBTRACK:
258 usi.nPos = si.nTrackPos;
259 break;
260
261 default:
262 break;
263 }
264
265 if (usi.nPos < si.nMin) {
266 usi.nPos = si.nMin;
267 }
268 if (usi.nPos > si.nMax) {
269 usi.nPos = si.nMax;
270 }
271
272 SetScrollInfo(hwnd, SB_HORZ, &usi, TRUE);
273
274 ScrollWindowEx(hwnd,
275 si.nPos - usi.nPos,
276 0,
277 NULL,
278 NULL,
279 NULL,
280 NULL,
281 SW_INVALIDATE);
282
283 return 0;
284}
285
286
287static LRESULT
289 HWND hwnd,
290 int x, int y,
291 browser_mouse_state button)
292{
293 SCROLLINFO si; /* scroll information */
294
295 /* get scroll positions */
296 si.cbSize = sizeof(si);
297 si.fMask = SIF_POS;
298 GetScrollInfo(hwnd, SB_HORZ, &si);
299 x += si.nPos;
300 GetScrollInfo(hwnd, SB_VERT, &si);
301 y += si.nPos;
302
303 nsw32_cw->mouse(nsw32_cw, button, x, y);
304 return 0;
305}
306
307static LRESULT
309 HWND hwnd,
310 int x, int y,
311 browser_mouse_state button)
312{
313 SCROLLINFO si; /* scroll information */
314
315 /* get scroll positions */
316 si.cbSize = sizeof(si);
317 si.fMask = SIF_POS;
318 GetScrollInfo(hwnd, SB_HORZ, &si);
319 x += si.nPos;
320 GetScrollInfo(hwnd, SB_VERT, &si);
321 y += si.nPos;
322
323 nsw32_cw->mouse(nsw32_cw, button, x, y);
324 return 0;
325}
326
327static LRESULT
329{
330 nsw32_cw->close(nsw32_cw);
331 return 0;
332}
333
334/**
335 * callback for core window win32 events
336 *
337 * \param hwnd The win32 window handle
338 * \param msg The win32 message identifier
339 * \param wparam The w win32 parameter
340 * \param lparam The l win32 parameter
341 */
342static LRESULT CALLBACK
344 UINT msg,
345 WPARAM wparam,
346 LPARAM lparam)
347{
348 struct nsw32_corewindow *nsw32_cw;
349
350 nsw32_cw = GetProp(hwnd, TEXT("CoreWnd"));
351 if (nsw32_cw != NULL) {
352 switch (msg) {
353 case WM_PAINT: /* redraw the exposed part of the window */
354 return nsw32_corewindow_paint(nsw32_cw, hwnd);
355
356 case WM_SIZE:
357 update_scrollbars(nsw32_cw);
358 break;
359
360 case WM_VSCROLL:
361 return nsw32_corewindow_vscroll(nsw32_cw, hwnd, wparam);
362
363 case WM_HSCROLL:
364 return nsw32_corewindow_hscroll(nsw32_cw, hwnd, wparam);
365
366 case WM_LBUTTONDOWN:
367 return nsw32_corewindow_mousedown(nsw32_cw, hwnd,
368 GET_X_LPARAM(lparam),
369 GET_Y_LPARAM(lparam),
371
372 case WM_RBUTTONDOWN:
373 return nsw32_corewindow_mousedown(nsw32_cw, hwnd,
374 GET_X_LPARAM(lparam),
375 GET_Y_LPARAM(lparam),
377
378 case WM_LBUTTONUP:
379 return nsw32_corewindow_mouseup(nsw32_cw, hwnd,
380 GET_X_LPARAM(lparam),
381 GET_Y_LPARAM(lparam),
383
384 case WM_RBUTTONUP:
385 return nsw32_corewindow_mouseup(nsw32_cw, hwnd,
386 GET_X_LPARAM(lparam),
387 GET_Y_LPARAM(lparam),
389
390 case WM_CLOSE:
391 return nsw32_corewindow_close(nsw32_cw);
392 }
393 }
394
395 return DefWindowProc(hwnd, msg, wparam, lparam);
396}
397
398
399/**
400 * callback from core to request an invalidation of a window area.
401 *
402 * The specified area of the window should now be considered
403 * out of date. If the area is NULL the entire window must be
404 * invalidated.
405 *
406 * \param[in] cw The core window to invalidate.
407 * \param[in] rect area to redraw or NULL for the entire window area.
408 * \return NSERROR_OK on success or appropriate error code.
409 */
410static nserror
411nsw32_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
412{
413 struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
414 RECT *redrawrectp = NULL;
415 RECT redrawrect;
416
417 if (rect != NULL) {
418 SCROLLINFO si; /* scroll information */
419
420 /* get scroll positions */
421 si.cbSize = sizeof(si);
422 si.fMask = SIF_POS;
423 GetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si);
424 redrawrect.left = (long)rect->x0 - si.nPos;
425 redrawrect.right = (long)rect->x1 - si.nPos;
426
427 GetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si);
428 redrawrect.top = (long)rect->y0 - si.nPos;
429 redrawrect.bottom = (long)rect->y1 - si.nPos;
430
431 redrawrectp = &redrawrect;
432 }
433
434 RedrawWindow(nsw32_cw->hWnd,
435 redrawrectp,
436 NULL,
437 RDW_INVALIDATE | RDW_NOERASE);
438
439 return NSERROR_OK;
440}
441
442
443/**
444 * Callback from the core to update the content area size
445 */
446static nserror
447nsw32_cw_update_size(struct core_window *cw, int width, int height)
448{
449 struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
450
451 nsw32_cw->content_width = width;
452 nsw32_cw->content_height = height;
453 NSLOG(netsurf, INFO, "new content size w:%d h:%d", width, height);
454
455 update_scrollbars(nsw32_cw);
456 return NSERROR_OK;
457}
458
459
460static nserror
461nsw32_cw_set_scroll(struct core_window *cw, int x, int y)
462{
463 /** /todo call setscroll apropriately */
464 return NSERROR_OK;
465}
466
467
468static nserror
469nsw32_cw_get_scroll(const struct core_window *cw, int *x, int *y)
470{
471 /** /todo call getscroll apropriately */
473}
474
475
476/**
477 * Callback from the core to obtain the window viewport dimensions
478 *
479 * \param[in] cw the core window object
480 * \param[out] width to be set to viewport width in px
481 * \param[out] height to be set to viewport height in px
482 */
483static nserror
484nsw32_cw_get_window_dimensions(const struct core_window *cw,
485 int *width, int *height)
486{
487 struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
488
489 RECT rc;
490 GetClientRect(nsw32_cw->hWnd, &rc);
491 *width = rc.right;
492 *height = rc.bottom;
493 return NSERROR_OK;
494}
495
496
497static nserror
499{
500 struct nsw32_corewindow *nsw32_cw = (struct nsw32_corewindow *)cw;
501 nsw32_cw->drag_status = ds;
502 return NSERROR_OK;
503}
504
505
508 .set_extent = nsw32_cw_update_size,
509 .set_scroll = nsw32_cw_set_scroll,
510 .get_scroll = nsw32_cw_get_scroll,
511 .get_dimensions = nsw32_cw_get_window_dimensions,
512 .drag_status = nsw32_cw_drag_status
513};
514
516
517/* exported function documented nsw32/corewindow.h */
519nsw32_corewindow_init(HINSTANCE hInstance,
520 HWND hWndParent,
521 struct nsw32_corewindow *nsw32_cw)
522{
523 DWORD dwStyle;
524
525 /* setup the core window callback table */
527
528 /* start with the content area being as small as possible */
529 nsw32_cw->content_width = -1;
530 nsw32_cw->content_height = -1;
531
532 if (hWndParent != NULL) {
533 dwStyle = WS_CHILDWINDOW |
534 WS_VISIBLE |
535 CS_DBLCLKS;
536 } else {
537 dwStyle = WS_OVERLAPPEDWINDOW |
538 WS_HSCROLL |
539 WS_VSCROLL |
540 WS_CLIPSIBLINGS |
541 WS_CLIPCHILDREN |
542 CS_DBLCLKS;
543 }
544
545 NSLOG(netsurf, INFO, "creating hInstance %p core window", hInstance);
546 nsw32_cw->hWnd = CreateWindowEx(0,
548 nsw32_cw->title,
549 dwStyle,
550 CW_USEDEFAULT,
551 CW_USEDEFAULT,
552 500,
553 400,
554 hWndParent,
555 NULL,
556 hInstance,
557 NULL);
558 if (nsw32_cw->hWnd == NULL) {
559 NSLOG(netsurf, INFO, "Window create failed");
560 return NSERROR_NOMEM;
561 }
562
563 SetProp(nsw32_cw->hWnd, TEXT("CoreWnd"), (HANDLE)nsw32_cw);
564
565 /* zero scroll offsets */
566 SCROLLINFO si;
567 si.cbSize = sizeof(si);
568 si.fMask = SIF_POS;
569 si.nPos = 0;
570 SetScrollInfo(nsw32_cw->hWnd, SB_VERT, &si, FALSE);
571 SetScrollInfo(nsw32_cw->hWnd, SB_HORZ, &si, FALSE);
572
573 return NSERROR_OK;
574}
575
576/* exported interface documented in nsw32/corewindow.h */
578{
579 return NSERROR_OK;
580}
581
582
583/* exported interface documented in windows/corewindow.h */
585{
586 nserror ret = NSERROR_OK;
587 WNDCLASSEX wc;
588
589 /* drawable area */
590 wc.cbSize = sizeof(WNDCLASSEX);
591 wc.style = 0;
593 wc.cbClsExtra = 0;
594 wc.cbWndExtra = 0;
595 wc.hInstance = hInstance;
596 wc.hIcon = NULL;
597 wc.hCursor = NULL;
598 wc.hbrBackground = (HBRUSH)(COLOR_MENU + 1);
599 wc.lpszMenuName = NULL;
600 wc.lpszClassName = windowclassname_corewindow;
601 wc.hIconSm = NULL;
602
603 if (RegisterClassEx(&wc) == 0) {
604 win_perror("CorewindowClass");
606 }
607
608 return ret;
609}
core_window_drag_status
drag status passed to drag_status callback
Definition: core_window.h:41
@ CORE_WINDOW_DRAG_NONE
Definition: core_window.h:42
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_INIT_FAILED
Initialisation failed.
Definition: errors.h:38
@ NSERROR_NOT_IMPLEMENTED
Functionality is not implemented.
Definition: errors.h:61
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
Core mouse and pointer states.
browser_mouse_state
Mouse state: 1 is primary mouse button.
Definition: mouse.h:52
@ BROWSER_MOUSE_PRESS_1
primary button pressed
Definition: mouse.h:59
@ BROWSER_MOUSE_CLICK_2
button 2 clicked.
Definition: mouse.h:72
@ BROWSER_MOUSE_PRESS_2
auxillary button pressed
Definition: mouse.h:61
@ BROWSER_MOUSE_CLICK_1
button 1 clicked.
Definition: mouse.h:70
Interface to key press operations.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Localised message support (interface).
int width
Definition: gui.c:160
int height
Definition: gui.c:161
Interface to utility string handling.
Core user interface window function table.
Definition: core_window.h:53
nserror(* invalidate)(struct core_window *cw, const struct rect *rect)
Invalidate an area of a window.
Definition: core_window.h:71
nsw32 core window state
Definition: corewindow.h:29
nserror(* close)(struct nsw32_corewindow *nsw32_cw)
callback for window close event
Definition: corewindow.h:82
const char * title
window title
Definition: corewindow.h:40
core_window_drag_status drag_status
drag status set by core
Definition: corewindow.h:43
nserror(* mouse)(struct nsw32_corewindow *nsw32_cw, browser_mouse_state mouse_state, int x, int y)
callback for mouse event on nsw32 core window
Definition: corewindow.h:74
int content_width
content width
Definition: corewindow.h:34
HWND hWnd
window handle
Definition: corewindow.h:31
int content_height
content height
Definition: corewindow.h:37
nserror(* draw)(struct nsw32_corewindow *nsw32_cw, int scrollx, int scrolly, struct rect *r)
callback to draw on drawable area of nsw32 core window
Definition: corewindow.h:52
Rectangle coordinates.
Definition: types.h:40
int x0
Definition: types.h:41
int y0
Top left.
Definition: types.h:41
int x1
Definition: types.h:42
int y1
Bottom right.
Definition: types.h:42
NetSurf types.
UTF-8 manipulation functions (interface).
void win_perror(const char *lpszFunction)
Definition: windbg.c:633
static LRESULT nsw32_corewindow_close(struct nsw32_corewindow *nsw32_cw)
Definition: corewindow.c:328
static const char windowclassname_corewindow[]
Definition: corewindow.c:51
struct core_window_table nsw32_cw_cb_table
Definition: corewindow.c:506
static nserror nsw32_cw_set_scroll(struct core_window *cw, int x, int y)
Definition: corewindow.c:461
static nserror nsw32_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
Definition: corewindow.c:498
static nserror nsw32_cw_get_window_dimensions(const struct core_window *cw, int *width, int *height)
Callback from the core to obtain the window viewport dimensions.
Definition: corewindow.c:484
static LRESULT nsw32_corewindow_paint(struct nsw32_corewindow *nsw32_cw, HWND hwnd)
Handle paint messages.
Definition: corewindow.c:117
static LRESULT nsw32_corewindow_hscroll(struct nsw32_corewindow *nsw32_cw, HWND hwnd, WPARAM wparam)
Definition: corewindow.c:226
static nserror nsw32_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
callback from core to request an invalidation of a window area.
Definition: corewindow.c:411
nserror nsw32_corewindow_init(HINSTANCE hInstance, HWND hWndParent, struct nsw32_corewindow *nsw32_cw)
initialise elements of nsw32 core window.
Definition: corewindow.c:519
nserror nsw32_create_corewindow_class(HINSTANCE hInstance)
Definition: corewindow.c:584
static LRESULT nsw32_corewindow_mousedown(struct nsw32_corewindow *nsw32_cw, HWND hwnd, int x, int y, browser_mouse_state button)
Definition: corewindow.c:288
nserror nsw32_corewindow_fini(struct nsw32_corewindow *nsw32_cw)
finalise elements of nsw32 core window.
Definition: corewindow.c:577
struct core_window_table * win32_core_window_table
Definition: corewindow.c:515
static void update_scrollbars(struct nsw32_corewindow *nsw32_cw)
update the scrollbar visibility and size
Definition: corewindow.c:57
static LRESULT nsw32_corewindow_mouseup(struct nsw32_corewindow *nsw32_cw, HWND hwnd, int x, int y, browser_mouse_state button)
Definition: corewindow.c:308
static LRESULT CALLBACK nsw32_window_corewindow_event_callback(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
callback for core window win32 events
Definition: corewindow.c:343
static LRESULT nsw32_corewindow_vscroll(struct nsw32_corewindow *nsw32_cw, HWND hwnd, WPARAM wparam)
Definition: corewindow.c:151
static nserror nsw32_cw_update_size(struct core_window *cw, int width, int height)
Callback from the core to update the content area size.
Definition: corewindow.c:447
static nserror nsw32_cw_get_scroll(const struct core_window *cw, int *x, int *y)
Definition: corewindow.c:469
HDC plot_hdc
Definition: plot.c:44
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357