bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: XIM patch


From: Adam Fedor
Subject: Re: XIM patch
Date: Wed, 16 Jan 2002 21:20:45 -0700
User-agent: Mozilla/5.0 (X11; U; Linux ppc; en-US; rv:0.9.4) Gecko/20011009

Christian Gillot wrote:

Sorry to resend that patch I think the attachment wasn't in the
previous mail.

Hi,

  Well, I finally did it. Here is a very first XIM implementation.
It just works for european languages (dead keys/compose).
I've been late making it because I had to learn the OpenStep API before digging deeper GNUstep. Don't hesitate mailing me if something
is wrong in it. I just would like to stress that it's a first
incomplete implementation but it do works.



Well sorry it's been so long, but we've had to put out a few library releases, plus I know XIM is complicated and we want to give it a good look.

First after reading about it, I realize that an input server can be incredibly complicated (particularly for asian languages), so I agree that we don't need to have remote servers of our own, since X already provides them (or interfaces with them via XIM). We just need a proper interface to XIM to exploit it.

Some things we do need however is to be able to switch the input method (on the fly). So anyway, I've rewritten your patch to convert the XIM functions into an encapsulated object (XIMInputServer), which at least makes it easier to switch out the input method (perhaps to a remote server if necessary) or change the XIM modifiers - although I haven't actually implemented any of the code to do this.

Please look at the attached patch (which includes a few other random changes which you can ignore) and see if it still works. I had to fix a few bugs in process_key_codes which caused problems with the key modifiers (command, alt, etc), but perhaps that fix broke something with XIM. I don't know - try to test it with the GSTest app (using Keyboard test and NSTextView test).


--
Adam Fedor, Digital Optics            | I'm glad I hate spinach, because
http://www.doc.com                    | if I didn't, I'd eat it, and you
http://www.gnustep.org                | know how I hate the stuff.
? xim2.patch
? xim.patch
? Documentation/version.texi
? Documentation/unknown.gsdocrefs
? Source/powerpc
Index: Headers/gnustep/xgps/XGContext.h
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Headers/gnustep/xgps/XGContext.h,v
retrieving revision 1.44
diff -c -r1.44 XGContext.h
*** Headers/gnustep/xgps/XGContext.h    19 Oct 2001 03:57:18 -0000      1.44
--- Headers/gnustep/xgps/XGContext.h    17 Jan 2002 04:09:04 -0000
***************
*** 44,50 ****
  #include <X11/Xlib.h>
  #include <X11/Xutil.h>
  
! #include <SharedX/XGGeneric.h>
  
  @class  XGGState;
  
--- 44,50 ----
  #include <X11/Xlib.h>
  #include <X11/Xutil.h>
  
! #include <XGGeneric.h>
  
  @class  XGGState;
  
***************
*** 78,83 ****
--- 78,84 ----
    Window              grabWindow;
    XGDrawMechanism     drawMechanism;
    struct XGGeneric    generic;        /* Defined in XGGeneric.h       */
+   id                    inputServer;
  }
  
  + (Display*) currentXDisplay;
Index: Headers/gnustep/xgps/XGContextWindow.h
===================================================================
RCS file: 
/cvsroot/gnustep/gnustep/core/xgps/Headers/gnustep/xgps/XGContextWindow.h,v
retrieving revision 1.13
diff -c -r1.13 XGContextWindow.h
*** Headers/gnustep/xgps/XGContextWindow.h      17 Dec 2001 21:32:39 -0000      
1.13
--- Headers/gnustep/xgps/XGContextWindow.h      17 Jan 2002 04:09:04 -0000
***************
*** 87,92 ****
--- 87,93 ----
    int                 boff;
    Atom                        protocols[4];
    int                 numProtocols;
+   XIC                   ic;
  } gswindow_device_t;
  
  @interface XGContext (DPSWindow)
Index: Source/GNUmakefile
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Source/GNUmakefile,v
retrieving revision 1.44
diff -c -r1.44 GNUmakefile
*** Source/GNUmakefile  3 Dec 2001 04:32:33 -0000       1.44
--- Source/GNUmakefile  17 Jan 2002 04:09:05 -0000
***************
*** 68,73 ****
--- 68,74 ----
  SharedX/XGContextWindow.m \
  SharedX/XGBitmapImageRep.m \
  SharedX/XGDragView.m \
