2022-07-01 11:42 BST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0002843Buildsystem[All Projects] Generalpublic2022-06-09 08:44
ReporterCameron Cawley 
Assigned To 
PrioritynormalSeverityminorReproducibilityhave not tried
StatusnewResolutionopen 
Summary0002843: [PATCH] windows: Improve keyboard and mouse input in core windows
DescriptionThis patch implements mouse dragging and modifiers, as well as keyboard input.
TagsNo tags attached.
Fixed in CI build #
Reported in CI build #
Attached Files
  • patch file icon 0001-windows-Improve-keyboard-and-mouse-input-in-core-win.patch (11,069 bytes) 2022-02-19 21:27 -
    From 17725fba789c83855bbadd31c74b3e525489d136 Mon Sep 17 00:00:00 2001
    From: Cameron Cawley <ccawley2011@gmail.com>
    Date: Sat, 19 Feb 2022 15:47:36 +0000
    Subject: [PATCH] windows: Improve keyboard and mouse input in core windows
    
    ---
     frontends/windows/corewindow.c | 302 ++++++++++++++++++++++++++++++++-
     frontends/windows/corewindow.h |  15 ++
     2 files changed, 309 insertions(+), 8 deletions(-)
    
    diff --git a/frontends/windows/corewindow.c b/frontends/windows/corewindow.c
    index 9a26efb43..1287966db 100644
    --- a/frontends/windows/corewindow.c
    +++ b/frontends/windows/corewindow.c
    @@ -300,10 +300,11 @@ nsw32_corewindow_hscroll(struct nsw32_corewindow *nsw32_cw,
     
     static LRESULT
     nsw32_corewindow_mousedown(struct nsw32_corewindow *nsw32_cw,
    -			 HWND hwnd,
    +			   HWND hwnd,
     			   int x, int y,
     			   browser_mouse_state button)
     {
    +	struct nsw32_corewindow_mouse *mouse = &nsw32_cw->mouse_state;
     	SCROLLINFO si; /* scroll information */
     
     	/* get scroll positions */
    @@ -314,7 +315,21 @@ nsw32_corewindow_mousedown(struct nsw32_corewindow *nsw32_cw,
     	GetScrollInfo(hwnd, SB_VERT, &si);
     	y += si.nPos;
     
    -	nsw32_cw->mouse(nsw32_cw, button, x, y);
    +	/* record event information for potentially starting a drag. */
    +	mouse->pressed_x = mouse->last_x = x;
    +	mouse->pressed_y = mouse->last_y = y;
    +	mouse->pressed = true;
    +
    +	mouse->state = button;
    +	if ((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000)
    +		mouse->state |= BROWSER_MOUSE_MOD_1;
    +	if ((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000)
    +		mouse->state |= BROWSER_MOUSE_MOD_2;
    +	if ((GetKeyState(VK_MENU) & 0x8000) == 0x8000)
    +		mouse->state |= BROWSER_MOUSE_MOD_3;
    +
    +	nsw32_cw->mouse(nsw32_cw, mouse->state, x, y);
    +
     	return 0;
     }
     
    @@ -324,6 +339,82 @@ nsw32_corewindow_mouseup(struct nsw32_corewindow *nsw32_cw,
     			 int x, int y,
     			 browser_mouse_state button)
     {
    +	struct nsw32_corewindow_mouse *mouse = &nsw32_cw->mouse_state;
    +	bool was_drag = false;
    +	SCROLLINFO si; /* scroll information */
    +
    +	/* get scroll positions */
    +	si.cbSize = sizeof(si);
    +	si.fMask = SIF_POS;
    +	GetScrollInfo(hwnd, SB_HORZ, &si);
    +	x += si.nPos;
    +	GetScrollInfo(hwnd, SB_VERT, &si);
    +	y += si.nPos;
    +
    +	/* only button 1 clicks are considered double clicks. If the
    +	 * mouse state is PRESS then we are waiting for a release to
    +	 * emit a click event, otherwise just reset the state to nothing.
    +	 */
    +	if (mouse->state & BROWSER_MOUSE_DOUBLE_CLICK) {
    +		if (mouse->state & BROWSER_MOUSE_PRESS_1) {
    +			mouse->state ^= BROWSER_MOUSE_PRESS_1 |
    +					BROWSER_MOUSE_CLICK_1;
    +		} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
    +			mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
    +					BROWSER_MOUSE_CLICK_2 |
    +					BROWSER_MOUSE_DOUBLE_CLICK);
    +		}
    +	} else if (mouse->state & BROWSER_MOUSE_PRESS_1) {
    +		mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
    +				 BROWSER_MOUSE_CLICK_1);
    +	} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
    +		mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
    +				 BROWSER_MOUSE_CLICK_2);
    +	} else if (mouse->state & BROWSER_MOUSE_HOLDING_1) {
    +		mouse->state ^= (BROWSER_MOUSE_HOLDING_1 |
    +				 BROWSER_MOUSE_DRAG_ON);
    +		was_drag = true;
    +	} else if (mouse->state & BROWSER_MOUSE_HOLDING_2) {
    +		mouse->state ^= (BROWSER_MOUSE_HOLDING_2 |
    +				 BROWSER_MOUSE_DRAG_ON);
    +		was_drag = true;
    +	}
    +
    +	/* Handle modifiers being removed */
    +	if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
    +	    !((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000)) {
    +		mouse->state ^= BROWSER_MOUSE_MOD_1;
    +	}
    +	if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
    +	    !((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000)) {
    +		mouse->state ^= BROWSER_MOUSE_MOD_2;
    +	}
    +	if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
    +	    !((GetKeyState(VK_MENU) & 0x8000) == 0x8000)) {
    +		mouse->state ^= BROWSER_MOUSE_MOD_3;
    +	}
    +
    +	/* end drag with modifiers */
    +	if (was_drag && (mouse->state & (
    +			BROWSER_MOUSE_MOD_1 |
    +			BROWSER_MOUSE_MOD_2 |
    +			BROWSER_MOUSE_MOD_3))) {
    +		mouse->state = BROWSER_MOUSE_HOVER;
    +	}
    +
    +	nsw32_cw->mouse(nsw32_cw, mouse->state, x, y);
    +
    +	mouse->pressed = false;
    +
    +	return 0;
    +}
    +
    +static LRESULT
    +nsw32_corewindow_mousemove(struct nsw32_corewindow *nsw32_cw,
    +			   HWND hwnd,
    +			   int x, int y)
    +{
    +	struct nsw32_corewindow_mouse *mouse = &nsw32_cw->mouse_state;
     	SCROLLINFO si; /* scroll information */
     
     	/* get scroll positions */
    @@ -334,7 +425,175 @@ nsw32_corewindow_mouseup(struct nsw32_corewindow *nsw32_cw,
     	GetScrollInfo(hwnd, SB_VERT, &si);
     	y += si.nPos;
     
    -	nsw32_cw->mouse(nsw32_cw, button, x, y);
    +	if (!mouse->pressed) {
    +		nsw32_cw->mouse(nsw32_cw,
    +				BROWSER_MOUSE_HOVER,
    +				x,
    +				y);
    +		return 0;
    +	}
    +
    +	if ((abs(x - mouse->last_x) < 5) &&
    +	    (abs(y - mouse->last_y) < 5)) {
    +		/* Mouse hasn't moved far enough from press coordinate
    +		 * for this to be considered a drag.
    +		 */
    +		return 1;
    +	}
    +
    +	/* This is a drag, ensure it's always treated as such, even if
    +	 * we drag back over the press location.
    +	 */
    +	mouse->last_x = INT_MIN;
    +	mouse->last_y = INT_MIN;
    +
    +
    +	if (mouse->state & BROWSER_MOUSE_PRESS_1) {
    +		/* Start button 1 drag */
    +		nsw32_cw->mouse(nsw32_cw,
    +				BROWSER_MOUSE_DRAG_1,
    +				mouse->pressed_x,
    +				mouse->pressed_y);
    +
    +		/* Replace PRESS with HOLDING and declare drag in progress */
    +		mouse->state ^= (BROWSER_MOUSE_PRESS_1 |
    +				 BROWSER_MOUSE_HOLDING_1);
    +		mouse->state |= BROWSER_MOUSE_DRAG_ON;
    +
    +	} else if (mouse->state & BROWSER_MOUSE_PRESS_2) {
    +		/* Start button 2s drag */
    +		nsw32_cw->mouse(nsw32_cw,
    +				BROWSER_MOUSE_DRAG_2,
    +				mouse->pressed_x,
    +				mouse->pressed_y);
    +
    +		/* Replace PRESS with HOLDING and declare drag in progress */
    +		mouse->state ^= (BROWSER_MOUSE_PRESS_2 |
    +				 BROWSER_MOUSE_HOLDING_2);
    +		mouse->state |= BROWSER_MOUSE_DRAG_ON;
    +
    +	} else {
    +		/* continue drag */
    +
    +		/* Handle modifiers being removed */
    +		if ((mouse->state & BROWSER_MOUSE_MOD_1) &&
    +		    !((GetKeyState(VK_SHIFT) & 0x8000) == 0x8000)) {
    +			mouse->state ^= BROWSER_MOUSE_MOD_1;
    +		}
    +		if ((mouse->state & BROWSER_MOUSE_MOD_2) &&
    +		    !((GetKeyState(VK_CONTROL) & 0x8000) == 0x8000)) {
    +			mouse->state ^= BROWSER_MOUSE_MOD_2;
    +		}
    +		if ((mouse->state & BROWSER_MOUSE_MOD_3) &&
    +		    !((GetKeyState(VK_MENU) & 0x8000) == 0x8000)) {
    +			mouse->state ^= BROWSER_MOUSE_MOD_3;
    +		}
    +
    +		if (mouse->state &
    +		    (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2)) {
    +			nsw32_cw->mouse(nsw32_cw,
    +					mouse->state,
    +					x, y);
    +		}
    +	}
    +
    +	return 0;
    +}
    +
    +static LRESULT
    +nsw32_corewindow_unichar(struct nsw32_corewindow *nsw32_cw, WPARAM wparam)
    +{
    +	uint32_t nskey;
    +
    +	if (wparam == UNICODE_NOCHAR) {
    +		return 1;
    +	}
    +
    +	nskey = wparam;
    +	nsw32_cw->key(nsw32_cw, nskey);
    +	return 0;
    +}
    +
    +static LRESULT
    +nsw32_corewindow_char(struct nsw32_corewindow *nsw32_cw, WPARAM wparam)
    +{
    +	uint32_t nskey;
    +
    +	nskey = wparam;
    +
    +	const uint32_t utf16_hi_surrogate_start = 0xD800;
    +	const uint32_t utf16_lo_surrogate_start = 0xDC00;
    +	const uint32_t utf16_surrogate_end = 0xDFFF;
    +
    +	static uint32_t highSurrogate = 0;
    +
    +	if ((nskey >= utf16_hi_surrogate_start) &&
    +	    (nskey < utf16_lo_surrogate_start) ) {
    +		highSurrogate = nskey;
    +	} else {
    +		if ((nskey >= utf16_lo_surrogate_start) &&
    +		    (nskey <= utf16_surrogate_end)) {
    +			uint32_t lowSurrogate = nskey;
    +			nskey = (highSurrogate - utf16_hi_surrogate_start) << 10;
    +			nskey |= ( lowSurrogate - utf16_lo_surrogate_start );
    +			nskey += 0x10000;
    +		}
    +		highSurrogate = 0;
    +
    +		nsw32_cw->key(nsw32_cw, nskey);
    +	}
    +
    +	return 0;
    +}
    +
    +static LRESULT
    +nsw32_corewindow_keydown(struct nsw32_corewindow *nsw32_cw, WPARAM wparam)
    +{
    +	uint32_t i;
    +
    +	switch(wparam) {
    +	case VK_LEFT:
    +		i = NS_KEY_LEFT;
    +		break;
    +
    +	case VK_RIGHT:
    +		i = NS_KEY_RIGHT;
    +		break;
    +
    +	case VK_UP:
    +		i = NS_KEY_UP;
    +		break;
    +
    +	case VK_DOWN:
    +		i = NS_KEY_DOWN;
    +		break;
    +
    +	case VK_HOME:
    +		i = NS_KEY_LINE_START;
    +		break;
    +
    +	case VK_END:
    +		i = NS_KEY_LINE_END;
    +		break;
    +
    +	case VK_DELETE:
    +		i = NS_KEY_DELETE_RIGHT;
    +		break;
    +
    +	case VK_NEXT:
    +		i = NS_KEY_PAGE_DOWN;
    +		break;
    +
    +	case VK_PRIOR:
    +		i = NS_KEY_PAGE_UP;
    +		break;
    +
    +	default:
    +		return 1;
    +	}
    +
    +	nsw32_cw->key(nsw32_cw, i);
    +
     	return 0;
     }
     
    @@ -383,6 +642,11 @@ nsw32_window_corewindow_event_callback(HWND hwnd,
     		case WM_HSCROLL:
     			return nsw32_corewindow_hscroll(nsw32_cw, hwnd, wparam);
     
    +		case WM_MOUSEMOVE:
    +			return nsw32_corewindow_mousemove(nsw32_cw, hwnd,
    +							  GET_X_LPARAM(lparam),
    +							  GET_Y_LPARAM(lparam));
    +
     		case WM_LBUTTONDOWN:
     			return nsw32_corewindow_mousedown(nsw32_cw, hwnd,
     							  GET_X_LPARAM(lparam),
    @@ -395,6 +659,18 @@ nsw32_window_corewindow_event_callback(HWND hwnd,
     							   GET_Y_LPARAM(lparam),
     							   BROWSER_MOUSE_PRESS_2);
     
    +		case WM_LBUTTONDBLCLK:
    +			return nsw32_corewindow_mousedown(nsw32_cw, hwnd,
    +							  GET_X_LPARAM(lparam),
    +							  GET_Y_LPARAM(lparam),
    +							  BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_DOUBLE_CLICK);
    +
    +		case WM_RBUTTONDBLCLK:
    +			return nsw32_corewindow_mousedown(nsw32_cw, hwnd,
    +							   GET_X_LPARAM(lparam),
    +							   GET_Y_LPARAM(lparam),
    +							   BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_DOUBLE_CLICK);
    +
     		case WM_LBUTTONUP:
     			return nsw32_corewindow_mouseup(nsw32_cw, hwnd,
     							GET_X_LPARAM(lparam),
    @@ -407,6 +683,18 @@ nsw32_window_corewindow_event_callback(HWND hwnd,
     							GET_Y_LPARAM(lparam),
     							BROWSER_MOUSE_CLICK_2);
     
    +		case WM_KEYDOWN:
    +			if (nsw32_corewindow_keydown(nsw32_cw, wparam) == 0) {
    +				return 0;
    +			}
    +			break;
    +
    +		case WM_CHAR:
    +			return nsw32_corewindow_char(nsw32_cw, wparam);
    +
    +		case WM_UNICHAR:
    +			return nsw32_corewindow_unichar(nsw32_cw, wparam);
    +
     		case WM_CLOSE:
     			return nsw32_corewindow_close(nsw32_cw);
     		}
    @@ -550,15 +838,13 @@ nsw32_corewindow_init(HINSTANCE hInstance,
     
     	if (hWndParent != NULL) {
     		dwStyle = WS_CHILDWINDOW |
    -			WS_VISIBLE |
    -			CS_DBLCLKS;
    +			WS_VISIBLE;
     	} else {
     		dwStyle = WS_OVERLAPPEDWINDOW |
     			WS_HSCROLL |
     			WS_VSCROLL |
     			WS_CLIPSIBLINGS |
    -			WS_CLIPCHILDREN |
    -			CS_DBLCLKS;
    +			WS_CLIPCHILDREN;
     	}
     
     	NSLOG(netsurf, INFO, "creating hInstance %p core window", hInstance);
    @@ -607,7 +893,7 @@ nserror nsw32_create_corewindow_class(HINSTANCE hInstance)
     
     	/* drawable area */
     	wc.cbSize = sizeof(WNDCLASSEX);
    -	wc.style = 0;
    +	wc.style = CS_DBLCLKS;
     	wc.lpfnWndProc = nsw32_window_corewindow_event_callback;
     	wc.cbClsExtra = 0;
     	wc.cbWndExtra = 0;
    diff --git a/frontends/windows/corewindow.h b/frontends/windows/corewindow.h
    index b91787a85..4678f5b50 100644
    --- a/frontends/windows/corewindow.h
    +++ b/frontends/windows/corewindow.h
    @@ -21,6 +21,18 @@
     
     #include "netsurf/core_window.h"
     
    +/**
    + * nsw32 core window mouse state
    + */
    +struct nsw32_corewindow_mouse {
    +	browser_mouse_state state; /**< last event status */
    +	bool pressed;
    +	int pressed_x;
    +	int pressed_y;
    +	int last_x;
    +	int last_y;
    +};
    +
     /**
      * nsw32 core window state
      */
    @@ -40,6 +52,9 @@ struct nsw32_corewindow {
     	/** window menu */
     	HMENU menu;
     
    +	/** mouse state */
    +	struct nsw32_corewindow_mouse mouse_state;
    +
             /** drag status set by core */
             core_window_drag_status drag_status;
     
    -- 
    2.30.2
    
    

-Relationships
+Relationships

-Notes
jack selleck

~0002367

jack selleck (reporter)

Software testing is essential for isolating and mitigating errors. A good QA process can uncover hundreds or even thousands of defects, and testing teams need to manage all of them. [url=https://www.google.com/maps?cid=15529787422432748750]Leaf filters Springfield IL[/url] Integrating bug tracking into the testing workflow improves efficiency by helping testers prioritize, monitor and report on the status of each error.
Faith SArim

~0002371

Faith SArim (viewer)

That is really nice to hear. thank you for the update and good luck.
- http://sacramento-drywall-pros.business.site/?m=true
Blare Martin

~0002384

Blare Martin (viewer)

I haven't been able to see the Dev CI build on any nightly Windows versions in the past few months. This screen looks incorrect to me.

See: https://www.greenvillelawn.com/edging
Faith SArim

~0002394

Faith SArim (viewer)

If you comment directly on an image that somebody has posted rather than replying to a comment thread, then you get the same error page immediately after posting the comment, but are able to view the original image again later. It's just that the original post then shows up without *any* comments, including yours or any of the others that were previously present!

http://autorepairgarland.com/services
Reza Rahardian

~0002396

Reza Rahardian (reporter)

I don't understand one bit of this thread. And this makes my wanna cry so I'm about to leave this page.
https://gisinfomedia.com
+Notes

-Issue History
Date Modified Username Field Change
2022-02-19 21:27 Cameron Cawley New Issue
2022-02-19 21:27 Cameron Cawley File Added: 0001-windows-Improve-keyboard-and-mouse-input-in-core-win.patch
2022-04-14 15:35 jack selleck Note Added: 0002367
2022-04-20 15:14 Faith SArim Note Added: 0002371
2022-04-28 09:58 Blare Martin Note Added: 0002384
2022-05-27 10:11 Faith SArim Note Added: 0002394
2022-06-09 08:44 Reza Rahardian Note Added: 0002396
+Issue History