-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent accelerator keys to work when typing text #2056
Merged
amaitland
merged 16 commits into
cefsharp:master
from
OutSystems:PreventAcceleratorKeys
Jan 18, 2018
Merged
Changes from 6 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
749a60f
Support serialization of Classes (previously only structs were suppor…
joaompneves 278a6c4
Added managed methods incterception mechanism
joaompneves c87bc70
Prevent accelerators keys to work when typing text
joaompneves ced0844
Improved keyboard handling
joaompneves e27a8a5
Disable keyboard navigation using arrows, tabs and home/end keys
joaompneves ba72173
Merge branch 'master' into PreventAcceleratorKeys
3a9d334
Fixed identation
joaompneves fa033b6
Fixed identation
joaompneves 1728e9a
Call correct base method and handle text input in case event wasn't h…
joaompneves 26f2414
Merge branch 'master' of https://github.com/OutSystems/CefSharp
joaompneves c880091
Merge from master
joaompneves 4d5cf63
Removed SourceHook method
joaompneves 6d94a91
Merge branch 'master' into PreventAcceleratorKeys
82c4d19
Merge branch 'master' into PreventAcceleratorKeys
b600d09
Added previous keyboard handling logic and ability to use it through …
joaompneves 65adad5
Merge branch 'master' into PreventAcceleratorKeys
amaitland File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,11 +2,8 @@ | |
// | ||
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. | ||
|
||
using CefSharp.Internals; | ||
using CefSharp.Wpf.Internals; | ||
using CefSharp.Wpf.Rendering; | ||
using Microsoft.Win32.SafeHandles; | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Windows; | ||
|
@@ -17,10 +14,12 @@ | |
using System.Windows.Interop; | ||
using System.Windows.Media; | ||
using System.Windows.Threading; | ||
using CefSharp.ModelBinding; | ||
using System.Runtime.CompilerServices; | ||
using CefSharp.Internals; | ||
using CefSharp.Wpf.Internals; | ||
using CefSharp.Wpf.Rendering; | ||
using Microsoft.Win32.SafeHandles; | ||
|
||
namespace CefSharp.Wpf | ||
namespace CefSharp.Wpf | ||
{ | ||
/// <summary> | ||
/// ChromiumWebBrowser is the WPF web browser control | ||
|
@@ -35,10 +34,6 @@ public class ChromiumWebBrowser : ContentControl, IRenderWebBrowser, IWpfWebBrow | |
/// </summary> | ||
private HwndSource source; | ||
/// <summary> | ||
/// The source hook | ||
/// </summary> | ||
private HwndSourceHook sourceHook; | ||
/// <summary> | ||
/// The tooltip timer | ||
/// </summary> | ||
private DispatcherTimer tooltipTimer; | ||
|
@@ -552,7 +547,7 @@ protected virtual void Dispose(bool isDisposing) | |
|
||
Cef.RemoveDisposable(this); | ||
|
||
RemoveSourceHook(); | ||
source = null; | ||
} | ||
} | ||
|
||
|
@@ -1521,8 +1516,6 @@ private void PresentationSourceChangedHandler(object sender, SourceChangedEventA | |
var notifyDpiChanged = DpiScaleFactor > 0 && !DpiScaleFactor.Equals(matrix.M11); | ||
|
||
DpiScaleFactor = source.CompositionTarget.TransformToDevice.M11; | ||
sourceHook = SourceHook; | ||
source.AddHook(sourceHook); | ||
|
||
if (notifyDpiChanged && browser != null) | ||
{ | ||
|
@@ -1538,8 +1531,6 @@ private void PresentationSourceChangedHandler(object sender, SourceChangedEventA | |
} | ||
else if (args.OldSource != null) | ||
{ | ||
RemoveSourceHook(); | ||
|
||
var window = args.OldSource.RootVisual as Window; | ||
if (window != null) | ||
{ | ||
|
@@ -1574,18 +1565,6 @@ private void WindowStateChanged(object sender, EventArgs e) | |
} | ||
} | ||
|
||
/// <summary> | ||
/// Removes the source hook. | ||
/// </summary> | ||
private void RemoveSourceHook() | ||
{ | ||
if (source != null && sourceHook != null) | ||
{ | ||
source.RemoveHook(sourceHook); | ||
source = null; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Create the underlying Browser instance, can be overriden to defer control creation | ||
/// The browser will only be created when size > Size(0,0). If you specify a positive | ||
|
@@ -1782,59 +1761,6 @@ private Popup CreatePopup() | |
return newPopup; | ||
} | ||
|
||
/// <summary> | ||
/// WindowProc callback interceptor. Handles Windows messages intended for the source hWnd, and passes them to the | ||
/// contained browser as needed. | ||
/// </summary> | ||
/// <param name="hWnd">The source handle.</param> | ||
/// <param name="message">The message.</param> | ||
/// <param name="wParam">Additional message info.</param> | ||
/// <param name="lParam">Even more message info.</param> | ||
/// <param name="handled">if set to <c>true</c>, the event has already been handled by someone else.</param> | ||
/// <returns>IntPtr.</returns> | ||
protected virtual IntPtr SourceHook(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled) | ||
{ | ||
if (handled) | ||
{ | ||
return IntPtr.Zero; | ||
} | ||
|
||
switch ((WM)message) | ||
{ | ||
case WM.SYSCHAR: | ||
case WM.SYSKEYDOWN: | ||
case WM.SYSKEYUP: | ||
case WM.KEYDOWN: | ||
case WM.KEYUP: | ||
case WM.CHAR: | ||
case WM.IME_CHAR: | ||
{ | ||
if (!IsKeyboardFocused) | ||
{ | ||
break; | ||
} | ||
|
||
if (message == (int)WM.SYSKEYDOWN && | ||
wParam.ToInt32() == KeyInterop.VirtualKeyFromKey(Key.F4)) | ||
{ | ||
// We don't want CEF to receive this event (and mark it as handled), since that makes it impossible to | ||
// shut down a CefSharp-based app by pressing Alt-F4, which is kind of bad. | ||
return IntPtr.Zero; | ||
} | ||
|
||
if (browser != null) | ||
{ | ||
browser.GetHost().SendKeyEvent(message, wParam.CastToInt32(), lParam.CastToInt32()); | ||
handled = true; | ||
} | ||
|
||
break; | ||
} | ||
} | ||
|
||
return IntPtr.Zero; | ||
} | ||
|
||
/// <summary> | ||
/// Converts a .NET Drag event to a CefSharp MouseEvent | ||
/// </summary> | ||
|
@@ -1972,25 +1898,43 @@ protected override void OnPreviewKeyUp(KeyEventArgs e) | |
/// <param name="e">The <see cref="KeyEventArgs"/> instance containing the event data.</param> | ||
private void OnPreviewKey(KeyEventArgs e) | ||
{ | ||
// As KeyDown and KeyUp bubble, it appears they're being handled before they get a chance to | ||
// trigger the appropriate WM_ messages handled by our SourceHook, so we have to handle these extra keys here. | ||
if (browser != null) | ||
{ | ||
var modifiers = e.GetModifiers(); | ||
var message = (int)(e.IsDown ? WM.KEYDOWN : WM.KEYUP); | ||
var virtualKey = KeyInterop.VirtualKeyFromKey(e.Key); | ||
|
||
browser.GetHost().SendKeyEvent(message, virtualKey, (int)modifiers); | ||
} | ||
|
||
// Hooking the Tab key like this makes the tab focusing in essence work like | ||
// KeyboardNavigation.TabNavigation="Cycle"; you will never be able to Tab out of the web browser control. | ||
// We also add the condition to allow ctrl+a to work when the web browser control is put inside listbox. | ||
// Prevent keyboard navigation using arrows and home and end keys | ||
if (e.Key == Key.Tab || e.Key == Key.Home || e.Key == Key.End || e.Key == Key.Up | ||
|| e.Key == Key.Down || e.Key == Key.Left || e.Key == Key.Right | ||
|| (e.Key == Key.A && Keyboard.Modifiers == ModifierKeys.Control)) | ||
{ | ||
var modifiers = e.GetModifiers(); | ||
var message = (int)(e.IsDown ? WM.KEYDOWN : WM.KEYUP); | ||
var virtualKey = KeyInterop.VirtualKeyFromKey(e.Key); | ||
e.Handled = true; | ||
} | ||
} | ||
|
||
if(browser != null) | ||
/// <summary> | ||
/// Handles the <see cref="E:PreviewTextInput" /> event. | ||
/// </summary> | ||
/// <param name="e">The <see cref="TextCompositionEventArgs"/> instance containing the event data.</param> | ||
protected override void OnPreviewTextInput(TextCompositionEventArgs e) | ||
{ | ||
if (browser != null) | ||
{ | ||
var browserHost = browser.GetHost(); | ||
for (int i = 0; i < e.Text.Length; i++) | ||
{ | ||
browser.GetHost().SendKeyEvent(message, virtualKey, (int)modifiers); | ||
e.Handled = true; | ||
browserHost.SendKeyEvent((int)WM.CHAR, e.Text[i], 0); | ||
} | ||
e.Handled = true; | ||
} | ||
base.OnTextInput(e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should |
||
} | ||
|
||
/// <summary> | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check if (!e.Handled)` here, handle the case where an overriding implementation chooses to handle the input.