add initial support for IME candidate strings in-game

This commit is contained in:
David Rose 2004-04-02 01:44:28 +00:00
parent 9315342da7
commit a28b2a8006
18 changed files with 315 additions and 5 deletions

View File

@ -191,3 +191,16 @@ void GraphicsWindowInputDevice::
keystroke(int keycode, double time) {
_button_events.push_back(ButtonEvent(keycode, time));
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsWindowInputDevice::candidate
// Access: Public
// Description: Records that the indicated candidate string has been
// highlighted.
////////////////////////////////////////////////////////////////////
void GraphicsWindowInputDevice::
candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, double time) {
_button_events.push_back(ButtonEvent(candidate_string,
highlight_start, highlight_end));
}

View File

@ -66,6 +66,8 @@ public:
void button_resume_down(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void button_up(ButtonHandle button, double time = ClockObject::get_global_clock()->get_frame_time());
void keystroke(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
void candidate(const wstring &candidate_string, size_t highlight_start,
size_t higlight_end, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE void set_pointer_in_window(int x, int y);
INLINE void set_pointer_out_of_window();

View File

@ -40,6 +40,8 @@ INLINE ButtonEvent::
ButtonEvent(ButtonHandle button, ButtonEvent::Type type, double time) :
_button(button),
_keycode(0),
_highlight_start(0),
_highlight_end(0),
_type(type),
_time(time)
{
@ -54,11 +56,31 @@ INLINE ButtonEvent::
ButtonEvent(short keycode, double time) :
_button(ButtonHandle::none()),
_keycode(keycode),
_highlight_start(0),
_highlight_end(0),
_type(T_keystroke),
_time(time)
{
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEvent::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ButtonEvent::
ButtonEvent(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end, double time) :
_button(ButtonHandle::none()),
_keycode(0),
_candidate_string(candidate_string),
_highlight_start(highlight_start),
_highlight_end(highlight_end),
_type(T_candidate),
_time(time)
{
}
////////////////////////////////////////////////////////////////////
// Function: ButtonEvent::Copy Constructor
// Access: Public
@ -68,6 +90,9 @@ INLINE ButtonEvent::
ButtonEvent(const ButtonEvent &copy) :
_button(copy._button),
_keycode(copy._keycode),
_candidate_string(copy._candidate_string),
_highlight_start(copy._highlight_start),
_highlight_end(copy._highlight_end),
_type(copy._type),
_time(copy._time)
{
@ -82,6 +107,9 @@ INLINE void ButtonEvent::
operator = (const ButtonEvent &copy) {
_button = copy._button;
_keycode = copy._keycode;
_candidate_string = copy._candidate_string;
_highlight_start = copy._highlight_start;
_highlight_end = copy._highlight_end;
_type = copy._type;
_time = copy._time;
}

View File

@ -20,6 +20,7 @@
#include "datagram.h"
#include "datagramIterator.h"
#include "buttonRegistry.h"
#include "textEncoder.h"
////////////////////////////////////////////////////////////////////
// Function: ButtonEvent::output
@ -44,6 +45,12 @@ output(ostream &out) const {
case T_keystroke:
out << "keystroke " << _keycode;
break;
case T_candidate:
out << "candidate "
<< TextEncoder::encode_wtext(_candidate_string,
TextEncoder::get_default_encoding());
break;
}
}
@ -69,6 +76,15 @@ write_datagram(Datagram &dg) const {
case T_keystroke:
dg.add_int16(_keycode);
break;
case T_candidate:
// We should probably store the wtext directly in the datagram
// rather than encoding it, but I don't feel like adding
// add_wstring() to datagram right now.
dg.add_string(TextEncoder::encode_wtext(_candidate_string,
TextEncoder::get_default_encoding()));
dg.add_uint16(_highlight_start);
dg.add_uint16(_highlight_end);
}
}
@ -90,5 +106,11 @@ read_datagram(DatagramIterator &scan) {
case T_keystroke:
_keycode = scan.get_int16();
break;
case T_candidate:
_candidate_string = TextEncoder::decode_text(scan.get_string(),
TextEncoder::get_default_encoding());
_highlight_start = scan.get_uint16();
_highlight_end = scan.get_uint16();
}
}

View File

@ -72,12 +72,19 @@ public:
// T_keystroke is a special keystroke event, and is sent along
// with a Unicode keycode value, not a ButtonHandle.
T_keystroke
T_keystroke,
// T_candidate is used to indicate that the user is using the IME
// and has in the process of selecting some possible text to type
// from a menu.
T_candidate,
};
INLINE ButtonEvent();
INLINE ButtonEvent(ButtonHandle button, Type type, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE ButtonEvent(short keycode, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE ButtonEvent(const wstring &candidate_string, size_t highlight_start,
size_t higlight_end, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE ButtonEvent(const ButtonEvent &copy);
INLINE void operator = (const ButtonEvent &copy);
@ -101,6 +108,11 @@ public:
// the Unicode character that was typed.
short _keycode;
// _candidate_string will be filled in if type is T_candidate.
wstring _candidate_string;
size_t _highlight_start;
size_t _highlight_end;
// This is the type of the button event (see above).
Type _type;

View File

@ -27,6 +27,7 @@
#include "glgsg.h"
#include "clockObject.h"
#include "pStatTimer.h"
#include "textEncoder.h"
#include <errno.h>
#include <sys/time.h>
@ -309,6 +310,20 @@ process_events() {
case KeyPress:
handle_keystroke(event.xkey);
handle_keypress(event.xkey);
/*
// Temp hack for testing. We pretend that we have received a
// candidate string every type the user types the backslash key.
{
KeySym key = XLookupKeysym(&event.xkey, 0);
if (key == XK_backslash) {
cerr << "Pressed backslash, sending candidate\n";
wstring candidate_string = TextEncoder::decode_text("This is a candidate string", TextEncoder::get_default_encoding());
_input_devices[0].candidate(candidate_string, 5, 7);
}
}
*/
break;
case KeyRelease:

View File

@ -27,6 +27,7 @@
#include "keyboardButton.h"
#include "mouseButton.h"
#include "lineSegs.h"
#include "textEncoder.h"
#include <math.h>
@ -456,6 +457,33 @@ keystroke(const MouseWatcherParameter &param, bool background) {
PGItem::keystroke(param, background);
}
////////////////////////////////////////////////////////////////////
// Function: PGEntry::candidate
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever
// the user selects an item from the IME menu.
////////////////////////////////////////////////////////////////////
void PGEntry::
candidate(const MouseWatcherParameter &param, bool background) {
if (get_active()) {
if (param.has_candidate()) {
// Do something with the candidate string.
TextEncoder te;
const wstring &cs = param.get_candidate_string();
size_t hs = param.get_highlight_start();
size_t he = param.get_highlight_end();
pgui_cat.info()
<< "Candidate: "
<< te.encode_wtext(cs.substr(0, hs))
<< " (" << te.encode_wtext(cs.substr(hs, he - hs)) << ") "
<< te.encode_wtext(cs.substr(he))
<< "\n";
}
}
PGItem::candidate(param, background);
}
////////////////////////////////////////////////////////////////////
// Function: PGEntry::accept
// Access: Public, Virtual

View File

@ -57,6 +57,7 @@ public:
virtual void press(const MouseWatcherParameter &param, bool background);
virtual void keystroke(const MouseWatcherParameter &param, bool background);
virtual void candidate(const MouseWatcherParameter &param, bool background);
virtual void accept(const MouseWatcherParameter &param);
virtual void overflow(const MouseWatcherParameter &param);

View File

@ -442,6 +442,17 @@ keystroke(const MouseWatcherParameter &param, bool background) {
}
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::keystroke
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever
// the user highlights an option in the IME window.
////////////////////////////////////////////////////////////////////
void PGItem::
candidate(const MouseWatcherParameter &param, bool background) {
// We don't throw sound events for candidate selections for now.
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::background_press
// Access: Public, Static

View File

@ -78,6 +78,7 @@ public:
virtual void press(const MouseWatcherParameter &param, bool background);
virtual void release(const MouseWatcherParameter &param, bool background);
virtual void keystroke(const MouseWatcherParameter &param, bool background);
virtual void candidate(const MouseWatcherParameter &param, bool background);
static void background_press(const MouseWatcherParameter &param);
static void background_release(const MouseWatcherParameter &param);

View File

@ -151,3 +151,16 @@ keystroke(const MouseWatcherParameter &param) {
_item->keystroke(param, false);
}
}
////////////////////////////////////////////////////////////////////
// Function: PGMouseWatcherRegion::candidate
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever
// the user selects an option from the IME menu.
////////////////////////////////////////////////////////////////////
void PGMouseWatcherRegion::
candidate(const MouseWatcherParameter &param) {
if (_item != (PGItem *)NULL) {
_item->candidate(param, false);
}
}

View File

@ -44,6 +44,7 @@ public:
virtual void press(const MouseWatcherParameter &param);
virtual void release(const MouseWatcherParameter &param);
virtual void keystroke(const MouseWatcherParameter &param);
virtual void candidate(const MouseWatcherParameter &param);
private:
PGItem *_item;

View File

@ -737,6 +737,48 @@ keystroke(int keycode) {
}
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::candidate
// Access: Protected
// Description: Records that the indicated candidate string has been
// highlighted in the IME.
////////////////////////////////////////////////////////////////////
void MouseWatcher::
candidate(const wstring &candidate_string, size_t highlight_start,
size_t highlight_end) {
MouseWatcherParameter param;
param.set_candidate(candidate_string, highlight_start, highlight_end);
param.set_modifier_buttons(_mods);
param.set_mouse(_mouse);
// Candidate strings go to all those regions that want keyboard
// events, exactly like keystrokes, above.
Regions::const_iterator ri;
for (ri = _regions.begin(); ri != _regions.end(); ++ri) {
MouseWatcherRegion *region = (*ri);
if (region->get_keyboard()) {
param.set_outside(region != _preferred_region);
region->candidate(param);
}
}
// Also check all of our sub-groups.
Groups::const_iterator gi;
for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
MouseWatcherGroup *group = (*gi);
for (ri = group->_regions.begin(); ri != group->_regions.end(); ++ri) {
MouseWatcherRegion *region = (*ri);
if (region->get_keyboard()) {
param.set_outside(region != _preferred_region);
region->candidate(param);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcher::global_keyboard_press
// Access: Protected
@ -973,6 +1015,10 @@ do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) {
keystroke(be._keycode);
break;
case ButtonEvent::T_candidate:
candidate(be._candidate_string, be._highlight_start, be._highlight_end);
break;
case ButtonEvent::T_resume_down:
// Ignore this, since the button wasn't pressed just now.
break;

View File

@ -139,6 +139,9 @@ protected:
void press(ButtonHandle button);
void release(ButtonHandle button);
void keystroke(int keycode);
void candidate(const wstring &candidate, size_t highlight_start,
size_t highlight_end);
void global_keyboard_press(const MouseWatcherParameter &param);
void global_keyboard_release(const MouseWatcherParameter &param);

View File

@ -88,6 +88,21 @@ set_keycode(int keycode) {
_flags |= F_has_keycode;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::set_candidate
// Access: Public
// Description: Sets the candidate string associated with this event,
// if any.
////////////////////////////////////////////////////////////////////
INLINE void MouseWatcherParameter::
set_candidate(const wstring &candidate_string,
size_t highlight_start, size_t highlight_end) {
_candidate_string = candidate_string;
_highlight_start = highlight_start;
_highlight_end = highlight_end;
_flags |= F_has_candidate;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::set_modifier_buttons
// Access: Public
@ -173,6 +188,75 @@ get_keycode() const {
return _keycode;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::has_candidate
// Access: Published
// Description: Returns true if this parameter has an associated
// candidate string, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool MouseWatcherParameter::
has_candidate() const {
return (_flags & F_has_candidate) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_candidate_string
// Access: Published
// Description: Returns the candidate string associated with this
// event. If has_candidate(), above, returns false,
// this returns the empty string.
////////////////////////////////////////////////////////////////////
INLINE const wstring &MouseWatcherParameter::
get_candidate_string() const {
return _candidate_string;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_candidate_string_encoded
// Access: Published
// Description: Returns the candidate string associated with this
// event. If has_candidate(), above, returns false,
// this returns the empty string.
////////////////////////////////////////////////////////////////////
INLINE string MouseWatcherParameter::
get_candidate_string_encoded() const {
return get_candidate_string_encoded(TextEncoder::get_default_encoding());
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_candidate_string_encoded
// Access: Published
// Description: Returns the candidate string associated with this
// event. If has_candidate(), above, returns false,
// this returns the empty string.
////////////////////////////////////////////////////////////////////
INLINE string MouseWatcherParameter::
get_candidate_string_encoded(TextEncoder::Encoding encoding) const {
return TextEncoder::encode_wtext(_candidate_string, encoding);
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_highlight_start
// Access: Published
// Description: Returns the first highlighted character in the
// candidate string.
////////////////////////////////////////////////////////////////////
INLINE size_t MouseWatcherParameter::
get_highlight_start() const {
return _highlight_start;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_highlight_end
// Access: Published
// Description: Returns one more than the last highlighted character
// in the candidate string.
////////////////////////////////////////////////////////////////////
INLINE size_t MouseWatcherParameter::
get_highlight_end() const {
return _highlight_end;
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherParameter::get_modifier_buttons
// Access: Published

View File

@ -23,6 +23,7 @@
#include "buttonHandle.h"
#include "modifierButtons.h"
#include "textEncoder.h"
#include "luse.h"
////////////////////////////////////////////////////////////////////
@ -40,6 +41,9 @@ public:
INLINE void set_button(const ButtonHandle &button);
INLINE void set_keycode(int keycode);
INLINE void set_candidate(const wstring &candidate_string,
size_t highlight_start,
size_t higlight_end);
INLINE void set_modifier_buttons(const ModifierButtons &mods);
INLINE void set_mouse(const LPoint2f &mouse);
INLINE void set_outside(bool flag);
@ -51,6 +55,17 @@ PUBLISHED:
INLINE bool has_keycode() const;
INLINE int get_keycode() const;
INLINE bool has_candidate() const;
public:
INLINE const wstring &get_candidate_string() const;
PUBLISHED:
INLINE string get_candidate_string_encoded() const;
INLINE string get_candidate_string_encoded(TextEncoder::Encoding encoding) const;
INLINE size_t get_highlight_start() const;
INLINE size_t get_highlight_end() const;
INLINE const ModifierButtons &get_modifier_buttons() const;
INLINE bool has_mouse() const;
@ -63,14 +78,18 @@ PUBLISHED:
public:
ButtonHandle _button;
short _keycode;
wstring _candidate_string;
size_t _highlight_start;
size_t _highlight_end;
ModifierButtons _mods;
LPoint2f _mouse;
enum Flags {
F_has_button = 0x001,
F_has_mouse = 0x002,
F_is_outside = 0x004,
F_has_keycode = 0x008,
F_has_button = 0x001,
F_has_mouse = 0x002,
F_is_outside = 0x004,
F_has_keycode = 0x008,
F_has_candidate = 0x010,
};
int _flags;
};

View File

@ -127,3 +127,13 @@ release(const MouseWatcherParameter &) {
void MouseWatcherRegion::
keystroke(const MouseWatcherParameter &) {
}
////////////////////////////////////////////////////////////////////
// Function: MouseWatcherRegion::candidate
// Access: Public, Virtual
// Description: This is a callback hook function, called whenever an
// IME candidate is highlighted by the user.
////////////////////////////////////////////////////////////////////
void MouseWatcherRegion::
candidate(const MouseWatcherParameter &) {
}

View File

@ -77,6 +77,7 @@ public:
virtual void press(const MouseWatcherParameter &param);
virtual void release(const MouseWatcherParameter &param);
virtual void keystroke(const MouseWatcherParameter &param);
virtual void candidate(const MouseWatcherParameter &param);
private:
LVecBase4f _frame;