~3v1n0/nux/check-dnd_area-trusty

« back to all changes in this revision

Viewing changes to Nux/XIMCallbacks.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
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
 
2
/*
 
3
 * Copyright 2013 Inalogic® Inc.
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify it
 
6
 * under the terms of the GNU Lesser General Public License, as
 
7
 * published by the  Free Software Foundation; either version 2.1 or 3.0
 
8
 * of the License.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
12
 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
 
13
 * PURPOSE.  See the applicable version of the GNU Lesser General Public
 
14
 * License for more details.
 
15
 *
 
16
 * You should have received a copy of both the GNU Lesser General Public
 
17
 * License along with this program. If not, see <http://www.gnu.org/licenses/>
 
18
 *
 
19
 * Authored by: Brandon Schaefer
 
20
 *
 
21
 */
 
22
 
 
23
 
 
24
#include "Nux.h"
 
25
#include "TextEntry.h"
 
26
#include "XICClient.h"
 
27
 
 
28
#include <string>
 
29
 
 
30
#include "NuxCore/Logger.h"
 
31
 
 
32
DECLARE_LOGGER(logger, "xim.callbacks");
 
33
 
 
34
using namespace std;
 
35
 
 
36
namespace nux
 
37
{
 
38
 
 
39
int const FEEDBACK_MASK = (XIMUnderline | XIMReverse);
 
40
 
 
41
int XICClient::PreeditStartCallback(XIC xic,
 
42
                                    XPointer clientdata,
 
43
                                    XPointer call_data)
 
44
{
 
45
  TextEntry* text_entry = (TextEntry*)clientdata;
 
46
  if (text_entry)
 
47
  {
 
48
    text_entry->PreeditStarted();
 
49
  }
 
50
 
 
51
  return 0;
 
52
}
 
53
 
 
54
int XICClient::PreeditDoneCallback(XIC xic,
 
55
                                   XPointer clientdata,
 
56
                                   XPointer call_data)
 
57
{
 
58
  TextEntry* text_entry = (TextEntry*)clientdata;
 
59
  if (text_entry)
 
60
  {
 
61
    text_entry->ClearPreedit();
 
62
  }
 
63
 
 
64
  return 0;
 
65
}
 
66
 
 
67
void add_feedback_attr(PangoAttrList* attrs,
 
68
                            char const* str,
 
69
                            XIMFeedback feedback,
 
70
                            int start,
 
71
                            int end)
 
72
{
 
73
  PangoAttribute* attr;
 
74
 
 
75
  int start_index = g_utf8_offset_to_pointer(str, start) - str;
 
76
  int end_index   = g_utf8_offset_to_pointer(str, end)   - str;
 
77
 
 
78
  if (feedback & XIMUnderline)
 
79
  {
 
80
    attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
 
81
    attr->start_index = start_index;
 
82
    attr->end_index = end_index;
 
83
 
 
84
    pango_attr_list_insert (attrs, attr);
 
85
  }
 
86
 
 
87
  if (feedback & XIMReverse)
 
88
  {
 
89
    attr = pango_attr_foreground_new(0xFFFF, 0xFFFF, 0xFFFF);
 
90
    attr->start_index = start_index;
 
91
    attr->end_index = end_index;
 
92
 
 
93
    pango_attr_list_insert (attrs, attr);
 
94
 
 
95
    attr = pango_attr_background_new(0x0, 0x0, 0x0);
 
96
 
 
97
    attr->start_index = start_index;
 
98
    attr->end_index = end_index;
 
99
 
 
100
    pango_attr_list_insert (attrs, attr);
 
101
  }
 
102
 
 
103
  if (feedback & ~FEEDBACK_MASK)
 
104
  {
 
105
    LOG_WARN(logger) << "Unrenderer feedback: " << (feedback & ~FEEDBACK_MASK);
 
106
  }
 
107
}
 
108
 
 
109
void feedback_to_pango_list(PangoAttrList** attrs,
 
110
                            char const* str,
 
111
                            int nfeedbacks,
 
112
                            XIMFeedback* feedbacks)
 
113
{
 
114
  XIMFeedback last_feedback = 0;
 
115
  int start = -1;
 
116
  int i = 0;
 
117
 
 
118
  if (attrs)
 
119
  {
 
120
    *attrs = pango_attr_list_new();
 
121
 
 
122
    for (i = 0; i < nfeedbacks; ++i)
 
123
    {
 
124
      XIMFeedback new_feedback = (feedbacks[i] & FEEDBACK_MASK);
 
125
      if (new_feedback != last_feedback)
 
126
      {
 
127
        last_feedback = new_feedback;
 
128
        start = i;
 
129
      }
 
130
      else
 
131
      {
 
132
        PangoAttribute* attr;
 
133
 
 
134
        int start_index = g_utf8_offset_to_pointer(str, start) - str;
 
135
        int end_index   = g_utf8_offset_to_pointer(str, i)   - str;
 
136
 
 
137
        attr = pango_attr_foreground_new(0x0, 0x0, 0x0);
 
138
        attr->start_index = start_index;
 
139
        attr->end_index = end_index;
 
140
 
 
141
        pango_attr_list_insert (*attrs, attr);
 
142
 
 
143
        attr = pango_attr_background_new(0xFFFF, 0xFFFF, 0xFFFF);
 
144
 
 
145
        attr->start_index = start_index;
 
146
        attr->end_index = end_index;
 
147
 
 
148
        pango_attr_list_insert (*attrs, attr);
 
149
      }
 
150
    }
 
151
 
 
152
    if (start >= 0)
 
153
      add_feedback_attr(*attrs, str, last_feedback, start, i);
 
154
  }
 
155
}
 
156
 
 
157
int XICClient::PreeditDrawCallback(XIC xic,
 
158
                                   XPointer clientdata,
 
159
                                   XIMPreeditDrawCallbackStruct* call_data)
 
160
{
 
161
  TextEntry* text_entry = (TextEntry*)clientdata;
 
162
 
 
163
  if (call_data->text && text_entry)
 
164
  {
 
165
    string preedit;
 
166
 
 
167
    // TODO Actually handle this correctly...
 
168
    if (call_data->text->encoding_is_wchar)
 
169
    {
 
170
      preedit = string("");
 
171
    }
 
172
    else
 
173
    {
 
174
      preedit = string(call_data->text->string.multi_byte);
 
175
    }
 
176
 
 
177
    PangoAttrList* preedit_attr;
 
178
    feedback_to_pango_list(&preedit_attr, preedit.c_str(),
 
179
                           call_data->text->length,
 
180
                           call_data->text->feedback);
 
181
 
 
182
    text_entry->UpdatePreeditAttribs(preedit_attr);
 
183
    text_entry->UpdatePreedit(preedit, call_data->caret);
 
184
  }
 
185
 
 
186
  return 0;
 
187
}
 
188
 
 
189
}