Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <stdio.h>
31 : :
32 : : #include <sal/alloca.h>
33 : : #include <osl/thread.h>
34 : :
35 : : #include <tools/prex.h>
36 : : #include <X11/Xlocale.h>
37 : : #include <X11/Xlib.h>
38 : : #include <tools/postx.h>
39 : :
40 : : #include <unx/salunx.h>
41 : : #include <unx/XIM.h>
42 : : #include <unx/i18n_ic.hxx>
43 : : #include <unx/i18n_im.hxx>
44 : : #include <unx/i18n_status.hxx>
45 : :
46 : : #include <unx/salframe.h>
47 : : #include <unx/saldata.hxx>
48 : : #include <unx/saldisp.hxx>
49 : :
50 : : using namespace vcl;
51 : :
52 : 0 : static void sendEmptyCommit( SalFrame* pFrame )
53 : : {
54 : 0 : vcl::DeletionListener aDel( pFrame );
55 : :
56 : 0 : SalExtTextInputEvent aEmptyEv;
57 : 0 : aEmptyEv.mnTime = 0;
58 : 0 : aEmptyEv.mpTextAttr = 0;
59 : 0 : aEmptyEv.maText = String();
60 : 0 : aEmptyEv.mnCursorPos = 0;
61 : 0 : aEmptyEv.mnCursorFlags = 0;
62 : 0 : aEmptyEv.mnDeltaStart = 0;
63 : 0 : aEmptyEv.mbOnlyCursor = False;
64 : 0 : pFrame->CallCallback( SALEVENT_EXTTEXTINPUT, (void*)&aEmptyEv );
65 : 0 : if( ! aDel.isDeleted() )
66 : 0 : pFrame->CallCallback( SALEVENT_ENDEXTTEXTINPUT, NULL );
67 : 0 : }
68 : :
69 : : // ---------------------------------------------------------------------------
70 : : //
71 : : // Constructor / Destructor, the InputContext is bound to the SalFrame, as it
72 : : // needs the shell window as a focus window
73 : : //
74 : : // ----------------------------------------------------------------------------
75 : :
76 : 0 : SalI18N_InputContext::~SalI18N_InputContext()
77 : : {
78 : 0 : if ( maContext != NULL )
79 : 0 : XDestroyIC( maContext );
80 : 0 : if ( mpAttributes != NULL )
81 : 0 : XFree( mpAttributes );
82 : 0 : if ( mpStatusAttributes != NULL )
83 : 0 : XFree( mpStatusAttributes );
84 : 0 : if ( mpPreeditAttributes != NULL )
85 : 0 : XFree( mpPreeditAttributes );
86 : :
87 : 0 : if (maClientData.aText.pUnicodeBuffer != NULL)
88 : 0 : free(maClientData.aText.pUnicodeBuffer);
89 : 0 : if (maClientData.aText.pCharStyle != NULL)
90 : 0 : free(maClientData.aText.pCharStyle);
91 : 0 : }
92 : :
93 : : // ----------------------------------------------------------------------------
94 : : // convenience routine to add items to a XVaNestedList
95 : : // ----------------------------------------------------------------------------
96 : :
97 : : static XVaNestedList
98 : 0 : XVaAddToNestedList( XVaNestedList a_srclist, char* name, XPointer value )
99 : : {
100 : : XVaNestedList a_dstlist;
101 : :
102 : : // if ( value == NULL )
103 : : // return a_srclist;
104 : :
105 : 0 : if ( a_srclist == NULL )
106 : : {
107 : : a_dstlist = XVaCreateNestedList(
108 : : 0,
109 : : name, value,
110 : 0 : NULL );
111 : : }
112 : : else
113 : : {
114 : : a_dstlist = XVaCreateNestedList(
115 : : 0,
116 : : XNVaNestedList, a_srclist,
117 : : name, value,
118 : 0 : NULL );
119 : : }
120 : :
121 : 0 : return a_dstlist != NULL ? a_dstlist : a_srclist ;
122 : : }
123 : :
124 : : // ----------------------------------------------------------------------------
125 : : // convenience routine to create a fontset
126 : : // ----------------------------------------------------------------------------
127 : :
128 : : static XFontSet
129 : 0 : get_font_set( Display *p_display )
130 : : {
131 : : static XFontSet p_font_set = NULL;
132 : :
133 : 0 : if (p_font_set == NULL)
134 : : {
135 : : char **pp_missing_list;
136 : : int n_missing_count;
137 : : char *p_default_string;
138 : :
139 : : p_font_set = XCreateFontSet(p_display, "-*",
140 : 0 : &pp_missing_list, &n_missing_count, &p_default_string);
141 : : }
142 : :
143 : 0 : return p_font_set;
144 : : }
145 : :
146 : : // ---------------------------------------------------------------------------
147 : : //
148 : : // Constructor for a InputContext (IC)
149 : : //
150 : : // ----------------------------------------------------------------------------
151 : :
152 : 0 : SalI18N_InputContext::SalI18N_InputContext ( SalFrame *pFrame ) :
153 : : mbUseable( True ),
154 : : maContext( (XIC)NULL ),
155 : : mnSupportedStatusStyle(
156 : : XIMStatusCallbacks |
157 : : XIMStatusNothing |
158 : : XIMStatusNone
159 : : ),
160 : : mnSupportedPreeditStyle(
161 : : XIMPreeditCallbacks |
162 : : XIMPreeditNothing |
163 : : XIMPreeditNone
164 : : ),
165 : : mnStatusStyle( 0 ),
166 : : mnPreeditStyle( 0 ),
167 : : mpAttributes( NULL ),
168 : : mpStatusAttributes( NULL ),
169 : 0 : mpPreeditAttributes( NULL )
170 : : {
171 : : #ifdef SOLARIS
172 : : static const char* pIIIMPEnable = getenv( "SAL_DISABLE_OWN_IM_STATUS" );
173 : : if( pIIIMPEnable && *pIIIMPEnable )
174 : : mnSupportedStatusStyle &= ~XIMStatusCallbacks;
175 : : #endif
176 : :
177 : 0 : maClientData.aText.pUnicodeBuffer = NULL;
178 : 0 : maClientData.aText.pCharStyle = NULL;
179 : 0 : maClientData.aInputEv.mnTime = 0;
180 : 0 : maClientData.aInputEv.mpTextAttr = NULL;
181 : 0 : maClientData.aInputEv.mnCursorPos = 0;
182 : 0 : maClientData.aInputEv.mnDeltaStart = 0;
183 : 0 : maClientData.aInputEv.mnCursorFlags = 0;
184 : 0 : maClientData.aInputEv.mbOnlyCursor = sal_False;
185 : :
186 : : SalI18N_InputMethod *pInputMethod;
187 : 0 : pInputMethod = GetGenericData()->GetSalDisplay()->GetInputMethod();
188 : :
189 : : mnSupportedPreeditStyle = XIMPreeditCallbacks | XIMPreeditPosition
190 : 0 : | XIMPreeditNothing | XIMPreeditNone;
191 : 0 : if (pInputMethod->UseMethod()
192 : 0 : && SupportInputMethodStyle( pInputMethod->GetSupportedStyles() ) )
193 : : {
194 : 0 : const SystemEnvData* pEnv = pFrame->GetSystemData();
195 : 0 : XLIB_Window aClientWindow = pEnv->aShellWindow;
196 : 0 : XLIB_Window aFocusWindow = pEnv->aWindow;
197 : :
198 : : // for status callbacks and commit string callbacks
199 : : #define PREEDIT_BUFSZ 16
200 : 0 : maClientData.eState = ePreeditStatusStartPending;
201 : 0 : maClientData.pFrame = pFrame;
202 : : maClientData.aText.pUnicodeBuffer =
203 : 0 : (sal_Unicode*)malloc(PREEDIT_BUFSZ * sizeof(sal_Unicode));
204 : : maClientData.aText.pCharStyle =
205 : 0 : (XIMFeedback*)malloc(PREEDIT_BUFSZ * sizeof(XIMFeedback));
206 : 0 : maClientData.aText.nSize = PREEDIT_BUFSZ;
207 : 0 : maClientData.aText.nCursorPos = 0;
208 : 0 : maClientData.aText.nLength = 0;
209 : :
210 : : //
211 : : // Status attributes
212 : : //
213 : :
214 : 0 : switch ( mnStatusStyle )
215 : : {
216 : : case XIMStatusCallbacks:
217 : : {
218 : : static XIMCallback aStatusStartCallback;
219 : : static XIMCallback aStatusDoneCallback;
220 : : static XIMCallback aStatusDrawCallback;
221 : :
222 : 0 : aStatusStartCallback.callback = (XIMProc)StatusStartCallback;
223 : 0 : aStatusStartCallback.client_data = (XPointer)&maClientData;
224 : 0 : aStatusDoneCallback.callback = (XIMProc)StatusDoneCallback;
225 : 0 : aStatusDoneCallback.client_data = (XPointer)&maClientData;
226 : 0 : aStatusDrawCallback.callback = (XIMProc)StatusDrawCallback;
227 : 0 : aStatusDrawCallback.client_data = (XPointer)&maClientData;
228 : :
229 : : mpStatusAttributes = XVaCreateNestedList (
230 : : 0,
231 : : XNStatusStartCallback, &aStatusStartCallback,
232 : : XNStatusDoneCallback, &aStatusDoneCallback,
233 : : XNStatusDrawCallback, &aStatusDrawCallback,
234 : 0 : NULL );
235 : :
236 : 0 : break;
237 : : }
238 : :
239 : : case XIMStatusArea:
240 : : /* not supported */
241 : 0 : break;
242 : :
243 : : case XIMStatusNone:
244 : : case XIMStatusNothing:
245 : : default:
246 : : /* no arguments needed */
247 : 0 : break;
248 : : }
249 : :
250 : : //
251 : : // set preedit attributes
252 : : //
253 : :
254 : 0 : switch ( mnPreeditStyle )
255 : : {
256 : : case XIMPreeditCallbacks:
257 : :
258 : 0 : maPreeditCaretCallback.callback = (XIMProc)PreeditCaretCallback;
259 : 0 : maPreeditStartCallback.callback = (XIMProc)PreeditStartCallback;
260 : 0 : maPreeditDoneCallback.callback = (XIMProc)PreeditDoneCallback;
261 : 0 : maPreeditDrawCallback.callback = (XIMProc)PreeditDrawCallback;
262 : 0 : maPreeditCaretCallback.client_data = (XPointer)&maClientData;
263 : 0 : maPreeditStartCallback.client_data = (XPointer)&maClientData;
264 : 0 : maPreeditDoneCallback.client_data = (XPointer)&maClientData;
265 : 0 : maPreeditDrawCallback.client_data = (XPointer)&maClientData;
266 : :
267 : : mpPreeditAttributes = XVaCreateNestedList (
268 : : 0,
269 : : XNPreeditStartCallback, &maPreeditStartCallback,
270 : : XNPreeditDoneCallback, &maPreeditDoneCallback,
271 : : XNPreeditDrawCallback, &maPreeditDrawCallback,
272 : : XNPreeditCaretCallback, &maPreeditCaretCallback,
273 : 0 : NULL );
274 : :
275 : 0 : break;
276 : :
277 : : case XIMPreeditArea:
278 : : /* not supported */
279 : 0 : break;
280 : :
281 : : case XIMPreeditPosition:
282 : : {
283 : : // spot location
284 : : SalExtTextInputPosEvent aPosEvent;
285 : 0 : pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
286 : :
287 : : static XPoint aSpot;
288 : 0 : aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
289 : 0 : aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
290 : :
291 : : // create attributes for preedit position style
292 : : mpPreeditAttributes = XVaCreateNestedList (
293 : : 0,
294 : : XNSpotLocation, &aSpot,
295 : 0 : NULL );
296 : :
297 : : // XCreateIC() fails on Redflag Linux 2.0 if there is no
298 : : // fontset though the data itself is not evaluated nor is
299 : : // it required according to the X specs.
300 : 0 : Display* pDisplay = GetGenericData()->GetSalDisplay()->GetDisplay();
301 : 0 : XFontSet pFontSet = get_font_set(pDisplay);
302 : :
303 : 0 : if (pFontSet != NULL)
304 : : {
305 : : mpPreeditAttributes = XVaAddToNestedList( mpPreeditAttributes,
306 : 0 : const_cast<char*>(XNFontSet), (XPointer)pFontSet);
307 : : }
308 : :
309 : : break;
310 : : }
311 : :
312 : : case XIMPreeditNone:
313 : : case XIMPreeditNothing:
314 : : default:
315 : : /* no arguments needed */
316 : 0 : break;
317 : : }
318 : :
319 : : // Create the InputContext by giving it exactly the information it
320 : : // deserves, because inappropriate attributes
321 : : // let XCreateIC fail on Solaris (eg. for C locale)
322 : :
323 : : mpAttributes = XVaCreateNestedList(
324 : : 0,
325 : : XNFocusWindow, aFocusWindow,
326 : : XNClientWindow, aClientWindow,
327 : : XNInputStyle, mnPreeditStyle | mnStatusStyle,
328 : 0 : NULL );
329 : :
330 : 0 : if ( mnPreeditStyle != XIMPreeditNone )
331 : : {
332 : : #if defined LINUX || defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY
333 : 0 : if ( mpPreeditAttributes != NULL )
334 : : #endif
335 : : mpAttributes = XVaAddToNestedList( mpAttributes,
336 : 0 : const_cast<char*>(XNPreeditAttributes), (XPointer)mpPreeditAttributes );
337 : : }
338 : 0 : if ( mnStatusStyle != XIMStatusNone )
339 : : {
340 : : #if defined LINUX || defined FREEBSD || defined NETBSD || defined OPENBSD || defined DRAGONFLY
341 : 0 : if ( mpStatusAttributes != NULL )
342 : : #endif
343 : : mpAttributes = XVaAddToNestedList( mpAttributes,
344 : 0 : const_cast<char*>(XNStatusAttributes), (XPointer)mpStatusAttributes );
345 : : }
346 : : maContext = XCreateIC( pInputMethod->GetMethod(),
347 : : XNVaNestedList, mpAttributes,
348 : 0 : NULL );
349 : : }
350 : :
351 : 0 : if ( maContext == NULL )
352 : : {
353 : : #if OSL_DEBUG_LEVEL > 1
354 : : fprintf(stderr, "input context creation failed\n");
355 : : #endif
356 : :
357 : 0 : mbUseable = False;
358 : :
359 : 0 : if ( mpAttributes != NULL )
360 : 0 : XFree( mpAttributes );
361 : 0 : if ( mpStatusAttributes != NULL )
362 : 0 : XFree( mpStatusAttributes );
363 : 0 : if ( mpPreeditAttributes != NULL )
364 : 0 : XFree( mpPreeditAttributes );
365 : 0 : if ( maClientData.aText.pUnicodeBuffer != NULL )
366 : 0 : free ( maClientData.aText.pUnicodeBuffer );
367 : 0 : if ( maClientData.aText.pCharStyle != NULL )
368 : 0 : free ( maClientData.aText.pCharStyle );
369 : :
370 : 0 : mpAttributes = NULL;
371 : 0 : mpStatusAttributes = NULL;
372 : 0 : mpPreeditAttributes = NULL;
373 : 0 : maClientData.aText.pUnicodeBuffer = NULL;
374 : 0 : maClientData.aText.pCharStyle = NULL;
375 : : }
376 : :
377 : 0 : if ( maContext != NULL)
378 : : {
379 : 0 : maDestroyCallback.callback = (XIMProc)IC_IMDestroyCallback;
380 : 0 : maDestroyCallback.client_data = (XPointer)this;
381 : : XSetICValues( maContext,
382 : : XNDestroyCallback, &maDestroyCallback,
383 : 0 : NULL );
384 : : }
385 : 0 : }
386 : :
387 : : // ---------------------------------------------------------------------------
388 : : //
389 : : // In Solaris 8 the status window does not unmap if the frame unmapps, so
390 : : // unmap it the hard way
391 : : //
392 : : // ---------------------------------------------------------------------------
393 : :
394 : : void
395 : 0 : SalI18N_InputContext::Unmap( SalFrame* pFrame )
396 : : {
397 : 0 : if ( maContext != NULL )
398 : : {
399 : 0 : I18NStatus& rStatus( I18NStatus::get() );
400 : 0 : if( rStatus.getParent() == pFrame )
401 : 0 : rStatus.show( false, I18NStatus::contextmap );
402 : :
403 : : }
404 : 0 : UnsetICFocus( pFrame );
405 : 0 : maClientData.pFrame = NULL;
406 : 0 : }
407 : :
408 : : void
409 : 0 : SalI18N_InputContext::Map( SalFrame *pFrame )
410 : : {
411 : 0 : if( mbUseable )
412 : : {
413 : 0 : I18NStatus& rStatus(I18NStatus::get() );
414 : 0 : rStatus.setParent( pFrame );
415 : 0 : if( pFrame )
416 : : {
417 : 0 : rStatus.show( true, I18NStatus::contextmap );
418 : 0 : if ( maContext == NULL )
419 : : {
420 : : SalI18N_InputMethod *pInputMethod;
421 : 0 : pInputMethod = GetGenericData()->GetSalDisplay()->GetInputMethod();
422 : :
423 : : maContext = XCreateIC( pInputMethod->GetMethod(),
424 : : XNVaNestedList, mpAttributes,
425 : 0 : NULL );
426 : : }
427 : 0 : if( maClientData.pFrame != pFrame )
428 : 0 : SetICFocus( pFrame );
429 : : }
430 : : }
431 : 0 : }
432 : :
433 : : // --------------------------------------------------------------------------
434 : : //
435 : : // Handle DestroyCallbacks
436 : : // in fact this is a callback called from the XNDestroyCallback
437 : : //
438 : : // --------------------------------------------------------------------------
439 : :
440 : : void
441 : 0 : SalI18N_InputContext::HandleDestroyIM()
442 : : {
443 : 0 : maContext = 0; // noli me tangere
444 : 0 : mbUseable = False;
445 : 0 : }
446 : :
447 : : // ---------------------------------------------------------------------------
448 : : //
449 : : // make sure, the input method gets all the X-Events it needs, this is only
450 : : // called once on each frame, it relys on a valid maContext
451 : : //
452 : : // ---------------------------------------------------------------------------
453 : :
454 : : void
455 : 0 : SalI18N_InputContext::ExtendEventMask( XLIB_Window aFocusWindow )
456 : : {
457 : : unsigned long nIMEventMask;
458 : : XWindowAttributes aWindowAttributes;
459 : :
460 : 0 : if ( mbUseable )
461 : : {
462 : 0 : Display *pDisplay = XDisplayOfIM( XIMOfIC(maContext) );
463 : :
464 : : XGetWindowAttributes( pDisplay, aFocusWindow,
465 : 0 : &aWindowAttributes );
466 : : XGetICValues ( maContext,
467 : : XNFilterEvents, &nIMEventMask,
468 : 0 : NULL);
469 : 0 : nIMEventMask |= aWindowAttributes.your_event_mask;
470 : 0 : XSelectInput ( pDisplay, aFocusWindow, nIMEventMask );
471 : : }
472 : 0 : }
473 : :
474 : : // ---------------------------------------------------------------------------
475 : : //
476 : : // tune the styles provided by the input method with the supported one
477 : : //
478 : : // ---------------------------------------------------------------------------
479 : :
480 : : unsigned int
481 : 0 : SalI18N_InputContext::GetWeightingOfIMStyle( XIMStyle nStyle ) const
482 : : {
483 : : struct StyleWeightingT {
484 : : const XIMStyle nStyle;
485 : : const unsigned int nWeight;
486 : : };
487 : :
488 : : StyleWeightingT const *pWeightPtr;
489 : : const StyleWeightingT pWeight[] = {
490 : : { XIMPreeditCallbacks, 0x10000000 },
491 : : { XIMPreeditPosition, 0x02000000 },
492 : : { XIMPreeditArea, 0x01000000 },
493 : : { XIMPreeditNothing, 0x00100000 },
494 : : { XIMPreeditNone, 0x00010000 },
495 : : { XIMStatusCallbacks, 0x1000 },
496 : : { XIMStatusArea, 0x0100 },
497 : : { XIMStatusNothing, 0x0010 },
498 : : { XIMStatusNone, 0x0001 },
499 : : { 0, 0x0 }
500 : 0 : };
501 : :
502 : 0 : int nWeight = 0;
503 : 0 : for ( pWeightPtr = pWeight; pWeightPtr->nStyle != 0; pWeightPtr++ )
504 : : {
505 : 0 : if ( (pWeightPtr->nStyle & nStyle) != 0 )
506 : 0 : nWeight += pWeightPtr->nWeight;
507 : : }
508 : 0 : return nWeight;
509 : : }
510 : :
511 : : Bool
512 : 0 : SalI18N_InputContext::IsSupportedIMStyle( XIMStyle nStyle ) const
513 : : {
514 : 0 : if ( (nStyle & mnSupportedPreeditStyle)
515 : : && (nStyle & mnSupportedStatusStyle) )
516 : : {
517 : 0 : return True;
518 : : }
519 : 0 : return False;
520 : : }
521 : :
522 : : Bool
523 : 0 : SalI18N_InputContext::SupportInputMethodStyle( XIMStyles *pIMStyles )
524 : : {
525 : 0 : mnPreeditStyle = 0;
526 : 0 : mnStatusStyle = 0;
527 : :
528 : 0 : if ( pIMStyles != NULL )
529 : : {
530 : 0 : int nBestScore = 0;
531 : 0 : int nActualScore = 0;
532 : :
533 : : // check whether the XIM supports one of the desired styles
534 : : // only a single preedit and a single status style must occure
535 : : // in a inpuut method style. Hideki said so, so i trust him
536 : 0 : for ( int nStyle = 0; nStyle < pIMStyles->count_styles; nStyle++ )
537 : : {
538 : 0 : XIMStyle nProvidedStyle = pIMStyles->supported_styles[ nStyle ];
539 : 0 : if ( IsSupportedIMStyle(nProvidedStyle) )
540 : : {
541 : 0 : nActualScore = GetWeightingOfIMStyle( nProvidedStyle );
542 : 0 : if ( nActualScore >= nBestScore )
543 : : {
544 : 0 : nBestScore = nActualScore;
545 : 0 : mnPreeditStyle = nProvidedStyle & mnSupportedPreeditStyle;
546 : 0 : mnStatusStyle = nProvidedStyle & mnSupportedStatusStyle;
547 : : }
548 : : }
549 : : }
550 : : }
551 : :
552 : : #if OSL_DEBUG_LEVEL > 1
553 : : char pBuf[ 128 ];
554 : : fprintf( stderr, "selected inputmethod style = %s\n",
555 : : GetMethodName(mnPreeditStyle | mnStatusStyle, pBuf, sizeof(pBuf)) );
556 : : #endif
557 : :
558 : 0 : return (mnPreeditStyle != 0) && (mnStatusStyle != 0) ;
559 : : }
560 : :
561 : : // ---------------------------------------------------------------------------
562 : : //
563 : : // handle extended and normal key input
564 : : //
565 : : // ---------------------------------------------------------------------------
566 : :
567 : : int
568 : 0 : SalI18N_InputContext::CommitKeyEvent(sal_Unicode* pText, sal_Size nLength)
569 : : {
570 : 0 : if (nLength == 1 && IsControlCode(pText[0]))
571 : 0 : return 0;
572 : :
573 : 0 : if( maClientData.pFrame )
574 : : {
575 : 0 : SalExtTextInputEvent aTextEvent;
576 : :
577 : 0 : aTextEvent.mnTime = 0;
578 : 0 : aTextEvent.mpTextAttr = 0;
579 : 0 : aTextEvent.mnCursorPos = nLength;
580 : 0 : aTextEvent.maText = rtl::OUString(pText, nLength);
581 : 0 : aTextEvent.mnCursorFlags = 0;
582 : 0 : aTextEvent.mnDeltaStart = 0;
583 : 0 : aTextEvent.mbOnlyCursor = False;
584 : :
585 : 0 : maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUT, (void*)&aTextEvent);
586 : 0 : maClientData.pFrame->CallCallback(SALEVENT_ENDEXTTEXTINPUT, (void*)NULL);
587 : : }
588 : : #if OSL_DEBUG_LEVEL > 1
589 : : else
590 : : fprintf(stderr, "CommitKeyEvent without frame\n" );
591 : : #endif
592 : :
593 : 0 : return 0;
594 : : }
595 : :
596 : : int
597 : 0 : SalI18N_InputContext::UpdateSpotLocation()
598 : : {
599 : 0 : if (maContext == 0 || maClientData.pFrame == NULL)
600 : 0 : return -1;
601 : :
602 : : SalExtTextInputPosEvent aPosEvent;
603 : 0 : maClientData.pFrame->CallCallback(SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent);
604 : :
605 : : XPoint aSpot;
606 : 0 : aSpot.x = aPosEvent.mnX + aPosEvent.mnWidth;
607 : 0 : aSpot.y = aPosEvent.mnY + aPosEvent.mnHeight;
608 : :
609 : 0 : XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &aSpot, NULL);
610 : 0 : XSetICValues(maContext, XNPreeditAttributes, preedit_attr, NULL);
611 : 0 : XFree(preedit_attr);
612 : :
613 : 0 : I18NStatus::get().show( true, I18NStatus::contextmap );
614 : :
615 : 0 : return 0;
616 : : }
617 : :
618 : : // ---------------------------------------------------------------------------
619 : : //
620 : : // set and unset the focus for the Input Context
621 : : // the context may be NULL despite it is useable if the framewindow is
622 : : // in unmapped state
623 : : //
624 : : // ---------------------------------------------------------------------------
625 : :
626 : : void
627 : 0 : SalI18N_InputContext::SetICFocus( SalFrame* pFocusFrame )
628 : : {
629 : 0 : I18NStatus::get().setParent( pFocusFrame );
630 : 0 : if ( mbUseable && (maContext != NULL) )
631 : : {
632 : 0 : maClientData.pFrame = pFocusFrame;
633 : :
634 : 0 : const SystemEnvData* pEnv = pFocusFrame->GetSystemData();
635 : 0 : XLIB_Window aClientWindow = pEnv->aShellWindow;
636 : 0 : XLIB_Window aFocusWindow = pEnv->aWindow;
637 : :
638 : : XSetICValues( maContext,
639 : : XNFocusWindow, aFocusWindow,
640 : : XNClientWindow, aClientWindow,
641 : 0 : NULL );
642 : :
643 : 0 : if( maClientData.aInputEv.mpTextAttr )
644 : : {
645 : 0 : sendEmptyCommit(pFocusFrame);
646 : : // begin preedit again
647 : 0 : GetGenericData()->GetSalDisplay()->SendInternalEvent( pFocusFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
648 : : }
649 : :
650 : 0 : XSetICFocus( maContext );
651 : : }
652 : 0 : }
653 : :
654 : : void
655 : 0 : SalI18N_InputContext::UnsetICFocus( SalFrame* pFrame )
656 : : {
657 : 0 : I18NStatus& rStatus( I18NStatus::get() );
658 : 0 : if( rStatus.getParent() == pFrame )
659 : 0 : rStatus.setParent( NULL );
660 : :
661 : 0 : if ( mbUseable && (maContext != NULL) )
662 : : {
663 : : // cancel an eventual event posted to begin preedit again
664 : 0 : GetGenericData()->GetSalDisplay()->CancelInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
665 : 0 : maClientData.pFrame = NULL;
666 : 0 : XUnsetICFocus( maContext );
667 : : }
668 : 0 : }
669 : :
670 : : // ---------------------------------------------------------------------------
671 : : //
672 : : // multi byte input method only
673 : : //
674 : : // ---------------------------------------------------------------------------
675 : :
676 : : void
677 : 0 : SalI18N_InputContext::SetLanguage(LanguageType)
678 : : {
679 : : // not yet implemented
680 : 0 : return;
681 : : }
682 : :
683 : : void
684 : 0 : SalI18N_InputContext::EndExtTextInput( sal_uInt16 /*nFlags*/ )
685 : : {
686 : 0 : if ( mbUseable && (maContext != NULL) && maClientData.pFrame )
687 : : {
688 : 0 : vcl::DeletionListener aDel( maClientData.pFrame );
689 : : // delete preedit in sal (commit an empty string)
690 : 0 : sendEmptyCommit( maClientData.pFrame );
691 : 0 : if( ! aDel.isDeleted() )
692 : : {
693 : : // mark previous preedit state again (will e.g. be sent at focus gain)
694 : 0 : maClientData.aInputEv.mpTextAttr = &maClientData.aInputFlags[0];
695 : 0 : if( static_cast<X11SalFrame*>(maClientData.pFrame)->hasFocus() )
696 : : {
697 : : // begin preedit again
698 : 0 : GetGenericData()->GetSalDisplay()->SendInternalEvent( maClientData.pFrame, &maClientData.aInputEv, SALEVENT_EXTTEXTINPUT );
699 : : }
700 : 0 : }
701 : : }
702 : 0 : }
703 : :
704 : :
705 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|