@@ -64,6 +64,7 @@ internal unsafe partial class X11Window : IWindowImpl, IPopupImpl, IXI2Client
64
64
private RawEventGrouper ? _rawEventGrouper ;
65
65
private bool _useRenderWindow = false ;
66
66
private bool _usePositioningFlags = false ;
67
+ private X11FocusProxy _focusProxy ;
67
68
68
69
private enum XSyncState
69
70
{
@@ -157,6 +158,8 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool ov
157
158
_renderHandle = _handle ;
158
159
159
160
Handle = new PlatformHandle ( _handle , "XID" ) ;
161
+ _focusProxy = new X11FocusProxy ( platform , _handle , OnEvent ) ;
162
+ SetWmClass ( _focusProxy . _handle , "FocusProxy" ) ;
160
163
_realSize = new PixelSize ( defaultWidth , defaultHeight ) ;
161
164
platform . Windows [ _handle ] = OnEvent ;
162
165
XEventMask ignoredMask = XEventMask . SubstructureRedirectMask
@@ -176,7 +179,7 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool ov
176
179
XChangeProperty ( _x11 . Display , _handle , _x11 . Atoms . _NET_WM_WINDOW_TYPE , _x11 . Atoms . XA_ATOM ,
177
180
32 , PropertyMode . Replace , new [ ] { _x11 . Atoms . _NET_WM_WINDOW_TYPE_NORMAL } , 1 ) ;
178
181
179
- SetWmClass ( _platform . Options . WmClass ) ;
182
+ SetWmClass ( _handle , _platform . Options . WmClass ) ;
180
183
}
181
184
182
185
var surfaces = new List < object >
@@ -213,7 +216,7 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool ov
213
216
InitializeIme ( ) ;
214
217
215
218
XChangeProperty ( _x11 . Display , _handle , _x11 . Atoms . WM_PROTOCOLS , _x11 . Atoms . XA_ATOM , 32 ,
216
- PropertyMode . Replace , new [ ] { _x11 . Atoms . WM_DELETE_WINDOW , _x11 . Atoms . _NET_WM_SYNC_REQUEST } , 2 ) ;
219
+ PropertyMode . Replace , new [ ] { _x11 . Atoms . WM_DELETE_WINDOW , _x11 . Atoms . WM_TAKE_FOCUS , _x11 . Atoms . _NET_WM_SYNC_REQUEST } , 3 ) ;
217
220
218
221
if ( _x11 . HasXSync )
219
222
{
@@ -548,6 +551,11 @@ private void OnEvent(ref XEvent ev)
548
551
_xSyncValue . Hi = ev . ClientMessageEvent . ptr4 . ToInt32 ( ) ;
549
552
_xSyncState = XSyncState . WaitConfigure ;
550
553
}
554
+ else if ( ev . ClientMessageEvent . ptr1 == _x11 . Atoms . WM_TAKE_FOCUS )
555
+ {
556
+ IntPtr time = ev . ClientMessageEvent . ptr2 ;
557
+ XSetInputFocus ( _x11 . Display , _focusProxy . _handle , RevertTo . Parent , time ) ;
558
+ }
551
559
}
552
560
}
553
561
else if ( ev . type == XEventName . KeyPress || ev . type == XEventName . KeyRelease )
@@ -922,6 +930,8 @@ private void Cleanup(bool fromDestroyNotification)
922
930
{
923
931
_renderHandle = IntPtr . Zero ;
924
932
}
933
+
934
+ _focusProxy . Cleanup ( ) ;
925
935
}
926
936
927
937
private bool ActivateTransientChildIfNeeded ( )
@@ -1077,7 +1087,7 @@ public void Activate()
1077
1087
else
1078
1088
{
1079
1089
XRaiseWindow ( _x11 . Display , _handle ) ;
1080
- XSetInputFocus ( _x11 . Display , _handle , 0 , IntPtr . Zero ) ;
1090
+ XSetInputFocus ( _x11 . Display , _focusProxy . _handle , 0 , IntPtr . Zero ) ;
1081
1091
}
1082
1092
}
1083
1093
@@ -1169,7 +1179,7 @@ public void SetTitle(string? title)
1169
1179
}
1170
1180
}
1171
1181
1172
- public void SetWmClass ( string wmClass )
1182
+ public void SetWmClass ( IntPtr handle , string wmClass )
1173
1183
{
1174
1184
// See https://tronche.com/gui/x/icccm/sec-4.html#WM_CLASS
1175
1185
// We don't actually parse the application's command line, so we only use RESOURCE_NAME and argv[0]
@@ -1185,7 +1195,7 @@ public void SetWmClass(string wmClass)
1185
1195
{
1186
1196
hint ->res_name = pAppId ;
1187
1197
hint ->res_class = pWmClass ;
1188
- XSetClassHint ( _x11 . Display , _handle , hint ) ;
1198
+ XSetClassHint ( _x11 . Display , handle , hint ) ;
1189
1199
}
1190
1200
1191
1201
XFree ( hint ) ;
0 commit comments