+ SharedX/XIMInputServer.m \
  XGBitmap.m \
  XGCommonFont.m \
  XGFont.m \
Index: Source/GNUmakefile.postamble
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Source/GNUmakefile.postamble,v
retrieving revision 1.15
diff -c -r1.15 GNUmakefile.postamble
*** Source/GNUmakefile.postamble        4 Dec 2001 11:08:42 -0000       1.15
--- Source/GNUmakefile.postamble        17 Jan 2002 04:09:05 -0000
***************
*** 49,60 ****
  # Things to do before installing
  # before-install::
  
- $(GNUSTEP_HEADERS)/gnustep/xgps/SharedX:
-       $(MKDIRS) $(GNUSTEP_HEADERS)/gnustep/xgps/SharedX
- 
  # Things to do after installing
! after-install:: $(GNUSTEP_HEADERS)/gnustep/xgps/SharedX
!       $(INSTALL_DATA) SharedX/XGGeneric.h 
$(GNUSTEP_HEADERS)/gnustep/xgps/SharedX
  
  # Things to do before uninstalling
  # before-uninstall::
--- 49,57 ----
  # Things to do before installing
  # before-install::
  
  # Things to do after installing
! after-install:: 
!       $(INSTALL_DATA) SharedX/XGGeneric.h $(GNUSTEP_HEADERS)/gnustep/xgps
  
  # Things to do before uninstalling
  # before-uninstall::
Index: Source/XGContext.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Source/XGContext.m,v
retrieving revision 1.88
diff -c -r1.88 XGContext.m
*** Source/XGContext.m  11 Jan 2002 10:07:54 -0000      1.88
--- Source/XGContext.m  17 Jan 2002 04:09:08 -0000
***************
*** 23,31 ****
--- 23,33 ----
     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
  
+ #include "config.h"
  #include "gnustep/xgps/XGContext.h"
  #include "gnustep/xgps/XGGState.h"
  #include "SharedX/xrtools.h"
+ #include "SharedX/XGInputServer.h"
  #include <AppKit/AppKitExceptions.h>
  #include <AppKit/NSAffineTransform.h>
  #include <AppKit/NSColor.h>
***************
*** 382,387 ****
--- 384,391 ----
    XSetErrorHandler(XGErrorHandler);
  
    [self _setupRootWindow];
+   inputServer = [[XIMInputServer allocWithZone: [self zone]] 
+                 initWithDelegate: nil display: dpy name: @"XIM"];
    return self;
  }
  
***************
*** 409,415 ****
    gstack =  NSZoneMalloc(z, sizeof(GSIArray_t));
    GSIArrayInitWithZoneAndCapacity((GSIArray)gstack, z, 2);
    ulist  = [[NSMutableArray allocWithZone: z] initWithCapacity: 32];
!   
    // Set up font cache
    fontid = [NSMutableArray arrayWithCapacity: 32];
  
--- 413,419 ----
    gstack =  NSZoneMalloc(z, sizeof(GSIArray_t));
    GSIArrayInitWithZoneAndCapacity((GSIArray)gstack, z, 2);
    ulist  = [[NSMutableArray allocWithZone: z] initWithCapacity: 32];
! 
    // Set up font cache
    fontid = [NSMutableArray arrayWithCapacity: 32];
  
***************
*** 449,454 ****
--- 453,459 ----
        GSIArrayEmpty((GSIArray)gstack);
        NSZoneFree([self zone], gstack);
        DESTROY(ulist);
+       DESTROY(inputServer);
        // FIXME: This wont work with garbage collection
        AUTORELEASE(RETAIN(self));
      }
Index: Source/SharedX/XGContextEvent.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Source/SharedX/XGContextEvent.m,v
retrieving revision 1.80
diff -c -r1.80 XGContextEvent.m
*** Source/SharedX/XGContextEvent.m     9 Jan 2002 20:46:21 -0000       1.80
--- Source/SharedX/XGContextEvent.m     17 Jan 2002 04:09:17 -0000
***************
*** 22,27 ****
--- 22,30 ----
     License along with this library; if not, write to the Free
     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
+ 
+ #include "config.h"
+ 
  #include <AppKit/AppKitExceptions.h>
  #include <AppKit/NSGraphics.h>
  #include <AppKit/NSWindow.h>
