~3v1n0/nux/check-dnd_area-trusty

« back to all changes in this revision

Viewing changes to Nux/XICClient.cpp

  • Committer: Tarmac
  • Author(s): Brandon Schaefer
  • Date: 2014-01-03 18:02:22 UTC
  • mfrom: (831.2.9 nux-xim)
  • Revision ID: tarmac-20140103180222-f8031e8kdo09rf3x
Adds preedit support to XIM. Such as preedit rendering in the TextEntry.

Move XIM support from GraphicsDisplayX11 to WindowThread. Fixes: https://bugs.launchpad.net/bugs/1265565.

Approved by Christopher Townsend, PS Jenkins bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
* Copyright 2012 Inalogic® Inc.
 
2
* Copyright 2012-2013 Inalogic® Inc.
3
3
*
4
4
* This program is free software: you can redistribute it and/or modify it
5
5
* under the terms of the GNU Lesser General Public License, as
21
21
 
22
22
#include "XICClient.h"
23
23
 
 
24
#include "NuxCore/Logger.h"
 
25
 
 
26
DECLARE_LOGGER(logger, "xic.client");
 
27
 
 
28
using namespace std;
 
29
 
24
30
namespace nux
25
31
{
26
32
 
 
33
int const FEEDBACK_MASK = (XIMUnderline | XIMReverse);
 
34
 
27
35
XICClient::XICClient()
28
 
  : xic_(NULL)
 
36
  : xic_(nullptr)
29
37
  , xim_style_(0)
30
38
  , focused_(false)
31
39
{
32
40
}
33
41
 
34
 
void XICClient::ResetXIC(XIM xim, Window window)
 
42
void XICClient::ResetXIC(XIM xim, Window window, Display* display)
35
43
{
36
44
  if (!xim_style_)
37
45
    SetupXIMStyle(xim);
38
46
 
39
 
  SetupXIC(xim, window);
40
 
}
41
 
 
42
 
void XICClient::SetupXIC(XIM xim, Window window)
 
47
  SetupXIC(xim, window, display);
 
48
}
 
49
 
 
50
void XICClient::SetCurrentTextEntry(TextEntry* text_entry)
 
51
{
 
52
  text_entry_ = text_entry;
 
53
}
 
54
 
 
55
static int preedit_caret_callback(XIC xic,
 
56
                                  XPointer clientdata,
 
57
                                  XIMPreeditCaretCallbackStruct* call_data)
 
58
{
 
59
  return 0;
 
60
}
 
61
 
 
62
static int status_start_callback(XIC xic,
 
63
                                 XPointer clientdata,
 
64
                                 XIMPreeditDrawCallbackStruct* call_data)
 
65
{
 
66
  return 0;
 
67
}
 
68
 
 
69
static void status_draw_callback(XIC xic,
 
70
                                 XPointer clientdata,
 
71
                                 XPointer* call_data)
 
72
{
 
73
}
 
74
 
 
75
static void status_done_callback(XIC xic,
 
76
                                 XPointer clientdata,
 
77
                                 XPointer* call_data)
 
78
{
 
79
}
 
80
 
 
81
XVaNestedList XICClient::GetPreeditCallbacks()
 
82
{
 
83
  preedit_start_cb_.callback = (XIMProc)XICClient::PreeditStartCallback;
 
84
  preedit_start_cb_.client_data = nullptr;
 
85
 
 
86
  preedit_done_cb_.callback = (XIMProc)XICClient::PreeditDoneCallback;
 
87
  preedit_done_cb_.client_data = (XPointer)text_entry_;
 
88
 
 
89
  preedit_draw_cb_.callback = (XIMProc)XICClient::PreeditDrawCallback;
 
90
  preedit_draw_cb_.client_data = (XPointer)text_entry_;
 
91
 
 
92
  preedit_caret_cb_.callback = (XIMProc)preedit_caret_callback;
 
93
  preedit_caret_cb_.client_data = nullptr;
 
94
 
 
95
  XVaNestedList p_list = nullptr;
 
96
  p_list = XVaCreateNestedList(0,
 
97
                               XNPreeditStartCallback, &preedit_start_cb_,
 
98
                               XNPreeditDoneCallback,  &preedit_done_cb_,
 
99
                               XNPreeditDrawCallback,  &preedit_draw_cb_,
 
100
                               XNPreeditCaretCallback, &preedit_caret_cb_,
 
101
                               nullptr);
 
102
 
 
103
  return p_list;
 
104
}
 
