-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Use the focus proxy window in X11 #12751
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
1213ba7
Use the focus proxy window in X11
vlad-lubenskyi edb1a7f
Fix variable naming
vlad-lubenskyi e0f3e85
Adjust X11Window to the name changes in X11FrameProxy
vlad-lubenskyi 597fdf6
Revert whitespace changes to simplify review
vlad-lubenskyi 8696bd2
Reformat X11FocusProxy.cs
vlad-lubenskyi e4bd589
Fix naming in X11Window
vlad-lubenskyi e70b7b2
Remove more whitespace changes
vlad-lubenskyi 00ae1fa
Revert a visibility change
vlad-lubenskyi f011f28
Clean up the focus proxy window
vlad-lubenskyi 2c671a9
Erase _handle on when cleaning up
vlad-lubenskyi 266f5ed
Rename CleanUp -> Cleanup
vlad-lubenskyi 5a92167
Merge branch 'master' into x11-focus-proxy
vlad-lubenskyi 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 hidden or 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 |
---|---|---|
@@ -0,0 +1,79 @@ | ||
using System; | ||
using static Avalonia.X11.XLib; | ||
|
||
namespace Avalonia.X11 | ||
{ | ||
/// <summary> | ||
/// An invisible X window that owns the input focus and forwards events to the owner window. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para> | ||
/// This is a known Linux technique for an auxiliary invisible window to hold the input focus | ||
/// for the main window. It is required by XEmbed protocol, but it also works for regular cases | ||
/// that don't imply embedded windows. | ||
/// </para> | ||
/// </remarks> | ||
/// | ||
/// <see href="https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html" /> | ||
/// <see href="https://gitlab.gnome.org/GNOME/gtk/-/blob/3.22.30/gdk/x11/gdkwindow-x11.c#L823" /> | ||
internal class X11FocusProxy | ||
{ | ||
private const int InvisibleBorder = 0; | ||
private const int DepthCopyFromParent = 0; | ||
private readonly IntPtr _visualCopyFromParent = IntPtr.Zero; | ||
private readonly (int X, int Y) _outOfScreen = (-1, -1); | ||
private readonly (int Width, int Height) _smallest = (1, 1); | ||
|
||
internal readonly IntPtr _handle; | ||
private readonly X11PlatformThreading.EventHandler _ownerEventHandler; | ||
|
||
/// <summary> | ||
/// Initializes instance and creates the underlying X window. | ||
/// </summary> | ||
/// | ||
/// <param name="platform">The X11 platform.</param> | ||
/// <param name="parent">The parent window to proxy the focus for.</param> | ||
/// <param name="eventHandler">An event handler that will handle X events that come to the proxy.</param> | ||
public X11FocusProxy(AvaloniaX11Platform platform, IntPtr parent, | ||
X11PlatformThreading.EventHandler eventHandler) | ||
{ | ||
_handle = PrepareXWindow(platform.Info.Display, parent); | ||
_ownerEventHandler = eventHandler; | ||
platform.Windows[_handle] = OnEvent; | ||
} | ||
|
||
private void OnEvent(ref XEvent ev) | ||
{ | ||
if (ev.type == XEventName.FocusIn || ev.type == XEventName.FocusOut) | ||
{ | ||
this._ownerEventHandler(ref ev); | ||
} | ||
|
||
if (ev.type == XEventName.KeyPress || ev.type == XEventName.KeyRelease) | ||
{ | ||
this._ownerEventHandler(ref ev); | ||
} | ||
} | ||
|
||
private IntPtr PrepareXWindow(IntPtr display, IntPtr parent) | ||
{ | ||
var valueMask = default(EventMask) | ||
| EventMask.FocusChangeMask | ||
| EventMask.KeyPressMask | ||
| EventMask.KeyReleaseMask; | ||
var attrs = new XSetWindowAttributes(); | ||
var handle = XCreateWindow(display, parent, | ||
_outOfScreen.X, _outOfScreen.Y, | ||
_smallest.Width, _smallest.Height, | ||
InvisibleBorder, | ||
DepthCopyFromParent, | ||
(int)CreateWindowArgs.InputOutput, | ||
_visualCopyFromParent, | ||
new UIntPtr((uint)valueMask), | ||
ref attrs); | ||
XMapWindow(display, handle); | ||
XSelectInput(display, handle, new IntPtr((uint)valueMask)); | ||
return handle; | ||
} | ||
} | ||
} |
This file contains hidden or 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
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.
Uh oh!
There was an error while loading. Please reload this page.