xref: /aoo42x/main/vcl/unx/generic/app/i18n_status.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_vcl.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
32*cdf0e10cSrcweir #include <stdio.h>
33*cdf0e10cSrcweir #endif
34*cdf0e10cSrcweir #include <sal/alloca.h>
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir #include <tools/prex.h>
37*cdf0e10cSrcweir #include <X11/Xlib.h>
38*cdf0e10cSrcweir #include <unx/XIM.h>
39*cdf0e10cSrcweir #include <tools/postx.h>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include <unx/salunx.h>
42*cdf0e10cSrcweir #include <unx/i18n_status.hxx>
43*cdf0e10cSrcweir #include <unx/i18n_ic.hxx>
44*cdf0e10cSrcweir #include <unx/saldisp.hxx>
45*cdf0e10cSrcweir #include <unx/salframe.h>
46*cdf0e10cSrcweir #include <unx/saldata.hxx>
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #include <vcl/wrkwin.hxx>
49*cdf0e10cSrcweir #include <vcl/fixed.hxx>
50*cdf0e10cSrcweir #include <vcl/menubtn.hxx>
51*cdf0e10cSrcweir #include <vcl/menu.hxx>
52*cdf0e10cSrcweir #include <vcl/svapp.hxx>
53*cdf0e10cSrcweir #include <vcl/sysdata.hxx>
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir #include <svdata.hxx>
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir using namespace vcl;
58*cdf0e10cSrcweir using namespace rtl;
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir namespace vcl {
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir class StatusWindow : public WorkWindow
63*cdf0e10cSrcweir {
64*cdf0e10cSrcweir protected:
65*cdf0e10cSrcweir     StatusWindow( WinBits nWinBits );
66*cdf0e10cSrcweir public:
67*cdf0e10cSrcweir     virtual ~StatusWindow();
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir     virtual void setPosition( SalFrame* );
70*cdf0e10cSrcweir     virtual void setText( const String & ) = 0;
71*cdf0e10cSrcweir     virtual String getText() const = 0;
72*cdf0e10cSrcweir     virtual void show( bool bShow, I18NStatus::ShowReason eReason ) = 0;
73*cdf0e10cSrcweir     virtual void toggle( bool bOn ) = 0;
74*cdf0e10cSrcweir };
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir }
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir StatusWindow::StatusWindow( WinBits nWinBits ) :
79*cdf0e10cSrcweir         WorkWindow( NULL, nWinBits )
80*cdf0e10cSrcweir {
81*cdf0e10cSrcweir }
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir StatusWindow::~StatusWindow() {}
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir void StatusWindow::setPosition( SalFrame* )
86*cdf0e10cSrcweir {
87*cdf0e10cSrcweir }
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir // --------------------------------------------------------------------------
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir namespace vcl {
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir class XIMStatusWindow : public StatusWindow
94*cdf0e10cSrcweir {
95*cdf0e10cSrcweir     FixedText				m_aStatusText;
96*cdf0e10cSrcweir     SalFrame*				m_pLastParent;
97*cdf0e10cSrcweir     Size					m_aWindowSize;
98*cdf0e10cSrcweir     bool                    m_bAnchoredAtRight;
99*cdf0e10cSrcweir         // true if the right edge (instead of the left edge) should stay at a
100*cdf0e10cSrcweir         // fixed position when re-sizing the window
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir     // for delayed showing
103*cdf0e10cSrcweir     bool					m_bDelayedShow;
104*cdf0e10cSrcweir     I18NStatus::ShowReason	m_eDelayedReason;
105*cdf0e10cSrcweir     sal_uLong					m_nDelayedEvent;
106*cdf0e10cSrcweir     // for toggling
107*cdf0e10cSrcweir     bool                    m_bOn;
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir     Point updatePosition();
110*cdf0e10cSrcweir     void layout();
111*cdf0e10cSrcweir     bool checkLastParent() const;
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     DECL_LINK( DelayedShowHdl, void* );
114*cdf0e10cSrcweir public:
115*cdf0e10cSrcweir     XIMStatusWindow( bool bOn );
116*cdf0e10cSrcweir     virtual ~XIMStatusWindow();
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir     virtual void setPosition( SalFrame* );
119*cdf0e10cSrcweir     virtual void setText( const String & );
120*cdf0e10cSrcweir     virtual String getText() const;
121*cdf0e10cSrcweir     virtual void show( bool bShow, I18NStatus::ShowReason eReason );
122*cdf0e10cSrcweir     virtual void toggle( bool bOn );
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir     // overload WorkWindow::DataChanged
125*cdf0e10cSrcweir     virtual void DataChanged( const DataChangedEvent& rEvt );
126*cdf0e10cSrcweir };
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir }
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir XIMStatusWindow::XIMStatusWindow( bool bOn ) :
131*cdf0e10cSrcweir         StatusWindow( WB_BORDER | WB_SYSTEMFLOATWIN | WB_TOOLTIPWIN ),
132*cdf0e10cSrcweir         m_aStatusText( this, 0 ),
133*cdf0e10cSrcweir         m_pLastParent( NULL ),
134*cdf0e10cSrcweir         m_bAnchoredAtRight( false ),
135*cdf0e10cSrcweir         m_bDelayedShow( false ),
136*cdf0e10cSrcweir         m_eDelayedReason( I18NStatus::contextmap ),
137*cdf0e10cSrcweir         m_nDelayedEvent( 0 ),
138*cdf0e10cSrcweir         m_bOn( bOn )
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir     layout();
141*cdf0e10cSrcweir }
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir XIMStatusWindow::~XIMStatusWindow()
144*cdf0e10cSrcweir {
145*cdf0e10cSrcweir     if( m_nDelayedEvent )
146*cdf0e10cSrcweir         Application::RemoveUserEvent( m_nDelayedEvent );
147*cdf0e10cSrcweir }
148*cdf0e10cSrcweir 
149*cdf0e10cSrcweir void XIMStatusWindow::toggle( bool bOn )
150*cdf0e10cSrcweir {
151*cdf0e10cSrcweir     m_bOn = bOn;
152*cdf0e10cSrcweir     show( bOn, I18NStatus::contextmap );
153*cdf0e10cSrcweir }
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir void XIMStatusWindow::layout()
156*cdf0e10cSrcweir {
157*cdf0e10cSrcweir     m_aWindowSize.Width() = m_aStatusText.GetTextWidth( m_aStatusText.GetText() )+8;
158*cdf0e10cSrcweir     Font aFont( m_aStatusText.GetFont() );
159*cdf0e10cSrcweir     m_aWindowSize.Height() = aFont.GetHeight()+10;
160*cdf0e10cSrcweir     m_aWindowSize = LogicToPixel( m_aWindowSize );
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir     Size aControlSize( m_aWindowSize );
163*cdf0e10cSrcweir     aControlSize.Width()  -= 4;
164*cdf0e10cSrcweir     aControlSize.Height() -= 4;
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir     m_aStatusText.SetPosSizePixel( Point( 1, 1 ), aControlSize );
167*cdf0e10cSrcweir     m_aStatusText.SetFont( aFont );
168*cdf0e10cSrcweir     m_aStatusText.Show( sal_True );
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir     if (m_bAnchoredAtRight && IsVisible())
171*cdf0e10cSrcweir     {
172*cdf0e10cSrcweir         SalFrame* pFrame = (SalFrame*)GetSystemData()->pSalFrame;
173*cdf0e10cSrcweir         long nDelta = pFrame->maGeometry.nWidth - m_aWindowSize.Width();
174*cdf0e10cSrcweir         pFrame->SetPosSize( pFrame->maGeometry.nX + nDelta,
175*cdf0e10cSrcweir                             pFrame->maGeometry.nY,
176*cdf0e10cSrcweir                             m_aWindowSize.Width(),
177*cdf0e10cSrcweir                             m_aWindowSize.Height(),
178*cdf0e10cSrcweir                             SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
179*cdf0e10cSrcweir     }
180*cdf0e10cSrcweir     else
181*cdf0e10cSrcweir         SetOutputSizePixel( m_aWindowSize );
182*cdf0e10cSrcweir }
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir bool XIMStatusWindow::checkLastParent() const
185*cdf0e10cSrcweir {
186*cdf0e10cSrcweir     if( m_pLastParent )
187*cdf0e10cSrcweir     {
188*cdf0e10cSrcweir         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
189*cdf0e10cSrcweir         for( std::list< SalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
190*cdf0e10cSrcweir         {
191*cdf0e10cSrcweir             if( *it == m_pLastParent )
192*cdf0e10cSrcweir                 return true;
193*cdf0e10cSrcweir         }
194*cdf0e10cSrcweir     }
195*cdf0e10cSrcweir     return false;
196*cdf0e10cSrcweir }
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir void XIMStatusWindow::DataChanged( const DataChangedEvent& )
199*cdf0e10cSrcweir {
200*cdf0e10cSrcweir     m_aStatusText.SetSettings( GetSettings() );
201*cdf0e10cSrcweir     layout();
202*cdf0e10cSrcweir }
203*cdf0e10cSrcweir 
204*cdf0e10cSrcweir Point XIMStatusWindow::updatePosition()
205*cdf0e10cSrcweir {
206*cdf0e10cSrcweir     Point aRet;
207*cdf0e10cSrcweir     if( checkLastParent() )
208*cdf0e10cSrcweir     {
209*cdf0e10cSrcweir         const SystemEnvData* pParentEnvData = m_pLastParent->GetSystemData();
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir         SalExtTextInputPosEvent aPosEvent;
212*cdf0e10cSrcweir         m_pLastParent->CallCallback( SALEVENT_EXTTEXTINPUTPOS, (void*)&aPosEvent );
213*cdf0e10cSrcweir         int x, y;
214*cdf0e10cSrcweir         XLIB_Window aChild;
215*cdf0e10cSrcweir         XTranslateCoordinates( (Display*)pParentEnvData->pDisplay,
216*cdf0e10cSrcweir                                (XLIB_Window)pParentEnvData->aShellWindow,
217*cdf0e10cSrcweir                                GetX11SalData()->GetDisplay()->GetRootWindow( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ),
218*cdf0e10cSrcweir                                0, 0,
219*cdf0e10cSrcweir                                &x, &y,
220*cdf0e10cSrcweir                                &aChild );
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir         // TODO:  Currently, place the status window to the (physical) left of
223*cdf0e10cSrcweir         // the cursor iff in vertical mode (assuming that the columns in
224*cdf0e10cSrcweir         // vertical mode are always written from right to left, this causes the
225*cdf0e10cSrcweir         // status window to keep out of the text already written).  This
226*cdf0e10cSrcweir         // heuristic would break if there is ever a vertical mode in which the
227*cdf0e10cSrcweir         // columns are written from left to right.  Also, more elaborate
228*cdf0e10cSrcweir         // positioning for (both horizontal and vertical) left-to-right and
229*cdf0e10cSrcweir         // right-to-left text would be possible.
230*cdf0e10cSrcweir         bool bLeft = aPosEvent.mbVertical;
231*cdf0e10cSrcweir             // true if status window is to the left of the cursor
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir         int const nGap = 4; // between cursor and status window
234*cdf0e10cSrcweir         if (aPosEvent.mbVertical)
235*cdf0e10cSrcweir         {
236*cdf0e10cSrcweir             aRet.X() = x + aPosEvent.mnX + (bLeft
237*cdf0e10cSrcweir                                             ? -m_aWindowSize.Width() - nGap
238*cdf0e10cSrcweir                                             : aPosEvent.mnHeight + nGap);
239*cdf0e10cSrcweir             aRet.Y() = y + aPosEvent.mnY;
240*cdf0e10cSrcweir         }
241*cdf0e10cSrcweir         else
242*cdf0e10cSrcweir         {
243*cdf0e10cSrcweir             aRet.X() = x + aPosEvent.mnX + (bLeft ? -m_aWindowSize.Width() : 0);
244*cdf0e10cSrcweir             aRet.Y() = y + aPosEvent.mnY+aPosEvent.mnHeight + nGap;
245*cdf0e10cSrcweir         }
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir         m_bAnchoredAtRight = bLeft;
248*cdf0e10cSrcweir     }
249*cdf0e10cSrcweir     return aRet;
250*cdf0e10cSrcweir }
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir void XIMStatusWindow::setPosition( SalFrame* pParent )
253*cdf0e10cSrcweir {
254*cdf0e10cSrcweir     if( pParent )
255*cdf0e10cSrcweir     {
256*cdf0e10cSrcweir         if( pParent != m_pLastParent )
257*cdf0e10cSrcweir         {
258*cdf0e10cSrcweir             setText( String() );
259*cdf0e10cSrcweir             m_pLastParent = pParent;
260*cdf0e10cSrcweir             Show( sal_False, SHOW_NOACTIVATE );
261*cdf0e10cSrcweir         }
262*cdf0e10cSrcweir         if( IsVisible() )
263*cdf0e10cSrcweir         {
264*cdf0e10cSrcweir             const SystemEnvData* pEnvData = GetSystemData();
265*cdf0e10cSrcweir             SalFrame* pStatusFrame = (SalFrame*)pEnvData->pSalFrame;
266*cdf0e10cSrcweir             Point aPoint = updatePosition();
267*cdf0e10cSrcweir             pStatusFrame->SetPosSize( aPoint.X(), aPoint.Y(), m_aWindowSize.Width(), m_aWindowSize.Height(), SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
268*cdf0e10cSrcweir         }
269*cdf0e10cSrcweir     }
270*cdf0e10cSrcweir }
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir IMPL_LINK( XIMStatusWindow, DelayedShowHdl, void*, EMPTYARG )
273*cdf0e10cSrcweir {
274*cdf0e10cSrcweir     m_nDelayedEvent = 0;
275*cdf0e10cSrcweir     const SystemEnvData* pData = GetSystemData();
276*cdf0e10cSrcweir     SalFrame* pStatusFrame = (SalFrame*)pData->pSalFrame;
277*cdf0e10cSrcweir     if( m_bDelayedShow )
278*cdf0e10cSrcweir     {
279*cdf0e10cSrcweir         Size aControlSize( m_aWindowSize.Width()-4, m_aWindowSize.Height()-4 );
280*cdf0e10cSrcweir         m_aStatusText.SetPosSizePixel( Point( 1, 1 ), aControlSize );
281*cdf0e10cSrcweir         Point aPoint = updatePosition();
282*cdf0e10cSrcweir         pStatusFrame->SetPosSize( aPoint.X(), aPoint.Y(), m_aWindowSize.Width(), m_aWindowSize.Height(), SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y | SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT );
283*cdf0e10cSrcweir     }
284*cdf0e10cSrcweir     Show( m_bDelayedShow && m_bOn, SHOW_NOACTIVATE );
285*cdf0e10cSrcweir     if( m_bDelayedShow )
286*cdf0e10cSrcweir     {
287*cdf0e10cSrcweir 		XRaiseWindow( (Display*)pData->pDisplay,
288*cdf0e10cSrcweir                       (XLIB_Window)pData->aShellWindow );
289*cdf0e10cSrcweir     }
290*cdf0e10cSrcweir     return 0;
291*cdf0e10cSrcweir }
292*cdf0e10cSrcweir 
293*cdf0e10cSrcweir void XIMStatusWindow::show( bool bShow, I18NStatus::ShowReason eReason )
294*cdf0e10cSrcweir {
295*cdf0e10cSrcweir     if( bShow && ! m_aStatusText.GetText().Len() )
296*cdf0e10cSrcweir         bShow = false;
297*cdf0e10cSrcweir 
298*cdf0e10cSrcweir     m_bDelayedShow = bShow;
299*cdf0e10cSrcweir     m_eDelayedReason = eReason;
300*cdf0e10cSrcweir     if( ! m_nDelayedEvent )
301*cdf0e10cSrcweir         m_nDelayedEvent = Application::PostUserEvent( LINK( this, XIMStatusWindow, DelayedShowHdl ) );
302*cdf0e10cSrcweir }
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir void XIMStatusWindow::setText( const String& rText )
305*cdf0e10cSrcweir {
306*cdf0e10cSrcweir     m_aStatusText.SetText( rText );
307*cdf0e10cSrcweir     m_aWindowSize.Width() = m_aStatusText.GetTextWidth( rText )+8;
308*cdf0e10cSrcweir }
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir String XIMStatusWindow::getText() const
311*cdf0e10cSrcweir {
312*cdf0e10cSrcweir     return m_aStatusText.GetText();
313*cdf0e10cSrcweir }
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir // --------------------------------------------------------------------------
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir namespace vcl {
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir class IIIMPStatusWindow : public StatusWindow
320*cdf0e10cSrcweir {
321*cdf0e10cSrcweir     MenuButton				m_aStatusBtn;
322*cdf0e10cSrcweir     PopupMenu				m_aMenu;
323*cdf0e10cSrcweir     SalFrame*				m_pResetFocus;
324*cdf0e10cSrcweir     bool                    m_bShow;
325*cdf0e10cSrcweir     bool                    m_bOn;
326*cdf0e10cSrcweir 
327*cdf0e10cSrcweir     DECL_LINK( SelectHdl, MenuButton* );
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir     void show();
330*cdf0e10cSrcweir 
331*cdf0e10cSrcweir public:
332*cdf0e10cSrcweir     IIIMPStatusWindow( SalFrame* pParent, bool bOn ); // for initial position
333*cdf0e10cSrcweir     virtual ~IIIMPStatusWindow();
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir     virtual void setText( const String & );
336*cdf0e10cSrcweir     virtual String getText() const;
337*cdf0e10cSrcweir     virtual void show( bool bShow, I18NStatus::ShowReason eReason );
338*cdf0e10cSrcweir     virtual void toggle( bool bOn );
339*cdf0e10cSrcweir     void layout();
340*cdf0e10cSrcweir 
341*cdf0e10cSrcweir     // overload Window focus handler
342*cdf0e10cSrcweir     virtual void        GetFocus();
343*cdf0e10cSrcweir     // overload WorkWindow::DataChanged
344*cdf0e10cSrcweir     virtual void DataChanged( const DataChangedEvent& rEvt );
345*cdf0e10cSrcweir };
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir }
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir IIIMPStatusWindow::IIIMPStatusWindow( SalFrame* pParent, bool bOn ) :
350*cdf0e10cSrcweir         StatusWindow( WB_MOVEABLE ),
351*cdf0e10cSrcweir         m_aStatusBtn( this, WB_BORDER ),
352*cdf0e10cSrcweir         m_pResetFocus( pParent ),
353*cdf0e10cSrcweir         m_bShow( true ),
354*cdf0e10cSrcweir         m_bOn( bOn )
355*cdf0e10cSrcweir {
356*cdf0e10cSrcweir     SetText( String( RTL_CONSTASCII_USTRINGPARAM( "IME Status" ) ) );
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir     layout();
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir     m_aStatusBtn.SetSelectHdl( LINK( this, IIIMPStatusWindow, SelectHdl ) );
361*cdf0e10cSrcweir     m_aStatusBtn.SetPopupMenu( &m_aMenu );
362*cdf0e10cSrcweir     m_aStatusBtn.Show( sal_True );
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir     const ::std::vector< I18NStatus::ChoiceData >& rChoices( I18NStatus::get().getChoices() );
365*cdf0e10cSrcweir     int i = 1;
366*cdf0e10cSrcweir     for( ::std::vector< I18NStatus::ChoiceData >::const_iterator it = rChoices.begin(); it != rChoices.end(); ++it, i++ )
367*cdf0e10cSrcweir         m_aMenu.InsertItem( i, it->aString );
368*cdf0e10cSrcweir 
369*cdf0e10cSrcweir     if( pParent )
370*cdf0e10cSrcweir     {
371*cdf0e10cSrcweir         const SystemEnvData* pEnvData = GetSystemData();
372*cdf0e10cSrcweir 
373*cdf0e10cSrcweir         const SalFrameGeometry& rGeom( pParent->GetUnmirroredGeometry() );
374*cdf0e10cSrcweir         int nDistance = rGeom.nTopDecoration;
375*cdf0e10cSrcweir         if( nDistance < 20 )
376*cdf0e10cSrcweir             nDistance = 20;
377*cdf0e10cSrcweir         XMoveWindow( (Display*)pEnvData->pDisplay,
378*cdf0e10cSrcweir                      (XLIB_Window)pEnvData->aShellWindow,
379*cdf0e10cSrcweir                      rGeom.nX,
380*cdf0e10cSrcweir                      rGeom.nY + rGeom.nHeight + nDistance
381*cdf0e10cSrcweir                      );
382*cdf0e10cSrcweir     }
383*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
384*cdf0e10cSrcweir     else
385*cdf0e10cSrcweir         fprintf( stderr, "Warning: could not reposition status window since no frame\n" );
386*cdf0e10cSrcweir #endif
387*cdf0e10cSrcweir     EnableAlwaysOnTop( sal_True );
388*cdf0e10cSrcweir }
389*cdf0e10cSrcweir 
390*cdf0e10cSrcweir IIIMPStatusWindow::~IIIMPStatusWindow()
391*cdf0e10cSrcweir {
392*cdf0e10cSrcweir }
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir void IIIMPStatusWindow::layout()
395*cdf0e10cSrcweir {
396*cdf0e10cSrcweir     Font aFont( m_aStatusBtn.GetFont() );
397*cdf0e10cSrcweir     Size aSize( 15*aFont.GetHeight(), aFont.GetHeight()+14 );
398*cdf0e10cSrcweir     aSize = m_aStatusBtn.LogicToPixel( aSize );
399*cdf0e10cSrcweir 
400*cdf0e10cSrcweir     m_aStatusBtn.SetPosSizePixel( Point( 0, 0 ), aSize );
401*cdf0e10cSrcweir     SetOutputSizePixel( aSize );
402*cdf0e10cSrcweir     if( IsVisible() )
403*cdf0e10cSrcweir         Invalidate();
404*cdf0e10cSrcweir }
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir void IIIMPStatusWindow::DataChanged( const DataChangedEvent& )
407*cdf0e10cSrcweir {
408*cdf0e10cSrcweir     m_aStatusBtn.SetSettings( GetSettings() );
409*cdf0e10cSrcweir     layout();
410*cdf0e10cSrcweir }
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir void IIIMPStatusWindow::setText( const String& rText )
413*cdf0e10cSrcweir {
414*cdf0e10cSrcweir     m_aStatusBtn.SetText( rText );
415*cdf0e10cSrcweir }
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir String IIIMPStatusWindow::getText() const
418*cdf0e10cSrcweir {
419*cdf0e10cSrcweir     return m_aStatusBtn.GetText();
420*cdf0e10cSrcweir }
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir void IIIMPStatusWindow::show( bool bShow, I18NStatus::ShowReason eReason )
423*cdf0e10cSrcweir {
424*cdf0e10cSrcweir     // hide IIIMPStatusWindow only in presentations
425*cdf0e10cSrcweir     if( ! bShow
426*cdf0e10cSrcweir         && eReason != I18NStatus::presentation
427*cdf0e10cSrcweir         )
428*cdf0e10cSrcweir         return;
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir     m_bShow = bShow;
431*cdf0e10cSrcweir     show();
432*cdf0e10cSrcweir }
433*cdf0e10cSrcweir 
434*cdf0e10cSrcweir void IIIMPStatusWindow::toggle( bool bOn )
435*cdf0e10cSrcweir {
436*cdf0e10cSrcweir     if (bOn != m_bOn)
437*cdf0e10cSrcweir     {
438*cdf0e10cSrcweir         m_bOn = bOn;
439*cdf0e10cSrcweir         show();
440*cdf0e10cSrcweir     }
441*cdf0e10cSrcweir }
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir void IIIMPStatusWindow::show()
444*cdf0e10cSrcweir {
445*cdf0e10cSrcweir     if (m_bOn && m_bShow && !IsVisible())
446*cdf0e10cSrcweir         m_pResetFocus = I18NStatus::get().getParent();
447*cdf0e10cSrcweir     Show(m_bOn && m_bShow);
448*cdf0e10cSrcweir }
449*cdf0e10cSrcweir 
450*cdf0e10cSrcweir void IIIMPStatusWindow::GetFocus()
451*cdf0e10cSrcweir {
452*cdf0e10cSrcweir     /*
453*cdf0e10cSrcweir      *  this is here just to put the focus back to the application
454*cdf0e10cSrcweir      *  window at startup on clickToFocus WMs
455*cdf0e10cSrcweir      */
456*cdf0e10cSrcweir     WorkWindow::GetFocus();
457*cdf0e10cSrcweir     if( m_pResetFocus )
458*cdf0e10cSrcweir     {
459*cdf0e10cSrcweir         /*
460*cdf0e10cSrcweir          *  look if reset focus still exists
461*cdf0e10cSrcweir          *  since reset focus really is an internal hack there should
462*cdf0e10cSrcweir          *  not be a method to be called in SalFrame destructor
463*cdf0e10cSrcweir          */
464*cdf0e10cSrcweir         const std::list< SalFrame* >& rFrames = GetX11SalData()->GetDisplay()->getFrames();
465*cdf0e10cSrcweir         std::list< SalFrame* >::const_iterator it;
466*cdf0e10cSrcweir         for( it = rFrames.begin(); it != rFrames.end() && *it != m_pResetFocus; ++it )
467*cdf0e10cSrcweir             ;
468*cdf0e10cSrcweir         if( it != rFrames.end() )
469*cdf0e10cSrcweir         {
470*cdf0e10cSrcweir             const SystemEnvData* pParentEnvData = m_pResetFocus->GetSystemData();
471*cdf0e10cSrcweir             SalXLib* pXLib = GetX11SalData()->GetDisplay()->GetXLib();
472*cdf0e10cSrcweir             pXLib->PushXErrorLevel( true );
473*cdf0e10cSrcweir             XSetInputFocus( (Display*)pParentEnvData->pDisplay,
474*cdf0e10cSrcweir                             (XLIB_Window)pParentEnvData->aShellWindow,
475*cdf0e10cSrcweir                             RevertToNone,
476*cdf0e10cSrcweir                             CurrentTime
477*cdf0e10cSrcweir                             );
478*cdf0e10cSrcweir             XSync( (Display*)pParentEnvData->pDisplay, False );
479*cdf0e10cSrcweir             pXLib->PopXErrorLevel();
480*cdf0e10cSrcweir         }
481*cdf0e10cSrcweir         m_pResetFocus = NULL;
482*cdf0e10cSrcweir     }
483*cdf0e10cSrcweir }
484*cdf0e10cSrcweir 
485*cdf0e10cSrcweir // --------------------------------------------------------------------------
486*cdf0e10cSrcweir 
487*cdf0e10cSrcweir IMPL_LINK( IIIMPStatusWindow, SelectHdl, MenuButton*, pBtn )
488*cdf0e10cSrcweir {
489*cdf0e10cSrcweir     if( pBtn == & m_aStatusBtn )
490*cdf0e10cSrcweir     {
491*cdf0e10cSrcweir         const ::std::vector< I18NStatus::ChoiceData >& rChoices( I18NStatus::get().getChoices() );
492*cdf0e10cSrcweir         unsigned int nIndex = m_aStatusBtn.GetCurItemId()-1;
493*cdf0e10cSrcweir         if( nIndex < rChoices.size() )
494*cdf0e10cSrcweir         {
495*cdf0e10cSrcweir             XSetICValues( static_cast<X11SalFrame*>(I18NStatus::get().getParent())->getInputContext()->GetContext(),
496*cdf0e10cSrcweir                           XNUnicodeCharacterSubset,
497*cdf0e10cSrcweir                           rChoices[nIndex].pData,
498*cdf0e10cSrcweir                           NULL);
499*cdf0e10cSrcweir             // FIXME: get rid of X11SalFrame
500*cdf0e10cSrcweir             X11SalFrame* pParent = static_cast<X11SalFrame*>(I18NStatus::get().getParent());
501*cdf0e10cSrcweir             if( pParent && pParent->isMapped() )
502*cdf0e10cSrcweir             {
503*cdf0e10cSrcweir                 const SystemEnvData* pEnv = pParent->GetSystemData();
504*cdf0e10cSrcweir                 SalXLib* pXLib = GetX11SalData()->GetDisplay()->GetXLib();
505*cdf0e10cSrcweir                 pXLib->PushXErrorLevel( true );
506*cdf0e10cSrcweir                 XSetInputFocus( (Display*)pEnv->pDisplay,
507*cdf0e10cSrcweir                                 (XLIB_Window)pEnv->aShellWindow,
508*cdf0e10cSrcweir                                 RevertToNone,
509*cdf0e10cSrcweir                                 CurrentTime
510*cdf0e10cSrcweir                                 );
511*cdf0e10cSrcweir                 XSync( (Display*)pEnv->pDisplay, False );
512*cdf0e10cSrcweir                 pXLib->PopXErrorLevel();
513*cdf0e10cSrcweir             }
514*cdf0e10cSrcweir         }
515*cdf0e10cSrcweir     }
516*cdf0e10cSrcweir     return 0;
517*cdf0e10cSrcweir }
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir /*
520*cdf0e10cSrcweir  *  I18NStatus
521*cdf0e10cSrcweir  */
522*cdf0e10cSrcweir 
523*cdf0e10cSrcweir I18NStatus* I18NStatus::pInstance = NULL;
524*cdf0e10cSrcweir 
525*cdf0e10cSrcweir I18NStatus& I18NStatus::get()
526*cdf0e10cSrcweir {
527*cdf0e10cSrcweir     if( ! pInstance )
528*cdf0e10cSrcweir         pInstance = new I18NStatus();
529*cdf0e10cSrcweir     return *pInstance;
530*cdf0e10cSrcweir }
531*cdf0e10cSrcweir 
532*cdf0e10cSrcweir // --------------------------------------------------------------------------
533*cdf0e10cSrcweir 
534*cdf0e10cSrcweir bool I18NStatus::exists()
535*cdf0e10cSrcweir {
536*cdf0e10cSrcweir     return pInstance != NULL;
537*cdf0e10cSrcweir }
538*cdf0e10cSrcweir 
539*cdf0e10cSrcweir // --------------------------------------------------------------------------
540*cdf0e10cSrcweir 
541*cdf0e10cSrcweir void I18NStatus::free()
542*cdf0e10cSrcweir {
543*cdf0e10cSrcweir     if( pInstance )
544*cdf0e10cSrcweir         delete pInstance, pInstance = NULL;
545*cdf0e10cSrcweir }
546*cdf0e10cSrcweir 
547*cdf0e10cSrcweir // --------------------------------------------------------------------------
548*cdf0e10cSrcweir 
549*cdf0e10cSrcweir I18NStatus::I18NStatus() :
550*cdf0e10cSrcweir         m_pParent( NULL ),
551*cdf0e10cSrcweir         m_pStatusWindow( NULL )
552*cdf0e10cSrcweir {
553*cdf0e10cSrcweir }
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir // --------------------------------------------------------------------------
556*cdf0e10cSrcweir 
557*cdf0e10cSrcweir I18NStatus::~I18NStatus()
558*cdf0e10cSrcweir {
559*cdf0e10cSrcweir     if( m_pStatusWindow )
560*cdf0e10cSrcweir         delete m_pStatusWindow, m_pStatusWindow = NULL;
561*cdf0e10cSrcweir     if( pInstance == this )
562*cdf0e10cSrcweir         pInstance = NULL;
563*cdf0e10cSrcweir }
564*cdf0e10cSrcweir 
565*cdf0e10cSrcweir // --------------------------------------------------------------------------
566*cdf0e10cSrcweir 
567*cdf0e10cSrcweir void I18NStatus::setParent( SalFrame* pParent )
568*cdf0e10cSrcweir {
569*cdf0e10cSrcweir     m_pParent = pParent;
570*cdf0e10cSrcweir     if( ! m_pStatusWindow )
571*cdf0e10cSrcweir     {
572*cdf0e10cSrcweir         bool bIIIMPmode = m_aChoices.begin() != m_aChoices.end();
573*cdf0e10cSrcweir         if( bIIIMPmode )
574*cdf0e10cSrcweir             m_pStatusWindow = new IIIMPStatusWindow( pParent,
575*cdf0e10cSrcweir                                                      getStatusWindowMode() );
576*cdf0e10cSrcweir         else
577*cdf0e10cSrcweir             m_pStatusWindow = new XIMStatusWindow( getStatusWindowMode() );
578*cdf0e10cSrcweir         setStatusText( m_aCurrentIM );
579*cdf0e10cSrcweir     }
580*cdf0e10cSrcweir     m_pStatusWindow->setPosition( m_pParent );
581*cdf0e10cSrcweir }
582*cdf0e10cSrcweir 
583*cdf0e10cSrcweir // --------------------------------------------------------------------------
584*cdf0e10cSrcweir 
585*cdf0e10cSrcweir void I18NStatus::show( bool bShow, ShowReason eReason )
586*cdf0e10cSrcweir {
587*cdf0e10cSrcweir     if( m_pStatusWindow )
588*cdf0e10cSrcweir     {
589*cdf0e10cSrcweir         m_pStatusWindow->setPosition( m_pParent );
590*cdf0e10cSrcweir         m_pStatusWindow->show( bShow, eReason );
591*cdf0e10cSrcweir     }
592*cdf0e10cSrcweir }
593*cdf0e10cSrcweir 
594*cdf0e10cSrcweir // --------------------------------------------------------------------------
595*cdf0e10cSrcweir 
596*cdf0e10cSrcweir void I18NStatus::setStatusText( const String& rText )
597*cdf0e10cSrcweir {
598*cdf0e10cSrcweir     if( m_pStatusWindow )
599*cdf0e10cSrcweir     {
600*cdf0e10cSrcweir         /*
601*cdf0e10cSrcweir          *  #93614# convert fullwidth ASCII forms to ascii
602*cdf0e10cSrcweir          */
603*cdf0e10cSrcweir         int nChars = rText.Len()+1;
604*cdf0e10cSrcweir         sal_Unicode* pBuffer = (sal_Unicode*)alloca( nChars*sizeof( sal_Unicode ) );
605*cdf0e10cSrcweir         const sal_Unicode* pCopy = rText.GetBuffer();
606*cdf0e10cSrcweir         for( int i = 0; i < nChars; i++ )
607*cdf0e10cSrcweir         {
608*cdf0e10cSrcweir             if( pCopy[i] >=0xff00 && pCopy[i] <= 0xff5f )
609*cdf0e10cSrcweir                 pBuffer[i] = (pCopy[i] & 0xff) + 0x20;
610*cdf0e10cSrcweir             else
611*cdf0e10cSrcweir                 pBuffer[i] = pCopy[i];
612*cdf0e10cSrcweir         }
613*cdf0e10cSrcweir         String aText( pBuffer );
614*cdf0e10cSrcweir         m_pStatusWindow->setText( aText );
615*cdf0e10cSrcweir         m_pStatusWindow->setPosition( m_pParent );
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir         bool bVisible = true;
618*cdf0e10cSrcweir         if( m_pParent )
619*cdf0e10cSrcweir         {
620*cdf0e10cSrcweir             long w, h;
621*cdf0e10cSrcweir             m_pParent->GetClientSize( w, h );
622*cdf0e10cSrcweir             if( w == 0 || h == 0 )
623*cdf0e10cSrcweir             {
624*cdf0e10cSrcweir                 bVisible = false;
625*cdf0e10cSrcweir             }
626*cdf0e10cSrcweir         }
627*cdf0e10cSrcweir 
628*cdf0e10cSrcweir         m_pStatusWindow->show( bVisible, contextmap );
629*cdf0e10cSrcweir     }
630*cdf0e10cSrcweir }
631*cdf0e10cSrcweir 
632*cdf0e10cSrcweir // --------------------------------------------------------------------------
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir void I18NStatus::changeIM( const String& rIM )
635*cdf0e10cSrcweir {
636*cdf0e10cSrcweir     m_aCurrentIM = rIM;
637*cdf0e10cSrcweir }
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir // --------------------------------------------------------------------------
640*cdf0e10cSrcweir 
641*cdf0e10cSrcweir String I18NStatus::getStatusText() const
642*cdf0e10cSrcweir {
643*cdf0e10cSrcweir     return m_pStatusWindow ? m_pStatusWindow->getText() :  String();
644*cdf0e10cSrcweir }
645*cdf0e10cSrcweir 
646*cdf0e10cSrcweir // --------------------------------------------------------------------------
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir void I18NStatus::clearChoices()
649*cdf0e10cSrcweir {
650*cdf0e10cSrcweir     m_aChoices.clear();
651*cdf0e10cSrcweir }
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir // --------------------------------------------------------------------------
654*cdf0e10cSrcweir 
655*cdf0e10cSrcweir void I18NStatus::addChoice( const String& rChoice, void* pData )
656*cdf0e10cSrcweir {
657*cdf0e10cSrcweir     ChoiceData aData;
658*cdf0e10cSrcweir     aData.pData		= pData;
659*cdf0e10cSrcweir     aData.aString	= rChoice;
660*cdf0e10cSrcweir     m_aChoices.push_back( aData );
661*cdf0e10cSrcweir }
662*cdf0e10cSrcweir 
663*cdf0e10cSrcweir // --------------------------------------------------------------------------
664*cdf0e10cSrcweir 
665*cdf0e10cSrcweir void I18NStatus::toTop() const
666*cdf0e10cSrcweir {
667*cdf0e10cSrcweir     if( m_pStatusWindow )
668*cdf0e10cSrcweir 	{
669*cdf0e10cSrcweir 		const SystemEnvData* pData = m_pStatusWindow->GetSystemData();
670*cdf0e10cSrcweir 		XRaiseWindow( (Display*)pData->pDisplay,
671*cdf0e10cSrcweir                       (XLIB_Window)pData->aShellWindow );
672*cdf0e10cSrcweir 	}
673*cdf0e10cSrcweir }
674*cdf0e10cSrcweir 
675*cdf0e10cSrcweir // --------------------------------------------------------------------------
676*cdf0e10cSrcweir 
677*cdf0e10cSrcweir SalFrame* I18NStatus::getStatusFrame() const
678*cdf0e10cSrcweir {
679*cdf0e10cSrcweir     SalFrame* pRet = NULL;
680*cdf0e10cSrcweir     if( m_pStatusWindow )
681*cdf0e10cSrcweir     {
682*cdf0e10cSrcweir 		const SystemEnvData* pData = m_pStatusWindow->GetSystemData();
683*cdf0e10cSrcweir         pRet = (SalFrame*)pData->pSalFrame;
684*cdf0e10cSrcweir     }
685*cdf0e10cSrcweir     return pRet;
686*cdf0e10cSrcweir }
687*cdf0e10cSrcweir 
688*cdf0e10cSrcweir bool I18NStatus::canToggleStatusWindow() const
689*cdf0e10cSrcweir {
690*cdf0e10cSrcweir     return true;
691*cdf0e10cSrcweir }
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir void I18NStatus::toggleStatusWindow()
694*cdf0e10cSrcweir {
695*cdf0e10cSrcweir     if (m_pStatusWindow != 0)
696*cdf0e10cSrcweir         m_pStatusWindow->toggle(getStatusWindowMode());
697*cdf0e10cSrcweir }
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir bool I18NStatus::getStatusWindowMode()
700*cdf0e10cSrcweir {
701*cdf0e10cSrcweir     switch (ImplGetSVData()->maAppData.meShowImeStatusWindow)
702*cdf0e10cSrcweir     {
703*cdf0e10cSrcweir     default: // ImplSVAppData::ImeStatusWindowMode_UNKNOWN
704*cdf0e10cSrcweir         return Application::GetShowImeStatusWindowDefault();
705*cdf0e10cSrcweir     case ImplSVAppData::ImeStatusWindowMode_HIDE:
706*cdf0e10cSrcweir         return false;
707*cdf0e10cSrcweir     case ImplSVAppData::ImeStatusWindowMode_SHOW:
708*cdf0e10cSrcweir         return true;
709*cdf0e10cSrcweir     }
710*cdf0e10cSrcweir }
711*cdf0e10cSrcweir 
712*cdf0e10cSrcweir /*
713*cdf0e10cSrcweir  * X11ImeStatus
714*cdf0e10cSrcweir  */
715*cdf0e10cSrcweir X11ImeStatus::~X11ImeStatus()
716*cdf0e10cSrcweir {
717*cdf0e10cSrcweir     vcl::I18NStatus::free();
718*cdf0e10cSrcweir }
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir bool X11ImeStatus::canToggle()
721*cdf0e10cSrcweir {
722*cdf0e10cSrcweir     return vcl::I18NStatus::get().canToggleStatusWindow();
723*cdf0e10cSrcweir }
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir void X11ImeStatus::toggle()
726*cdf0e10cSrcweir {
727*cdf0e10cSrcweir     vcl::I18NStatus::get().toggleStatusWindow();
728*cdf0e10cSrcweir }
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir SalI18NImeStatus* X11SalInstance::CreateI18NImeStatus()
731*cdf0e10cSrcweir {
732*cdf0e10cSrcweir     return new X11ImeStatus();
733*cdf0e10cSrcweir }
734