105
 
 
106
XVaNestedList XICClient::GetStatusCallbacks()
 
107
{
 
108
  status_start_cb_.callback = (XIMProc)status_start_callback;
 
109
  status_start_cb_.client_data = nullptr;
 
110
 
 
111
  status_done_cb_.callback = (XIMProc)status_done_callback;
 
112
  status_done_cb_.client_data = nullptr;
 
113
 
 
114
  status_draw_cb_.callback = (XIMProc)status_draw_callback;
 
115
  status_draw_cb_.client_data = nullptr;
 
116
 
 
117
  XVaNestedList s_list = nullptr;
 
118
  s_list = XVaCreateNestedList(0,
 
119
                               XNStatusStartCallback, &status_start_callback,
 
120
                               XNStatusDoneCallback,  &status_done_callback,
 
121
                               XNStatusDrawCallback,  &status_draw_callback,
 
122
                               nullptr);
 
123
 
 
124
  return s_list;
 
125
}
 
126
 
 
127
XIMStyle XICClient::FilterXIMStyle()
 
128
{
 
129
  XIMStyle style = 0;
 
130
 
 
131
  if (xim_style_ & XIMPreeditCallbacks)
 
132
  {
 
133
    style |= XIMPreeditCallbacks;
 
134
  }
 
135
  else if (xim_style_ & XIMPreeditNone)
 
136
  {
 
137
    style |= XIMPreeditNone;
 
138
  }
 
139
  else
 
140
  {
 
141
    style |= XIMPreeditNothing;
 
142
  }
 
143
 
 
144
  if (xim_style_ & XIMStatusCallbacks)
 
145
  {
 
146
    style |= XIMStatusCallbacks;
 
147
  }
 
148
  else if (xim_style_ & XIMStatusNone)
 
149
  {
 
150
    style |= XIMStatusNone;
 
151
  }
 
152
  else
 
153
  {
 
154
    style |= XIMStatusNothing;
 
155
  }
 
156
 
 
157
  return style;
 
158
}
 
159
 
 
160
void XICClient::SetupXIC(XIM xim, Window window, Display* display)
43
161
{
44
162
  if (xic_)
45
163
    DestroyXIC();
46
164
 
47
 
  xic_ = XCreateIC(xim, XNInputStyle, xim_style_, XNClientWindow, window, XNFocusWindow, window, NULL);
 
165
  XIMStyle style = FilterXIMStyle();
 
166
  
 
167
  const char* p_name = nullptr;
 
168
  XVaNestedList p_list = nullptr;
 
169
  if (style & XIMPreeditCallbacks)
 
170
  {
 
171
    p_list = GetPreeditCallbacks();
 
172
    p_name = XNPreeditAttributes;
 
173
  }
 
174
 
 
175
  const char* s_name = nullptr;
 
176
  XVaNestedList s_list = nullptr;
 
177
  if (style & XIMStatusCallbacks)
 
178
  {
 
179
    s_list = GetStatusCallbacks();
 
180
    s_name = XNStatusAttributes;
 
181
  }
 
182
 
 
183
  xic_ = XCreateIC(xim, XNInputStyle, style,
 
184
                   XNClientWindow, window,
 
185
                   p_name, p_list,
 
186
                   s_name, s_list,
 
187
                   nullptr);
 
188
 
 
189
  if (p_list)
 
190
    XFree(p_list);
 
191
  if (s_list)
 
192
    XFree(s_list);
 
193
 
 
194
  xim_style_ = style;
 
195
}
 
196
 
 
197
XIMStyle ChooseBetterStyle(XIMStyle style1, XIMStyle style2)
 
