2
* Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
4
* The contents of this file are subject to the terms of either the GNU Lesser
5
* General Public License Version 2.1 only ("LGPL") or the Common Development and
6
* Distribution License ("CDDL")(collectively, the "License"). You may not use this
7
* file except in compliance with the License. You can obtain a copy of the CDDL at
8
* http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
9
* http://www.opensource.org/licenses/lgpl-license.php. See the License for the
10
* specific language governing permissions and limitations under the License. When
11
* distributing the software, include this License Header Notice in each file and
12
* include the full text of the License in the License file as well as the
15
* NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
17
* For Covered Software in this distribution, this License shall be governed by the
18
* laws of the State of California (excluding conflict-of-law provisions).
19
* Any litigation relating to this License shall be subject to the jurisdiction of
20
* the Federal Courts of the Northern District of California and the state courts
21
* of the State of California, with venue lying in Santa Clara County, California.
25
* If you wish your version of this file to be governed by only the CDDL or only
26
* the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
27
* include this software in this distribution under the [CDDL or LGPL Version 2.1]
28
* license." If you don't indicate a single choice of license, a recipient has the
29
* option to distribute your version of this file under either the CDDL or the LGPL
30
* Version 2.1, or to extend the choice of license to its licensees as provided
31
* above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
32
* Version 2 license, then the option applies only if the new code is made subject
33
* to such option by the copyright holder.
36
#include <sys/types.h>
42
#include <X11/Xfuncs.h>
43
#include <X11/Xutil.h>
44
#include <X11/Xatom.h>
52
static IC* icmaps[MAX_IC_NUM];
53
static IC ics[MAX_IC_NUM];
55
static size_t free_stack_sz = 0;
56
static IC* free_stack[MAX_IC_NUM];
58
static IC* current_ic;
60
// check if this ic is available
62
__find_application_pid(Window w)
64
if (w == DefaultRootWindow(dpy))
72
int status = XGetWindowProperty(
73
dpy, w, XInternAtom(dpy, "_NET_WM_PID", True), 0,
74
1024L, False, AnyPropertyType, &actual_type, &actual_format, &nitems,
75
&bytes, (unsigned char**) &prop);
77
if (status == BadRequest)
84
Window* children = NULL;
86
status = XQueryTree(dpy, w, &root, &parent, &children, &sz);
88
if (status == BadRequest)
94
return __find_application_pid(parent);
96
// TODO: is this portable?
97
return prop[1] * 256 + prop[0];
102
__ic_available(IC* ic)
104
int pid = __find_application_pid(ic->client_window);
109
// verify if a process is running
111
snprintf(path, 255, "/proc/%d", pid);
113
if (stat(path, &buf) != 0) {
114
LOG("GC can't catch the process %d", pid);
117
if (!S_ISDIR(buf.st_mode)) {
118
LOG("GC can't catch the process %d", pid);
128
for (i = 0; i < MAX_IC_NUM; i++) {
133
if (__ic_available(ic) == false) {
134
LOG("GC detected garbage %d", ic->icid);
144
memset(ic, 0, sizeof(IC));
146
ic->is_chn_punc = true;
152
memset(ics, 0, sizeof(IC) * MAX_IC_NUM);
154
for (i = 0; i < MAX_IC_NUM; i++) {
158
free_stack[free_stack_sz] = &ics[i];
169
memset(icmaps, 0, sizeof(IC*) * MAX_IC_NUM);
175
icmgr_create_ic(int connect_id)
177
static int created_cnt = 0;
180
if (created_cnt == GC_THRESHOLD || free_stack_sz < MAX_IC_NUM / 3) {
185
if (free_stack_sz == 0) {
186
LOG("Error free stack empty!!");
191
IC* ic = free_stack[free_stack_sz];
193
icmaps[ic->icid] = ic;
196
/* icmgr_set_current(ic->icid); */
198
ic->connect_id = connect_id;
200
/* current_ic = ic; */
205
icmgr_destroy_ic(int icid)
207
IC* ic = icmaps[icid];
211
memset(ic, 0, sizeof(IC));
216
// return to free stack
217
free_stack[free_stack_sz] = ic;
224
icmgr_set_current(int icid)
226
IC* ic = icmaps[icid];
234
icmgr_get_current(void)
240
icmgr_toggle_english(void)
243
current_ic->is_english = !current_ic->is_english;
248
icmgr_toggle_full(void)
251
current_ic->is_full = !current_ic->is_full;
256
icmgr_toggle_punc(void)
259
current_ic->is_chn_punc = !current_ic->is_chn_punc;
270
icmgr_clear_current(void)
278
if (current_ic == NULL) {
283
/* refresh preedit */
284
if (current_ic->is_enabled) {
285
if (current_ic->is_english && preedit_status())
287
else if (!current_ic->is_english && !preedit_status())
290
preedit_set_full(current_ic->is_full);
291
preedit_set_chinese_punc(current_ic->is_chn_punc);
298
extern IC_UI icmgr_gtk;
299
extern IC_UI icmgr_skin;
301
static IC_UI* current_icmgr_ui = NULL;
307
settings_get(SKIN_NAME, skin_name);
308
if (strcmp(skin_name, "classic") == 0) {
309
current_icmgr_ui = &icmgr_gtk;
311
current_icmgr_ui = &icmgr_skin;
314
if (!current_icmgr_ui->init(skin_name)) {
315
fprintf(stderr, "Error init front end!\n");
328
icmgr_ui_refresh(void)
331
if (current_icmgr_ui != NULL) {
333
settings_get(SKIN_NAME, skin_name);
334
if (strcmp(skin_name, current_icmgr_ui->get_name()) != 0) {
335
current_icmgr_ui->dispose();
338
current_icmgr_ui->refresh();