mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-05 11:28:17 -04:00
better internationalization input support
This commit is contained in:
parent
038230f7ec
commit
a84c3ffec4
@ -59,3 +59,15 @@ INLINE Atom glxGraphicsPipe::
|
|||||||
get_wm_delete_window() const {
|
get_wm_delete_window() const {
|
||||||
return _wm_delete_window;
|
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;
|
||||||
|
}
|
||||||
|
@ -46,6 +46,8 @@ glxGraphicsPipe(const string &display) {
|
|||||||
display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY");
|
display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
_supports_fullscreen = false;
|
_supports_fullscreen = false;
|
||||||
_display = NULL;
|
_display = NULL;
|
||||||
@ -61,6 +63,12 @@ glxGraphicsPipe(const string &display) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!XSupportsLocale()) {
|
||||||
|
glxdisplay_cat.warning()
|
||||||
|
<< "X does not support locale " << setlocale(LC_ALL, NULL) << "\n";
|
||||||
|
}
|
||||||
|
XSetLocaleModifiers("");
|
||||||
|
|
||||||
int errorBase, eventBase;
|
int errorBase, eventBase;
|
||||||
if (!glXQueryExtension(_display, &errorBase, &eventBase)) {
|
if (!glXQueryExtension(_display, &errorBase, &eventBase)) {
|
||||||
glxdisplay_cat.error()
|
glxdisplay_cat.error()
|
||||||
@ -75,6 +83,27 @@ glxGraphicsPipe(const string &display) {
|
|||||||
_display_height = DisplayHeight(_display, _screen);
|
_display_height = DisplayHeight(_display, _screen);
|
||||||
_is_valid = true;
|
_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.
|
// Get the X atom number.
|
||||||
_wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
|
_wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
|
||||||
}
|
}
|
||||||
@ -86,6 +115,9 @@ glxGraphicsPipe(const string &display) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
glxGraphicsPipe::
|
glxGraphicsPipe::
|
||||||
~glxGraphicsPipe() {
|
~glxGraphicsPipe() {
|
||||||
|
if (_im) {
|
||||||
|
XCloseIM(_im);
|
||||||
|
}
|
||||||
if (_display) {
|
if (_display) {
|
||||||
XCloseDisplay(_display);
|
XCloseDisplay(_display);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ typedef int Window;
|
|||||||
typedef int XErrorEvent;
|
typedef int XErrorEvent;
|
||||||
typedef int XVisualInfo;
|
typedef int XVisualInfo;
|
||||||
typedef int Atom;
|
typedef int Atom;
|
||||||
|
typedef int XIM;
|
||||||
|
typedef int XIC;
|
||||||
#else
|
#else
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
@ -54,6 +56,7 @@ public:
|
|||||||
INLINE Display *get_display() const;
|
INLINE Display *get_display() const;
|
||||||
INLINE int get_screen() const;
|
INLINE int get_screen() const;
|
||||||
INLINE Window get_root() const;
|
INLINE Window get_root() const;
|
||||||
|
INLINE XIM get_im() const;
|
||||||
|
|
||||||
INLINE Atom get_wm_delete_window() const;
|
INLINE Atom get_wm_delete_window() const;
|
||||||
|
|
||||||
@ -73,6 +76,7 @@ private:
|
|||||||
Display *_display;
|
Display *_display;
|
||||||
int _screen;
|
int _screen;
|
||||||
Window _root;
|
Window _root;
|
||||||
|
XIM _im;
|
||||||
|
|
||||||
Atom _wm_protocols;
|
Atom _wm_protocols;
|
||||||
Atom _wm_delete_window;
|
Atom _wm_delete_window;
|
||||||
|
@ -48,6 +48,7 @@ glxGraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) :
|
|||||||
_display = glx_pipe->get_display();
|
_display = glx_pipe->get_display();
|
||||||
_screen = glx_pipe->get_screen();
|
_screen = glx_pipe->get_screen();
|
||||||
_xwindow = (Window)NULL;
|
_xwindow = (Window)NULL;
|
||||||
|
_ic = (XIC)NULL;
|
||||||
_awaiting_configure = false;
|
_awaiting_configure = false;
|
||||||
_wm_delete_window = glx_pipe->get_wm_delete_window();
|
_wm_delete_window = glx_pipe->get_wm_delete_window();
|
||||||
|
|
||||||
@ -162,6 +163,10 @@ process_events() {
|
|||||||
|
|
||||||
XEvent event;
|
XEvent event;
|
||||||
while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
|
while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
|
||||||
|
if (XFilterEvent(&event, None)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
WindowProperties properties;
|
WindowProperties properties;
|
||||||
ButtonHandle button;
|
ButtonHandle button;
|
||||||
|
|
||||||
@ -195,13 +200,22 @@ process_events() {
|
|||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
_input_devices[0].set_pointer_in_window(event.xkey.x, event.xkey.y);
|
_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.
|
// First, get the keystroke as a wide-character sequence.
|
||||||
KeySym key = XLookupKeysym(&event.xkey, index);
|
static const int buffer_size = 256;
|
||||||
if (key > 0 && key < 128) {
|
wchar_t buffer[buffer_size];
|
||||||
// If it's an ASCII key, press it.
|
Status status;
|
||||||
_input_devices[0].keystroke(key);
|
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.
|
// Now get the raw unshifted button.
|
||||||
@ -349,9 +363,14 @@ set_properties_now(WindowProperties &properties) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void glxGraphicsWindow::
|
void glxGraphicsWindow::
|
||||||
close_window() {
|
close_window() {
|
||||||
|
if (_ic != (XIC)NULL) {
|
||||||
|
XDestroyIC(_ic);
|
||||||
|
_ic = (XIC)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (_xwindow != (Window)NULL) {
|
if (_xwindow != (Window)NULL) {
|
||||||
XDestroyWindow(_display, _xwindow);
|
XDestroyWindow(_display, _xwindow);
|
||||||
_xwindow = (Window)0;
|
_xwindow = (Window)NULL;
|
||||||
|
|
||||||
// This may be necessary if we just closed the last X window in an
|
// This may be necessary if we just closed the last X window in an
|
||||||
// application, so the server hears the close request.
|
// application, so the server hears the close request.
|
||||||
@ -423,6 +442,19 @@ open_window() {
|
|||||||
}
|
}
|
||||||
set_wm_properties(_properties);
|
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);
|
XMapWindow(_display, _xwindow);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -65,6 +65,8 @@ private:
|
|||||||
int _screen;
|
int _screen;
|
||||||
Window _xwindow;
|
Window _xwindow;
|
||||||
Colormap _colormap;
|
Colormap _colormap;
|
||||||
|
XIC _ic;
|
||||||
|
|
||||||
long _event_mask;
|
long _event_mask;
|
||||||
bool _awaiting_configure;
|
bool _awaiting_configure;
|
||||||
Atom _wm_delete_window;
|
Atom _wm_delete_window;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user