198
{
 
199
  XIMStyle s,t;
 
200
  XIMStyle preedit = XIMPreeditArea | XIMPreeditCallbacks |
 
201
                     XIMPreeditPosition | XIMPreeditNothing | XIMPreeditNone;
 
202
 
 
203
  XIMStyle status = XIMStatusArea | XIMStatusCallbacks |
 
204
                    XIMStatusNothing | XIMStatusNone;
 
205
 
 
206
  if (style1 == 0)
 
207
    return style2;
 
208
 
 
209
  if (style2 == 0)
 
210
    return style1;
 
211
 
 
212
  if ((style1 & (preedit | status)) == (style2 & (preedit | status)))
 
213
    return style1;
 
214
 
 
215
  s = style1 & preedit;
 
216
  t = style2 & preedit;
 
217
  if (s != t)
 
218
  {
 
219
    if (s | t | XIMPreeditCallbacks)
 
220
      return (s == XIMPreeditCallbacks) ? style1 : style2;
 
221
    else if (s | t | XIMPreeditPosition)
 
222
      return (s == XIMPreeditPosition)  ? style1 : style2;
 
223
    else if (s | t | XIMPreeditArea)
 
224
      return (s == XIMPreeditArea)      ? style1 : style2;
 
225
    else if (s | t | XIMPreeditNothing)
 
226
      return (s == XIMPreeditNothing)   ? style1 : style2;
 
227
    else if (s | t | XIMPreeditNone)
 
228
      return (s == XIMPreeditNone)      ? style1 : style2;
 
229
  }
 
230
  else
 
231
  {
 
232
    s = style1 & status;
 
233
    t = style2 & status;
 
234
 
 
235
    if (s | t | XIMStatusCallbacks)
 
236
      return (s == XIMStatusCallbacks) ? style1 : style2;
 
237
    else if (s | t | XIMStatusArea)
 
238
      return (s == XIMStatusArea)      ? style1 : style2;
 
239
    else if (s | t | XIMStatusNothing)
 
240
      return (s == XIMStatusNothing)   ? style1 : style2;
 
241
    else if (s | t | XIMStatusNone)
 
242
      return (s == XIMStatusNone)      ? style1 : style2;
 
243
  }
48
244
}
49
245
 
50
246
void XICClient::SetupXIMStyle(XIM xim)
51
247
{
52
248
  int i;
53
 
  XIMStyles *xim_styles = NULL;
54
 
  XIMStyle root_style = (XIMPreeditNothing|XIMStatusNothing);
55
 
 
56
 
  XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL);
57
 
 
 
249
  XIMStyles *xim_styles = nullptr;
 
250
  XIMStyle prefered_style = XIMPreeditCallbacks | XIMStatusCallbacks;
 
251
 
 
252
  XGetIMValues(xim, XNQueryInputStyle, &xim_styles, nullptr);
 
253
 
 
254
  XIMStyle best = 0, style = 0;
58
255
  for (i = 0; i < xim_styles->count_styles; ++i)
59
 
    if (xim_styles->supported_styles[i] == root_style)
 
256
  {
 
257
    style = xim_styles->supported_styles[i];
 
258
 
 
259
    if ((style & prefered_style) == style)
 
260
    {
 
261
      best = ChooseBetterStyle(style, best);
60
262
      break;
 
263
    }
 
264
    else
 
265
    {
 
266
      best = ChooseBetterStyle(style, best);
 
267
    }
 
268
  }
61
269
 
62
 
  if (i >= xim_styles->count_styles)
63
 
    xim_style_ = 0;
64
 
  xim_style_ = root_style;
 
270
  xim_style_ = best;
65
271
 
66
272
  XFree(xim_styles);
67
273
}
68
274
 
69
275
bool XICClient::HasXIC() const
70
276
{
71
 
  return xic_ != NULL;
 
277
  return xic_ != nullptr;
72
278
}
73
279
 
74
280
XIC XICClient::GetXIC() const
78
284
 
79
285
void XICClient::Reinitialize()
80
286
{
81
 
  xic_ = NULL;
 
287
  xic_ = nullptr;
82
288
  xim_style_ = 0;
83
289
  focused_ = false;
84
290
}
111
317
  if (xic_)
112
318
  {
113
319
    XDestroyIC(xic_);
114
 
    xic_ = NULL;
 
320
    xic_ = nullptr;
115
321
  }
116
322
}
117
323