***************
*** 45,50 ****
--- 48,54 ----
  #include "gnustep/xgps/XGContextPrivate.h"
  #include "XGDrawingEngine.h"
  #endif
+ #include "SharedX/XGInputServer.h"
  #include "SharedX/XGDragView.h"
  #include "SharedX/XGGeneric.h"
  #include "SharedX/xrtools.h"
***************
*** 251,258 ****
        // loop and grab all of the events from the X queue
        while (count-- > 0)
        {
-         //NSDebugLLog(@"NSEvent", @"Get next XWindows event\n");
          XNextEvent(XDPY, &xEvent);
          switch (xEvent.type)
            {
              // mouse button events
--- 255,270 ----
        // loop and grab all of the events from the X queue
        while (count-- > 0)
        {
          XNextEvent(XDPY, &xEvent);
+ 
+ #ifdef USE_XIM
+         if (XFilterEvent(&xEvent, None)) 
+           {
+             NSDebugLLog(@"NSKeyEvent", @"Event filtered (by XIM?)\n");
+             continue;
+           }
+ #endif
+ 
          switch (xEvent.type)
            {
              // mouse button events
***************
*** 1045,1051 ****
                break;
  
              case MotionNotify:
!               NSDebugLLog(@"NSEvent", @"%d MotionNotify - %d %d\n",
                  xEvent.xmotion.window, xEvent.xmotion.x, xEvent.xmotion.y);
                {
                  unsigned int  state;
--- 1057,1063 ----
                break;
  
              case MotionNotify:
!               NSDebugLLog(@"NSMotionEvent", @"%d MotionNotify - %d %d\n",
                  xEvent.xmotion.window, xEvent.xmotion.x, xEvent.xmotion.y);
                {
                  unsigned int  state;
***************
*** 1306,1314 ****
  static NSEvent*
  process_key_event (XEvent* xEvent, XGContext* context, NSEventType eventType)
  {
-   char        buf[256];
-   int count;
-   XComposeStatus compose;
    NSString    *keys, *ukeys;
    KeySym      keysym;
    NSPoint     eventLocation;
--- 1318,1323 ----
***************
*** 1320,1331 ****
    int         control_key = 0;
    int         command_key = 0;
    int         alt_key = 0;
    
-   NSDebugLog(@"Process key event");
- 
    if (_is_keyboard_initialized == NO)
      initialize_keyboard ();
  
    /* Process NSFlagsChanged events.  We can't use a switch because we
       are not comparing to constants. */
    if (xEvent->xkey.keycode == _control_keycodes[0]) 
--- 1329,1351 ----
    int         control_key = 0;
    int         command_key = 0;
    int         alt_key = 0;
+   Display *display = [XGContext currentXDisplay];
    
    if (_is_keyboard_initialized == NO)
      initialize_keyboard ();
  
+   /* Process location */
+   window = [XGContext _windowWithTag: [[NSApp keyWindow] windowNumber]];
+   eventLocation.x = xEvent->xbutton.x;
+   if (window)
+     {
+       eventLocation.y = window->siz_hints.height - xEvent->xbutton.y;
+     }
+   else
+     {
+       eventLocation.y = xEvent->xbutton.y;
+     }
+     
    /* Process NSFlagsChanged events.  We can't use a switch because we
       are not comparing to constants. */
    if (xEvent->xkey.keycode == _control_keycodes[0]) 
***************
*** 1375,1406 ****
            _alt_pressed &= ~alt_key;
        }
      }
!   
    /* Process modifiers */
    eventFlags = process_modifier_flags (xEvent->xkey.state);
  
!   /* Process location */
!   window = [XGContext _windowWithTag: [[NSApp keyWindow] windowNumber]];
!   eventLocation.x = xEvent->xbutton.x;
!   if (window)
!     {
!       eventLocation.y = window->siz_hints.height - xEvent->xbutton.y;
!     }
!   else
!     {
!       eventLocation.y = xEvent->xbutton.y;
!     }
!   
!   NSDebugLog (@"keysym=%d, xLocation = (%d, %d), userLocation = (%f, %f)",
!             keysym, xEvent->xbutton.x, xEvent->xbutton.y,
!             eventLocation.x, eventLocation.y);
!   
    /* Process keycode */
    keyCode = ((XKeyEvent *)xEvent)->keycode;
!   
!   /* Process characters */
!   count = XLookupString ((XKeyEvent *)xEvent, buf, 256, &keysym, &compose);
  
    /* Add NSNumericPadKeyMask if the key is in the KeyPad */
    if (IsKeypadKey (keysym))
      eventFlags = eventFlags | NSNumericPadKeyMask;
--- 1395,1417 ----
            _alt_pressed &= ~alt_key;
        }
      }
! 
    /* Process modifiers */
    eventFlags = process_modifier_flags (xEvent->xkey.state);
  
!   /* Process characters */
!   keys = [context->inputServer lookupStringForEvent: (XKeyEvent *)xEvent
!                window: window
!                keysym: &keysym];
! 
    /* Process keycode */
    keyCode = ((XKeyEvent *)xEvent)->keycode;
!   //keyCode = XKeysymToKeycode(display,keysym);
  
+   NSDebugLLog (@"NSKeyEvent", 
+                @"keysym=%d, keyCode=%d originalkeyCode=%d flags=%d",
+                keysym, keyCode, ((XKeyEvent *)xEvent)->keycode, eventFlags);
+   
    /* Add NSNumericPadKeyMask if the key is in the KeyPad */
    if (IsKeypadKey (keysym))
      eventFlags = eventFlags | NSNumericPadKeyMask;
***************
*** 1412,1438 ****
    /* if (IsFunctionKey (keysym) || IsMiscFunctionKey (keysym))
         eventFlags = eventFlags | NSFunctionKeyMask; */
  
-   // Make sure that the string is properly terminated
-   if (count > 255)
-     buf[255] = '\0';
-   else
-     {
-       if (count < 1) 
-       buf[0] = '\0';
-       else           
-       buf[count] = '\0';
-     }
- 
    /* Now we get the unicode character for the pressed key using 
       our internal table */
    unicode = process_char (keysym, &eventFlags);
  
    /* If that didn't work, we use what X gave us */
!   if (unicode == 0)
!     {
!       keys = [NSString stringWithCString: buf];
!     }
!   else
      {
        keys = [NSString stringWithCharacters: &unicode  length: 1];
      }
--- 1423,1434 ----
    /* if (IsFunctionKey (keysym) || IsMiscFunctionKey (keysym))
         eventFlags = eventFlags | NSFunctionKeyMask; */
  
    /* Now we get the unicode character for the pressed key using 
       our internal table */
    unicode = process_char (keysym, &eventFlags);
  
    /* If that didn't work, we use what X gave us */
!   if (unicode != 0)
      {
        keys = [NSString stringWithCharacters: &unicode  length: 1];
      }
***************
*** 1440,1470 ****
    // Now the same ignoring modifiers, except Shift, ShiftLock, NumLock.
    xEvent->xkey.state = (xEvent->xkey.state & (ShiftMask | LockMask 
                                              | _num_lock_mask));
!   count = XLookupString ((XKeyEvent *)xEvent, buf, 256, &keysym, &compose);
!   
!   // Make sure that the string is properly terminated
!   if (count > 255)
!     buf[255] = '\0';
!   else
!     {
!       if (count < 1)
!       buf[0] = '\0';
!       else
!       buf[count] = '\0';
!     }
! 
    unicode = process_char (keysym, &eventFlags);
! 
!   if (unicode == 0)
!     {
!       ukeys = [NSString stringWithCString: buf];
!     }
!   else
      {
        ukeys = [NSString stringWithCharacters: &unicode  length: 1];
      }
  
!   if (unicode == 0 && *buf == '\0' 
        && context->generic.lastKeyFlags != eventFlags)
      {
        eventType = NSFlagsChanged;
--- 1436,1451 ----
    // Now the same ignoring modifiers, except Shift, ShiftLock, NumLock.
    xEvent->xkey.state = (xEvent->xkey.state & (ShiftMask | LockMask 
                                              | _num_lock_mask));
!   ukeys = [context->inputServer lookupStringForEvent: (XKeyEvent *)xEvent
!                 window: window
!                 keysym: &keysym];
    unicode = process_char (keysym, &eventFlags);
!   if (unicode != 0)
      {
        ukeys = [NSString stringWithCharacters: &unicode  length: 1];
      }
  
!   if (unicode == 0 && [ukeys length] == 0
        && context->generic.lastKeyFlags != eventFlags)
      {
        eventType = NSFlagsChanged;
***************
*** 1728,1731 ****
  }
  
  @end
- 
--- 1709,1711 ----
Index: Source/SharedX/XGContextWindow.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/xgps/Source/SharedX/XGContextWindow.m,v
retrieving revision 1.92
diff -c -r1.92 XGContextWindow.m
*** Source/SharedX/XGContextWindow.m    9 Jan 2002 20:46:21 -0000       1.92
--- Source/SharedX/XGContextWindow.m    17 Jan 2002 04:09:24 -0000
***************
*** 22,27 ****
--- 22,28 ----
     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
  
+ #include "config.h"
  #include <math.h>
  #include <Foundation/NSString.h>
  #include <Foundation/NSArray.h>
***************
*** 29,34 ****
--- 30,36 ----
  #include <AppKit/NSGraphics.h>
  
  #include "SharedX/XGDragView.h"
+ #include "SharedX/XGInputServer.h"
  
  #ifdef XDPS_BACKEND_LIBRARY
  #define XGContext       NSDPSContext
***************
*** 1015,1020 ****
--- 1017,1023 ----
    window->region = XCreateRegion();
    window->buffer = 0;
    window->alpha_buffer = 0;
+   window->ic = 0;
  
    // make sure that new window has the correct cursor
    [self _initializeCursorForXWindow: window->ident];
***************
*** 1047,1052 ****
--- 1050,1059 ----
      return;
  
    NSDebugLLog(@"XGTrace", @"DPSwindow: %d", num);
+   if (window->ic)
+     {
+       [inputServer ximCloseIC: window->ic];
+     }
    if (window->ident)
      {
        XDestroyWindow(XDPY, window->ident);
***************
*** 2087,2092 ****
--- 2094,2100 ----
    generic.desiredFocusWindow = win;
    generic.focusRequestNumber = XNextRequest(XDPY);
    XSetInputFocus(XDPY, window->ident, RevertToParent, generic.lastTime);
+   [inputServer ximFocusICWindow: window];
  }
  
  /*
Index: Source/SharedX/XGInputServer.h
===================================================================
RCS file: Source/SharedX/XGInputServer.h
diff -N Source/SharedX/XGInputServer.h
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- Source/SharedX/XGInputServer.h      17 Jan 2002 04:09:27 -0000
***************
*** 0 ****
--- 1,55 ----
+ /* XGInputServer - Keyboard input handling
+ 
+    Copyright (C) 2002 Free Software Foundation, Inc.
+ 
+    Author: Adam Fedor <fedor@gnu.org>
+    Date: January 2002
+ 
+    This file is part of the GNUstep GUI Library.
+ 
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+    
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+ 
+    You should have received a copy of the GNU Library General Public
+    License along with this library; see the file COPYING.LIB.
+    If not, write to the Free Software Foundation,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */ 
+ 
+ #ifndef _GNUstep_H_XGInputServer
+ #define _GNUstep_H_XGInputServer
+ 
+ #include <AppKit/NSInputServer.h>
+ #include "gnustep/xgps/XGContextWindow.h"
+ 
+ @protocol XInputFiltering
+ - (BOOL) filterEvent: (XEvent *)event;
+ - (NSString *) lookupStringForEvent: (XKeyEvent *)event 
+                            window: (gswindow_device_t *)window
+                              keysym: (KeySym *)keysymptr;
+ @end
+ 
+ 
+ @interface XIMInputServer: NSInputServer <XInputFiltering>
+ {
+   id delegate;
+   NSString *server_name;
+   XIM xim;
+   XIMStyle xim_style;
+ }
+ 
+ - (id) initWithDelegate: (id)aDelegate
+               display: (Display *)dpy
+                  name: (NSString *)name;
+ - (void) ximFocusICWindow: (gswindow_device_t *)windev;
+ - (void) ximCloseIC: (XIC)xic;
+ @end
+ 
+ #endif
Index: Source/SharedX/XIMInputServer.m
===================================================================
RCS file: Source/SharedX/XIMInputServer.m
diff -N Source/SharedX/XIMInputServer.m
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- Source/SharedX/XIMInputServer.m     17 Jan 2002 04:09:27 -0000
***************
*** 0 ****
--- 1,288 ----
+ /* XIMInputServer - XIM Keyboard input handling
+ 
+    Copyright (C) 2002 Free Software Foundation, Inc.
+ 
+    Author: Christian Gillot <cgillot@neo-rousseaux.org>
+    Date: Nov 2001
+    Author: Adam Fedor <fedor@gnu.org>
+    Date: Jan 2002
+ 
+    This file is part of the GNUstep GUI Library.
+ 
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+    
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+ 
+    You should have received a copy of the GNU Library General Public
+    License along with this library; see the file COPYING.LIB.
+    If not, write to the Free Software Foundation,
+    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */ 
+ 
+ #include "config.h"
+ #include "XGInputServer.h"
+ 
+ @interface XIMInputServer (XIMPrivate)
+ - (BOOL) ximInit: (Display *)dpy;
+ - (void) ximClose;
+ - (int) ximStyleInit;
+ - (XIC) ximCreateIC: (Window)w;
+ - (unsigned long) ximXicGetMask: (XIC)xic;
+ @end
+ 
+ @implementation XIMInputServer
+ 
+ - (id) initWithDelegate: (id)aDelegate
+                  name: (NSString *)name
+ {
+   Display *dpy = [XGContext currentXDisplay];
+   return [self initWithDelegate: aDelegate display: dpy name: name];
+ }
+ 
+ - (id) initWithDelegate: (id)aDelegate
+               display: (Display *)dpy
+                  name: (NSString *)name
+ {
+   delegate = aDelegate;
+   ASSIGN(server_name, name);
+ 
+ #if USE_XIM
+   if ([self ximInit: dpy] == NO)
+     {
+       NSLog(@"Error occured while initializing XIM");
+       [self dealloc];
+       return nil;
+     }
+ #endif
+   return self;
+ }
+ 
+ - (void) dealloc
+ {
+   DESTROY(server_name);
+   [self ximClose];
+ }
+ 
+ /* ----------------------------------------------------------------------
+    XInputFiltering protocol methods
+ */
+ - (BOOL) filterEvent: (XEvent *)event
+ {
+   if (XFilterEvent(event, None)) 
+     {
+       NSDebugLLog(@"NSKeyEvent", @"Event filtered by XIM\n");
+       return YES;
+     }
+   return NO;
+ }
+ 
+ #define BUF_LEN 255
+ 
+ - (NSString *) lookupStringForEvent: (XKeyEvent *)event 
+                            window: (gswindow_device_t *)windev
+                            keysym: (KeySym *)keysymptr
+ {
+   int count;
+   Status status;
+   NSString *keys;
+   KeySym   keysym;
+   XComposeStatus compose;
+   char buf[BUF_LEN+1];
+ 
+   /* Process characters */
+   if (windev->ic)
+     {
+       count = XmbLookupString(windev->ic, event, buf, BUF_LEN, 
+                             &keysym, &status);
+       // FIXME: code this
+       if (status==XBufferOverflow)
+       NSDebugLLog(@"NSKeyEvent",@"XmbLookupString buffer overflow\n");
+     }
+   else 
+     {
+       count = XLookupString (event, buf, BUF_LEN, &keysym, &compose);
+     }
+ 
+   // Make sure that the string is properly terminated
+   if (count > BUF_LEN)
+     buf[BUF_LEN] = '\0';
+   else
+     {
+       if (count < 1) 
+       buf[0] = '\0';
+       else           
+       buf[count] = '\0';
+     }
+   keys = [NSString stringWithCString: buf];
+ 
+   if (keysymptr)
+     *keysymptr = keysym;
+ 
+   return keys;
+ }
+ 
+ /* ----------------------------------------------------------------------
+    NSInputServiceProvider protocol methods
+ */
+ - (void) activeConversationChanged: (id)sender
+                toNewConversation: (long)newConversation
+ {
+   NSWindow *window;
+   gswindow_device_t *windev;
+ 
+   [super activeConversationChanged: sender
+                toNewConversation: newConversation];
+ 
+   if ([sender respondsToSelector: @selector(window)] == NO)
+     {
+       [NSException raise: NSInvalidArgumentException
+                   format: @"NSTextInput sender does not respond to window"];
+     }
+   window = [sender window];
+   windev = [XGContext _windowWithTag: [window windowNumber]];
+   if (windev == NULL)
+     {
+       [NSException raise: NSInvalidArgumentException
+                   format: @"NSTextInput sender has invalid window"];
+     }
+ 
+   [self ximFocusICWindow: windev];
+ }
+ 
+ - (void) activeConversationWillChange: (id)sender
+                 fromOldConversation: (long)oldConversation
+ {
+   [super activeConversationWillChange: sender
+                 fromOldConversation: oldConversation];
+ }
+ 
+ /* ----------------------------------------------------------------------
+    XIM private methods
+ */
+ - (BOOL) ximInit: (Display *)dpy
+ {
+   XClassHint class_hints;
+ 
+   if (!XSupportsLocale ())
+     {
+       NSDebugLLog(@"XIM", @"locale not supported by Xlib\n");
+       /* FIXME: Should we reset the locale or just hope that X 
+        can deal with it? */
+       //setlocale (LC_ALL, "C");
+     }
+   
+   if (!XSetLocaleModifiers (""))
+     NSDebugLLog(@"XIM", @"can not set locale modifiers\n");
+ 
+   /* FIXME: Get these */
+   class_hints.res_name = class_hints.res_class = NULL;
+   xim = XOpenIM(dpy, NULL, class_hints.res_name, class_hints.res_class);
+   if (xim == NULL) 
+     {
+       NSDebugLLog(@"XIM", @"Can't open XIM.\n");
+       return NO;
+     }
+ 
+   if (![self ximStyleInit])
+     {
+       [self ximClose];
+       return NO;
+     }
+ 
+   NSDebugLLog(@"XIM", @"Initialized XIM\n");
+   return YES;
+ }
+ 
+ - (int) ximStyleInit
+ {
+   /* FIXME: Right now we only support this style *but*
+      this is only temporary */
+   XIMStyle xim_supported_style=XIMPreeditNothing|XIMStatusNothing;
+   XIMStyles *styles;
+   char *failed_arg;
+   int i;
+ 
+   failed_arg = XGetIMValues(xim,XNQueryInputStyle,&styles,NULL);
+   if (failed_arg!=NULL)
+     {
+       NSDebugLLog(@"XIM", @"Can't getting the following IM value :%s",
+                 failed_arg);
+       return 0;
+     } 
+ 
+   for (i=0;i<styles->count_styles;i++)
+     {
+       if (styles->supported_styles[i]==xim_supported_style)
+       {
+         xim_style=xim_supported_style;
+         XFree(styles);
+         return 1;
+       }
+     }
+ 
+   XFree(styles);
+   return 0;
+ }
+ 
+ - (void) ximClose
+ {
+   NSDebugLLog(@"XIM", @"Closed XIM\n");
+   if (xim)
+     XCloseIM(xim);
+   xim=NULL;
+ }
+ 
+ - (void) ximFocusICWindow: (gswindow_device_t *)windev
+ {
+   /* Make sure we have an ic for this window */
+ #if USE_XIM
+   if (windev->ic == NULL)
+     {
+       windev->ic = [self ximCreateIC: windev->ident];
+       if (windev->ic == NULL) 
+       {
+         [self ximClose];
+       }
+     }
+ #endif
+   
+   /* Now set focus to this window */
+   if (windev->ic)
+     {
+       NSDebugLLog(@"XIM", @"XSetICFocus to window %p", 
+                 windev->ident);
+       XSetICFocus(windev->ic);
+     }
+ }
+ 
+ - (XIC) ximCreateIC: (Window)w
+ {
+   XIC xic;
+   xic = XCreateIC(xim, XNClientWindow, w, XNInputStyle,
+                 xim_style, XNFocusWindow, w, NULL);
+   if (xic==NULL)
+     NSDebugLLog(@"XIM", @"Can't create the input context.\n");
+   return xic;
+ }
+ 
+ - (unsigned long) ximXicGetMask: (XIC)xic
+ {
+   unsigned long xic_xmask = 0;
+   if (XGetICValues(xic,XNFilterEvents,&xic_xmask,NULL)!=NULL)
+     NSDebugLLog(@"XIM", @"Can't get the event mask for that input context");
+ 
+   return xic_xmask;
+ }
+ 
+ - (void) ximCloseIC: (XIC)xic
+ {
+   XDestroyIC(xic);
+ }
+ 
+ @end

reply via email to

[Prev in Thread] Current Thread [Next in Thread]