Hello,
I had hard time to show XIM frontend UI on winforms. I'm still not fully
successful[*1], but now
at least I can enable XIM mode with scim.
Note that this patch does not enable internationalized text input yet.
There still seem some
or many issues that block Xutf8LookupString() results.
The patch is somehow questionable:
- I moved call to X11Keyboard.EnsureLayoutInitialized() to
X11Keyboard.ctor(). Without this
iiimx shows inconsistent key state[*2], but I'm not sure if this change
is mandatory.
- Now there are two filters for X11 events:
- for KeyPress and KeyRelease, for FocusWindow (as it used to be done).
- for everything, for IntPtr.Zero (i.e. event.AnyEvent.Window IIRC): it
is required to filter
XIM events out correctly. For example, XIM raises XClientMessageEvent
that should be
filtered out.
[*1] iiimx (atok x3) and kinput2 still fail for me.
[*2] Yes, I still cannot get its UI "show" up, but I can differentiate
its XIM-ish mode and
non-XIM-ish mode by not seeing keyboard inputs to a textbox.
I still need some more changes, but I think those changes could be applied.
Atsushi Eno
Index: System.Windows.Forms/X11Keyboard.cs
===================================================================
--- System.Windows.Forms/X11Keyboard.cs (revision 94997)
+++ System.Windows.Forms/X11Keyboard.cs (working copy)
@@ -43,6 +43,7 @@
private IntPtr display;
private IntPtr window;
private IntPtr xic;
+ private EventMask xic_event_mask = EventMask.NoEventMask;
private StringBuilder lookup_buffer;
private int min_keycode, max_keycode, keysyms_per_keycode, syms;
private int [] keyc2vkey = new int [256];
@@ -61,6 +62,7 @@
this.display = display;
this.window = window;
lookup_buffer = new StringBuilder (24);
+ EnsureLayoutInitialized ();
}
public void EnsureLayoutInitialized ()
@@ -86,10 +88,22 @@
Console.Error.WriteLine ("Could not get XIM");
else
xic = CreateXic (window, xim);
-
+ if (XGetICValues (xic, "filterEvents", out xic_event_mask, IntPtr.Zero) != null)
+ Console.Error.WriteLine ("Could not get XIC values");
+ EventMask mask = EventMask.ExposureMask | EventMask.KeyPressMask | EventMask.FocusChangeMask;
+ xic_event_mask |= mask;
+ XplatUIX11.XSelectInput(display, window, new IntPtr ((int) xic_event_mask));
initialized = true;
}
+ internal IntPtr Window {
+ get { return window; }
+ }
+
+ public EventMask KeyEventMask {
+ get { return xic_event_mask; }
+ }
+
public Keys ModifierKeys {
get {
Keys keys = Keys.None;
@@ -134,8 +148,6 @@
public void KeyEvent (IntPtr hwnd, XEvent xevent, ref MSG msg)
{
- EnsureLayoutInitialized ();
-
XKeySym keysym;
int ascii_chars;
@@ -450,8 +462,6 @@
public int EventToVkey (XEvent e)
{
- EnsureLayoutInitialized ();
-
IntPtr status;
XKeySym ks;
@@ -719,6 +729,9 @@
private static extern IntPtr XCreateIC (IntPtr xim, string name, XIMProperties im_style, string name2, IntPtr value2, string name3, IntPtr value3, IntPtr terminator);
[DllImport ("libX11")]
+ private static extern string XGetICValues (IntPtr xic, string name, out EventMask value, IntPtr terminator);
+
+ [DllImport ("libX11")]
private static extern void XSetICFocus (IntPtr xic);
[DllImport ("libX11")]
Index: System.Windows.Forms/XplatUIX11.cs
===================================================================
--- System.Windows.Forms/XplatUIX11.cs (revision 94997)
+++ System.Windows.Forms/XplatUIX11.cs (working copy)
@@ -508,7 +508,7 @@
SetupAtoms();
// Grab atom changes off the root window to catch certain WM events
- XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int)EventMask.PropertyChangeMask));
+ XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
// Handle any upcoming errors
ErrorHandler = new XErrorHandler(HandleError);
@@ -1560,11 +1560,14 @@
XNextEvent (DisplayHandle, ref xevent);
- if (xevent.AnyEvent.type == XEventName.KeyPress) {
+ if (xevent.AnyEvent.type == XEventName.KeyPress ||
+ xevent.AnyEvent.type == XEventName.KeyRelease) {
if (XFilterEvent(ref xevent, FosterParent)) {
continue;
}
}
+ if (XFilterEvent (ref xevent, IntPtr.Zero))
+ continue;
}
hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
@@ -2671,9 +2674,9 @@
}
lock (XlibLock) {
- XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask)));
+ XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
if (hwnd.whole_window != hwnd.client_window)
- XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
+ XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
}
if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
@@ -5118,6 +5121,7 @@
prev_focus_window = FocusWindow;
FocusWindow = hwnd.client_window;
+ Keyboard.FocusIn (FocusWindow);
if (prev_focus_window != IntPtr.Zero) {
SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list