mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
add initial support for IME candidate strings in-game
This commit is contained in:
parent
9315342da7
commit
a28b2a8006
@ -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));
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 ©) :
|
||||
_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 ©) {
|
||||
_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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 ©);
|
||||
INLINE void operator = (const ButtonEvent ©);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 ¶m, 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 ¶m, 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
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
|
||||
virtual void press(const MouseWatcherParameter ¶m, bool background);
|
||||
virtual void keystroke(const MouseWatcherParameter ¶m, bool background);
|
||||
virtual void candidate(const MouseWatcherParameter ¶m, bool background);
|
||||
|
||||
virtual void accept(const MouseWatcherParameter ¶m);
|
||||
virtual void overflow(const MouseWatcherParameter ¶m);
|
||||
|
@ -442,6 +442,17 @@ keystroke(const MouseWatcherParameter ¶m, 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 ¶m, bool background) {
|
||||
// We don't throw sound events for candidate selections for now.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGItem::background_press
|
||||
// Access: Public, Static
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
virtual void press(const MouseWatcherParameter ¶m, bool background);
|
||||
virtual void release(const MouseWatcherParameter ¶m, bool background);
|
||||
virtual void keystroke(const MouseWatcherParameter ¶m, bool background);
|
||||
virtual void candidate(const MouseWatcherParameter ¶m, bool background);
|
||||
|
||||
static void background_press(const MouseWatcherParameter ¶m);
|
||||
static void background_release(const MouseWatcherParameter ¶m);
|
||||
|
@ -151,3 +151,16 @@ keystroke(const MouseWatcherParameter ¶m) {
|
||||
_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 ¶m) {
|
||||
if (_item != (PGItem *)NULL) {
|
||||
_item->candidate(param, false);
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
virtual void press(const MouseWatcherParameter ¶m);
|
||||
virtual void release(const MouseWatcherParameter ¶m);
|
||||
virtual void keystroke(const MouseWatcherParameter ¶m);
|
||||
virtual void candidate(const MouseWatcherParameter ¶m);
|
||||
|
||||
private:
|
||||
PGItem *_item;
|
||||
|
@ -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;
|
||||
|
@ -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 ¶m);
|
||||
void global_keyboard_release(const MouseWatcherParameter ¶m);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 &) {
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ public:
|
||||
virtual void press(const MouseWatcherParameter ¶m);
|
||||
virtual void release(const MouseWatcherParameter ¶m);
|
||||
virtual void keystroke(const MouseWatcherParameter ¶m);
|
||||
virtual void candidate(const MouseWatcherParameter ¶m);
|
||||
|
||||
private:
|
||||
LVecBase4f _frame;
|
||||
|
Loading…
x
Reference in New Issue
Block a user