better internationalization input support

This commit is contained in:
David Rose 2003-12-26 23:00:28 +00:00
parent 038230f7ec
commit a84c3ffec4
5 changed files with 89 additions and 7 deletions

View File

@ -59,3 +59,15 @@ INLINE Atom glxGraphicsPipe::
get_wm_delete_window() const {
return _wm_delete_window;
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsPipe::get_im
// Access: Public
// Description: Returns the input method opened for the pipe, or NULL
// if the input method could not be opened for some
// reason.
////////////////////////////////////////////////////////////////////
INLINE XIM glxGraphicsPipe::
get_im() const {
return _im;
}

View File

@ -46,6 +46,8 @@ glxGraphicsPipe(const string &display) {
display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY");
}
setlocale(LC_ALL, "");
_is_valid = false;
_supports_fullscreen = false;
_display = NULL;
@ -61,6 +63,12 @@ glxGraphicsPipe(const string &display) {
return;
}
if (!XSupportsLocale()) {
glxdisplay_cat.warning()
<< "X does not support locale " << setlocale(LC_ALL, NULL) << "\n";
}
XSetLocaleModifiers("");
int errorBase, eventBase;
if (!glXQueryExtension(_display, &errorBase, &eventBase)) {
glxdisplay_cat.error()
@ -75,6 +83,27 @@ glxGraphicsPipe(const string &display) {
_display_height = DisplayHeight(_display, _screen);
_is_valid = true;
// Connect to an input method for supporting international text
// entry.
_im = XOpenIM(_display, NULL, NULL, NULL);
if (_im == (XIM)NULL) {
glxdisplay_cat.warning()
<< "Couldn't open input method.\n";
}
// What styles does the current input method support?
/*
XIMStyles *im_supported_styles;
XGetIMValues(_im, XNQueryInputStyle, &im_supported_styles, NULL);
for (int i = 0; i < im_supported_styles->count_styles; i++) {
XIMStyle style = im_supported_styles->supported_styles[i];
cerr << "style " << i << ". " << hex << style << dec << "\n";
}
XFree(im_supported_styles);
*/
// Get the X atom number.
_wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
}
@ -86,6 +115,9 @@ glxGraphicsPipe(const string &display) {
////////////////////////////////////////////////////////////////////
glxGraphicsPipe::
~glxGraphicsPipe() {
if (_im) {
XCloseIM(_im);
}
if (_display) {
XCloseDisplay(_display);
}

View File

@ -32,6 +32,8 @@ typedef int Window;
typedef int XErrorEvent;
typedef int XVisualInfo;
typedef int Atom;
typedef int XIM;
typedef int XIC;
#else
#include <X11/Xlib.h>
#include <GL/glx.h>
@ -54,6 +56,7 @@ public:
INLINE Display *get_display() const;
INLINE int get_screen() const;
INLINE Window get_root() const;
INLINE XIM get_im() const;
INLINE Atom get_wm_delete_window() const;
@ -73,6 +76,7 @@ private:
Display *_display;
int _screen;
Window _root;
XIM _im;
Atom _wm_protocols;
Atom _wm_delete_window;

View File

@ -48,6 +48,7 @@ glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
_display = glx_pipe->get_display();
_screen = glx_pipe->get_screen();
_xwindow = (Window)NULL;
_ic = (XIC)NULL;
_awaiting_configure = false;
_wm_delete_window = glx_pipe->get_wm_delete_window();
@ -162,6 +163,10 @@ process_events() {
XEvent event;
while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
if (XFilterEvent(&event, None)) {
continue;
}
WindowProperties properties;
ButtonHandle button;
@ -195,13 +200,22 @@ process_events() {
case KeyPress:
{
_input_devices[0].set_pointer_in_window(event.xkey.x, event.xkey.y);
int index = ((event.xkey.state & ShiftMask) != 0) ? 1 : 0;
// First, get the keystroke, as modified by the shift key.
KeySym key = XLookupKeysym(&event.xkey, index);
if (key > 0 && key < 128) {
// If it's an ASCII key, press it.
_input_devices[0].keystroke(key);
// First, get the keystroke as a wide-character sequence.
static const int buffer_size = 256;
wchar_t buffer[buffer_size];
Status status;
int len = XwcLookupString(_ic, &event.xkey, buffer, buffer_size, NULL,
&status);
if (status == XBufferOverflow) {
glxdisplay_cat.error()
<< "Overflowed input buffer.\n";
}
// Now each of the returned wide characters represents a
// keystroke.
for (int i = 0; i < len; i++) {
_input_devices[0].keystroke(buffer[i]);
}
// Now get the raw unshifted button.
@ -349,9 +363,14 @@ set_properties_now(WindowProperties &properties) {
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
close_window() {
if (_ic != (XIC)NULL) {
XDestroyIC(_ic);
_ic = (XIC)NULL;
}
if (_xwindow != (Window)NULL) {
XDestroyWindow(_display, _xwindow);
_xwindow = (Window)0;
_xwindow = (Window)NULL;
// This may be necessary if we just closed the last X window in an
// application, so the server hears the close request.
@ -423,6 +442,19 @@ open_window() {
}
set_wm_properties(_properties);
// We don't specify any fancy properties of the XIC. It would be
// nicer if we could support fancy IM's that want preedit callbacks,
// etc., but that can wait until we have an X server that actually
// supports these to test it on.
_ic = XCreateIC
(glx_pipe->get_im(),
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
NULL);
if (_ic == (XIC)NULL) {
glxdisplay_cat.warning()
<< "Couldn't create input context.\n";
}
XMapWindow(_display, _xwindow);
return true;

View File

@ -65,6 +65,8 @@ private:
int _screen;
Window _xwindow;
Colormap _colormap;
XIC _ic;
long _event_mask;
bool _awaiting_configure;
Atom _wm_delete_window;