Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <cstdlib>
23 :
24 : #include <tools/debug.hxx>
25 :
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/menu.hxx>
28 : #include <vcl/event.hxx>
29 : #include <vcl/syswin.hxx>
30 : #include <vcl/taskpanelist.hxx>
31 : #include <vcl/unowrap.hxx>
32 :
33 : #include <rtl/strbuf.hxx>
34 :
35 : #include <salframe.hxx>
36 : #include <svdata.hxx>
37 : #include <brdwin.hxx>
38 : #include <window.h>
39 :
40 : using namespace ::com::sun::star::uno;
41 : using namespace ::com::sun::star::lang;
42 :
43 : class SystemWindow::ImplData
44 : {
45 : public:
46 : ImplData();
47 : ~ImplData();
48 :
49 : TaskPaneList* mpTaskPaneList;
50 : Size maMaxOutSize;
51 : OUString maRepresentedURL;
52 : Link maCloseHdl;
53 : };
54 :
55 0 : SystemWindow::ImplData::ImplData()
56 : {
57 0 : mpTaskPaneList = NULL;
58 0 : maMaxOutSize = Size( SHRT_MAX, SHRT_MAX );
59 0 : }
60 :
61 0 : SystemWindow::ImplData::~ImplData()
62 : {
63 0 : if( mpTaskPaneList )
64 0 : delete mpTaskPaneList;
65 0 : }
66 :
67 0 : SystemWindow::SystemWindow( WindowType nType ) :
68 0 : Window( nType )
69 : {
70 0 : mpImplData = new ImplData;
71 0 : mpWindowImpl->mbSysWin = true;
72 0 : mpWindowImpl->mnActivateMode = ACTIVATE_MODE_GRABFOCUS;
73 :
74 0 : mpMenuBar = NULL;
75 0 : mbPinned = false;
76 0 : mbRollUp = false;
77 0 : mbRollFunc = false;
78 0 : mbDockBtn = false;
79 0 : mbHideBtn = false;
80 0 : mbSysChild = false;
81 0 : mnMenuBarMode = MENUBAR_MODE_NORMAL;
82 0 : mnIcon = 0;
83 0 : }
84 :
85 0 : SystemWindow::~SystemWindow()
86 : {
87 0 : delete mpImplData;
88 0 : mpImplData = NULL;
89 0 : }
90 :
91 0 : bool SystemWindow::Notify( NotifyEvent& rNEvt )
92 : {
93 : // capture KeyEvents for menu handling
94 0 : if ( rNEvt.GetType() == EVENT_KEYINPUT )
95 : {
96 0 : MenuBar* pMBar = mpMenuBar;
97 0 : if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
98 : {
99 0 : Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
100 0 : if( pWin && pWin->IsSystemWindow() )
101 0 : pMBar = ((SystemWindow*)pWin)->GetMenuBar();
102 : }
103 0 : if ( pMBar && pMBar->ImplHandleKeyEvent( *rNEvt.GetKeyEvent(), false ) )
104 0 : return true;
105 : }
106 :
107 0 : return Window::Notify( rNEvt );
108 : }
109 :
110 0 : bool SystemWindow::PreNotify( NotifyEvent& rNEvt )
111 : {
112 : // capture KeyEvents for taskpane cycling
113 0 : if ( rNEvt.GetType() == EVENT_KEYINPUT )
114 : {
115 0 : if( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F6 &&
116 0 : rNEvt.GetKeyEvent()->GetKeyCode().IsMod1() &&
117 0 : !rNEvt.GetKeyEvent()->GetKeyCode().IsShift() )
118 : {
119 : // Ctrl-F6 goes directly to the document
120 0 : GrabFocusToDocument();
121 0 : return true;
122 : }
123 : else
124 : {
125 0 : TaskPaneList *pTList = mpImplData->mpTaskPaneList;
126 0 : if( !pTList && ( GetType() == WINDOW_FLOATINGWINDOW ) )
127 : {
128 0 : Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
129 0 : if( pWin && pWin->IsSystemWindow() )
130 0 : pTList = ((SystemWindow*)pWin)->mpImplData->mpTaskPaneList;
131 : }
132 0 : if( !pTList )
133 : {
134 : // search topmost system window which is the one to handle dialog/toolbar cycling
135 0 : SystemWindow *pSysWin = this;
136 0 : Window *pWin = this;
137 0 : while( pWin )
138 : {
139 0 : pWin = pWin->GetParent();
140 0 : if( pWin && pWin->IsSystemWindow() )
141 0 : pSysWin = (SystemWindow*) pWin;
142 : }
143 0 : pTList = pSysWin->mpImplData->mpTaskPaneList;
144 : }
145 0 : if( pTList && pTList->HandleKeyEvent( *rNEvt.GetKeyEvent() ) )
146 0 : return true;
147 : }
148 : }
149 0 : return Window::PreNotify( rNEvt );
150 : }
151 :
152 0 : TaskPaneList* SystemWindow::GetTaskPaneList()
153 : {
154 0 : if( mpImplData->mpTaskPaneList )
155 0 : return mpImplData->mpTaskPaneList ;
156 : else
157 : {
158 0 : mpImplData->mpTaskPaneList = new TaskPaneList();
159 0 : MenuBar* pMBar = mpMenuBar;
160 0 : if ( !pMBar && ( GetType() == WINDOW_FLOATINGWINDOW ) )
161 : {
162 0 : Window* pWin = ImplGetFrameWindow()->ImplGetWindow();
163 0 : if ( pWin && pWin->IsSystemWindow() )
164 0 : pMBar = ((SystemWindow*)pWin)->GetMenuBar();
165 : }
166 0 : if( pMBar )
167 0 : mpImplData->mpTaskPaneList->AddWindow( pMBar->ImplGetWindow() );
168 0 : return mpImplData->mpTaskPaneList;
169 : }
170 : }
171 :
172 0 : bool SystemWindow::Close()
173 : {
174 0 : ImplDelData aDelData;
175 0 : ImplAddDel( &aDelData );
176 0 : ImplCallEventListeners( VCLEVENT_WINDOW_CLOSE );
177 0 : if ( aDelData.IsDead() )
178 0 : return false;
179 0 : ImplRemoveDel( &aDelData );
180 :
181 0 : if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() )
182 0 : return false;
183 :
184 : // Is Window not closeable, ignore close
185 0 : Window* pBorderWin = ImplGetBorderWindow();
186 : WinBits nStyle;
187 0 : if ( pBorderWin )
188 0 : nStyle = pBorderWin->GetStyle();
189 : else
190 0 : nStyle = GetStyle();
191 0 : if ( !(nStyle & WB_CLOSEABLE) )
192 0 : return false;
193 :
194 0 : Hide();
195 :
196 0 : return true;
197 : }
198 :
199 0 : void SystemWindow::TitleButtonClick( sal_uInt16 )
200 : {
201 0 : }
202 :
203 0 : void SystemWindow::Pin()
204 : {
205 0 : }
206 :
207 0 : void SystemWindow::Roll()
208 : {
209 0 : }
210 :
211 0 : void SystemWindow::Resizing( Size& )
212 : {
213 0 : }
214 :
215 0 : void SystemWindow::SetRepresentedURL( const OUString& i_rURL )
216 : {
217 0 : bool bChanged = (i_rURL != mpImplData->maRepresentedURL);
218 0 : mpImplData->maRepresentedURL = i_rURL;
219 0 : if ( !mbSysChild && bChanged )
220 : {
221 0 : const Window* pWindow = this;
222 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
223 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
224 :
225 0 : if ( pWindow->mpWindowImpl->mbFrame )
226 0 : pWindow->mpWindowImpl->mpFrame->SetRepresentedURL( i_rURL );
227 : }
228 0 : }
229 :
230 0 : void SystemWindow::SetIcon( sal_uInt16 nIcon )
231 : {
232 0 : if ( mnIcon == nIcon )
233 0 : return;
234 :
235 0 : mnIcon = nIcon;
236 :
237 0 : if ( !mbSysChild )
238 : {
239 0 : const Window* pWindow = this;
240 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
241 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
242 :
243 0 : if ( pWindow->mpWindowImpl->mbFrame )
244 0 : pWindow->mpWindowImpl->mpFrame->SetIcon( nIcon );
245 : }
246 : }
247 :
248 0 : void SystemWindow::EnableSaveBackground( bool bSave )
249 : {
250 0 : if( ImplGetSVData()->maWinData.mbNoSaveBackground )
251 0 : bSave = false;
252 :
253 0 : Window* pWindow = this;
254 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
255 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
256 0 : if ( pWindow->mpWindowImpl->mbOverlapWin && !pWindow->mpWindowImpl->mbFrame )
257 : {
258 0 : pWindow->mpWindowImpl->mpOverlapData->mbSaveBack = bSave;
259 0 : if ( !bSave )
260 0 : pWindow->ImplDeleteOverlapBackground();
261 : }
262 0 : }
263 :
264 0 : bool SystemWindow::IsSaveBackgroundEnabled() const
265 : {
266 0 : const Window* pWindow = this;
267 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
268 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
269 0 : if ( pWindow->mpWindowImpl->mpOverlapData )
270 0 : return pWindow->mpWindowImpl->mpOverlapData->mbSaveBack;
271 : else
272 0 : return false;
273 : }
274 :
275 0 : void SystemWindow::ShowTitleButton( sal_uInt16 nButton, bool bVisible )
276 : {
277 0 : if ( nButton == TITLE_BUTTON_DOCKING )
278 : {
279 0 : if ( mbDockBtn != bVisible )
280 : {
281 0 : mbDockBtn = bVisible;
282 0 : if ( mpWindowImpl->mpBorderWindow )
283 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetDockButton( bVisible );
284 : }
285 : }
286 0 : else if ( nButton == TITLE_BUTTON_HIDE )
287 : {
288 0 : if ( mbHideBtn != bVisible )
289 : {
290 0 : mbHideBtn = bVisible;
291 0 : if ( mpWindowImpl->mpBorderWindow )
292 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetHideButton( bVisible );
293 : }
294 : }
295 0 : else if ( nButton == TITLE_BUTTON_MENU )
296 : {
297 0 : if ( mpWindowImpl->mpBorderWindow )
298 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuButton( bVisible );
299 : }
300 : else
301 0 : return;
302 : }
303 :
304 0 : bool SystemWindow::IsTitleButtonVisible( sal_uInt16 nButton ) const
305 : {
306 0 : if ( nButton == TITLE_BUTTON_DOCKING )
307 0 : return mbDockBtn;
308 : else /* if ( nButton == TITLE_BUTTON_HIDE ) */
309 0 : return mbHideBtn;
310 : }
311 :
312 0 : void SystemWindow::SetPin( bool bPin )
313 : {
314 0 : if ( bPin != mbPinned )
315 : {
316 0 : mbPinned = bPin;
317 0 : if ( mpWindowImpl->mpBorderWindow )
318 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetPin( bPin );
319 : }
320 0 : }
321 :
322 0 : void SystemWindow::RollUp()
323 : {
324 0 : if ( !mbRollUp )
325 : {
326 0 : maOrgSize = GetOutputSizePixel();
327 0 : mbRollFunc = true;
328 0 : Size aSize = maRollUpOutSize;
329 0 : if ( !aSize.Width() )
330 0 : aSize.Width() = GetOutputSizePixel().Width();
331 0 : mbRollUp = true;
332 0 : if ( mpWindowImpl->mpBorderWindow )
333 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetRollUp( true, aSize );
334 : else
335 0 : SetOutputSizePixel( aSize );
336 0 : mbRollFunc = false;
337 : }
338 0 : }
339 :
340 0 : void SystemWindow::RollDown()
341 : {
342 0 : if ( mbRollUp )
343 : {
344 0 : mbRollUp = false;
345 0 : if ( mpWindowImpl->mpBorderWindow )
346 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetRollUp( false, maOrgSize );
347 : else
348 0 : SetOutputSizePixel( maOrgSize );
349 : }
350 0 : }
351 :
352 0 : void SystemWindow::SetMinOutputSizePixel( const Size& rSize )
353 : {
354 0 : maMinOutSize = rSize;
355 0 : if ( mpWindowImpl->mpBorderWindow )
356 : {
357 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMinOutputSize( rSize.Width(), rSize.Height() );
358 0 : if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
359 0 : mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
360 : }
361 0 : else if ( mpWindowImpl->mbFrame )
362 0 : mpWindowImpl->mpFrame->SetMinClientSize( rSize.Width(), rSize.Height() );
363 0 : }
364 :
365 0 : void SystemWindow::SetMaxOutputSizePixel( const Size& rSize )
366 : {
367 0 : Size aSize( rSize );
368 0 : if( aSize.Width() > SHRT_MAX || aSize.Width() <= 0 )
369 0 : aSize.Width() = SHRT_MAX;
370 0 : if( aSize.Height() > SHRT_MAX || aSize.Height() <= 0 )
371 0 : aSize.Height() = SHRT_MAX;
372 :
373 0 : mpImplData->maMaxOutSize = aSize;
374 0 : if ( mpWindowImpl->mpBorderWindow )
375 : {
376 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMaxOutputSize( aSize.Width(), aSize.Height() );
377 0 : if ( mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame )
378 0 : mpWindowImpl->mpBorderWindow->mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
379 : }
380 0 : else if ( mpWindowImpl->mbFrame )
381 0 : mpWindowImpl->mpFrame->SetMaxClientSize( aSize.Width(), aSize.Height() );
382 0 : }
383 :
384 0 : const Size& SystemWindow::GetMaxOutputSizePixel() const
385 : {
386 0 : return mpImplData->maMaxOutSize;
387 : }
388 :
389 0 : Size SystemWindow::GetResizeOutputSizePixel() const
390 : {
391 0 : Size aSize = GetOutputSizePixel();
392 0 : if ( aSize.Width() < maMinOutSize.Width() )
393 0 : aSize.Width() = maMinOutSize.Width();
394 0 : if ( aSize.Height() < maMinOutSize.Height() )
395 0 : aSize.Height() = maMinOutSize.Height();
396 0 : return aSize;
397 : }
398 :
399 0 : static void ImplWindowStateFromStr(WindowStateData& rData,
400 : const OString& rStr)
401 : {
402 0 : sal_uLong nValidMask = 0;
403 0 : sal_Int32 nIndex = 0;
404 0 : OString aTokenStr;
405 :
406 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
407 0 : if (!aTokenStr.isEmpty())
408 : {
409 0 : rData.SetX(aTokenStr.toInt32());
410 0 : if( rData.GetX() > -16384 && rData.GetX() < 16384 )
411 0 : nValidMask |= WINDOWSTATE_MASK_X;
412 : else
413 0 : rData.SetX( 0 );
414 : }
415 : else
416 0 : rData.SetX( 0 );
417 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
418 0 : if (!aTokenStr.isEmpty())
419 : {
420 0 : rData.SetY(aTokenStr.toInt32());
421 0 : if( rData.GetY() > -16384 && rData.GetY() < 16384 )
422 0 : nValidMask |= WINDOWSTATE_MASK_Y;
423 : else
424 0 : rData.SetY( 0 );
425 : }
426 : else
427 0 : rData.SetY( 0 );
428 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
429 0 : if (!aTokenStr.isEmpty())
430 : {
431 0 : rData.SetWidth(aTokenStr.toInt32());
432 0 : if( rData.GetWidth() > 0 && rData.GetWidth() < 16384 )
433 0 : nValidMask |= WINDOWSTATE_MASK_WIDTH;
434 : else
435 0 : rData.SetWidth( 0 );
436 : }
437 : else
438 0 : rData.SetWidth( 0 );
439 0 : aTokenStr = rStr.getToken(0, ';', nIndex);
440 0 : if (!aTokenStr.isEmpty())
441 : {
442 0 : rData.SetHeight(aTokenStr.toInt32());
443 0 : if( rData.GetHeight() > 0 && rData.GetHeight() < 16384 )
444 0 : nValidMask |= WINDOWSTATE_MASK_HEIGHT;
445 : else
446 0 : rData.SetHeight( 0 );
447 : }
448 : else
449 0 : rData.SetHeight( 0 );
450 0 : aTokenStr = rStr.getToken(0, ';', nIndex);
451 0 : if (!aTokenStr.isEmpty())
452 : {
453 : // #94144# allow Minimize again, should be masked out when read from configuration
454 : // 91625 - ignore Minimize
455 0 : sal_uInt32 nState = (sal_uInt32)aTokenStr.toInt32();
456 : //nState &= ~(WINDOWSTATE_STATE_MINIMIZED);
457 0 : rData.SetState( nState );
458 0 : nValidMask |= WINDOWSTATE_MASK_STATE;
459 : }
460 : else
461 0 : rData.SetState( 0 );
462 :
463 : // read maximized pos/size
464 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
465 0 : if (!aTokenStr.isEmpty())
466 : {
467 0 : rData.SetMaximizedX(aTokenStr.toInt32());
468 0 : if( rData.GetMaximizedX() > -16384 && rData.GetMaximizedX() < 16384 )
469 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_X;
470 : else
471 0 : rData.SetMaximizedX( 0 );
472 : }
473 : else
474 0 : rData.SetMaximizedX( 0 );
475 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
476 0 : if (!aTokenStr.isEmpty())
477 : {
478 0 : rData.SetMaximizedY(aTokenStr.toInt32());
479 0 : if( rData.GetMaximizedY() > -16384 && rData.GetMaximizedY() < 16384 )
480 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_Y;
481 : else
482 0 : rData.SetMaximizedY( 0 );
483 : }
484 : else
485 0 : rData.SetMaximizedY( 0 );
486 0 : aTokenStr = rStr.getToken(0, ',', nIndex);
487 0 : if (!aTokenStr.isEmpty())
488 : {
489 0 : rData.SetMaximizedWidth(aTokenStr.toInt32());
490 0 : if( rData.GetMaximizedWidth() > 0 && rData.GetMaximizedWidth() < 16384 )
491 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_WIDTH;
492 : else
493 0 : rData.SetMaximizedWidth( 0 );
494 : }
495 : else
496 0 : rData.SetMaximizedWidth( 0 );
497 0 : aTokenStr = rStr.getToken(0, ';', nIndex);
498 0 : if (!aTokenStr.isEmpty())
499 : {
500 0 : rData.SetMaximizedHeight(aTokenStr.toInt32());
501 0 : if( rData.GetMaximizedHeight() > 0 && rData.GetMaximizedHeight() < 16384 )
502 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
503 : else
504 0 : rData.SetMaximizedHeight( 0 );
505 : }
506 : else
507 0 : rData.SetMaximizedHeight( 0 );
508 :
509 : // mark valid fields
510 0 : rData.SetMask( nValidMask );
511 0 : }
512 :
513 0 : static OString ImplWindowStateToStr(const WindowStateData& rData)
514 : {
515 0 : sal_uLong nValidMask = rData.GetMask();
516 0 : if ( !nValidMask )
517 0 : return OString();
518 :
519 0 : OStringBuffer rStrBuf;
520 :
521 0 : if ( nValidMask & WINDOWSTATE_MASK_X )
522 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetX()));
523 0 : rStrBuf.append(',');
524 0 : if ( nValidMask & WINDOWSTATE_MASK_Y )
525 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetY()));
526 0 : rStrBuf.append(',');
527 0 : if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
528 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetWidth()));
529 0 : rStrBuf.append(',');
530 0 : if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
531 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetHeight()));
532 0 : rStrBuf.append( ';' );
533 0 : if ( nValidMask & WINDOWSTATE_MASK_STATE )
534 : {
535 : // #94144# allow Minimize again, should be masked out when read from configuration
536 : // 91625 - ignore Minimize
537 0 : sal_uInt32 nState = rData.GetState();
538 0 : rStrBuf.append(static_cast<sal_Int32>(nState));
539 : }
540 0 : rStrBuf.append(';');
541 0 : if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_X )
542 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedX()));
543 0 : rStrBuf.append(',');
544 0 : if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_Y )
545 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedY()));
546 0 : rStrBuf.append( ',' );
547 0 : if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_WIDTH )
548 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedWidth()));
549 0 : rStrBuf.append(',');
550 0 : if ( nValidMask & WINDOWSTATE_MASK_MAXIMIZED_HEIGHT )
551 0 : rStrBuf.append(static_cast<sal_Int32>(rData.GetMaximizedHeight()));
552 0 : rStrBuf.append(';');
553 :
554 0 : return rStrBuf.makeStringAndClear();
555 : }
556 :
557 0 : void SystemWindow::ImplMoveToScreen( long& io_rX, long& io_rY, long i_nWidth, long i_nHeight, Window* i_pConfigureWin )
558 : {
559 0 : Rectangle aScreenRect;
560 0 : if( !Application::IsUnifiedDisplay() )
561 0 : aScreenRect = Application::GetScreenPosSizePixel( GetScreenNumber() );
562 : else
563 : {
564 0 : aScreenRect = Application::GetScreenPosSizePixel( 0 );
565 0 : for( unsigned int i = 1; i < Application::GetScreenCount(); i++ )
566 0 : aScreenRect.Union( Application::GetScreenPosSizePixel( i ) );
567 : }
568 : // unfortunately most of the time width and height are not really known
569 0 : if( i_nWidth < 1 )
570 0 : i_nWidth = 50;
571 0 : if( i_nHeight < 1 )
572 0 : i_nHeight = 50;
573 :
574 : // check left border
575 0 : bool bMove = false;
576 0 : if( io_rX + i_nWidth < aScreenRect.Left() )
577 : {
578 0 : bMove = true;
579 0 : io_rX = aScreenRect.Left();
580 : }
581 : // check right border
582 0 : if( io_rX > aScreenRect.Right() - i_nWidth )
583 : {
584 0 : bMove = true;
585 0 : io_rX = aScreenRect.Right() - i_nWidth;
586 : }
587 : // check top border
588 0 : if( io_rY + i_nHeight < aScreenRect.Top() )
589 : {
590 0 : bMove = true;
591 0 : io_rY = aScreenRect.Top();
592 : }
593 : // check bottom border
594 0 : if( io_rY > aScreenRect.Bottom() - i_nHeight )
595 : {
596 0 : bMove = true;
597 0 : io_rY = aScreenRect.Bottom() - i_nHeight;
598 : }
599 0 : Window* pParent = i_pConfigureWin->GetParent();
600 0 : if( bMove && pParent )
601 : {
602 : // calculate absolute screen pos here, since that is what is contained in WindowState
603 0 : Point aParentAbsPos( pParent->OutputToAbsoluteScreenPixel( Point(0,0) ) );
604 0 : Size aParentSizePixel( pParent->GetOutputSizePixel() );
605 0 : Point aPos( (aParentSizePixel.Width() - i_nWidth) / 2,
606 0 : (aParentSizePixel.Height() - i_nHeight) / 2 );
607 0 : io_rX = aParentAbsPos.X() + aPos.X();
608 0 : io_rY = aParentAbsPos.Y() + aPos.Y();
609 : }
610 0 : }
611 :
612 0 : void SystemWindow::SetWindowStateData( const WindowStateData& rData )
613 : {
614 0 : sal_uLong nValidMask = rData.GetMask();
615 0 : if ( !nValidMask )
616 0 : return;
617 :
618 0 : if ( mbSysChild )
619 0 : return;
620 :
621 0 : Window* pWindow = this;
622 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
623 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
624 :
625 0 : if ( pWindow->mpWindowImpl->mbFrame )
626 : {
627 0 : sal_uLong nState = rData.GetState();
628 : SalFrameState aState;
629 0 : aState.mnMask = rData.GetMask();
630 0 : aState.mnX = rData.GetX();
631 0 : aState.mnY = rData.GetY();
632 0 : aState.mnWidth = rData.GetWidth();
633 0 : aState.mnHeight = rData.GetHeight();
634 :
635 0 : if( rData.GetMask() & (WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
636 : {
637 : // #i43799# adjust window state sizes if a minimial output size was set
638 : // otherwise the frame and the client might get different sizes
639 0 : if( maMinOutSize.Width() > aState.mnWidth )
640 0 : aState.mnWidth = maMinOutSize.Width();
641 0 : if( maMinOutSize.Height() > aState.mnHeight )
642 0 : aState.mnHeight = maMinOutSize.Height();
643 : }
644 :
645 0 : aState.mnMaximizedX = rData.GetMaximizedX();
646 0 : aState.mnMaximizedY = rData.GetMaximizedY();
647 0 : aState.mnMaximizedWidth = rData.GetMaximizedWidth();
648 0 : aState.mnMaximizedHeight = rData.GetMaximizedHeight();
649 : // #94144# allow Minimize again, should be masked out when read from configuration
650 : // 91625 - ignore Minimize
651 : //nState &= ~(WINDOWSTATE_STATE_MINIMIZED);
652 0 : aState.mnState = nState & WINDOWSTATE_STATE_SYSTEMMASK;
653 :
654 : // normalize window positions onto screen
655 0 : ImplMoveToScreen( aState.mnX, aState.mnY, aState.mnWidth, aState.mnHeight, pWindow );
656 0 : ImplMoveToScreen( aState.mnMaximizedX, aState.mnMaximizedY, aState.mnMaximizedWidth, aState.mnMaximizedHeight, pWindow );
657 :
658 : // #96568# avoid having multiple frames at the same screen location
659 : // do the check only if not maximized
660 0 : if( !((rData.GetMask() & WINDOWSTATE_MASK_STATE) && (nState & WINDOWSTATE_STATE_MAXIMIZED)) )
661 0 : if( rData.GetMask() & (WINDOWSTATE_MASK_POS|WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
662 : {
663 0 : Rectangle aDesktop = GetDesktopRectPixel();
664 0 : ImplSVData *pSVData = ImplGetSVData();
665 0 : Window *pWin = pSVData->maWinData.mpFirstFrame;
666 0 : bool bWrapped = false;
667 0 : while( pWin )
668 : {
669 0 : if( !pWin->ImplIsRealParentPath( this ) && ( pWin != this ) &&
670 0 : pWin->ImplGetWindow()->IsTopWindow() && pWin->mpWindowImpl->mbReallyVisible )
671 : {
672 0 : SalFrameGeometry g = pWin->mpWindowImpl->mpFrame->GetGeometry();
673 0 : if( std::abs(g.nX-aState.mnX) < 2 && std::abs(g.nY-aState.mnY) < 5 )
674 : {
675 0 : long displacement = g.nTopDecoration ? g.nTopDecoration : 20;
676 0 : if( (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.Right() ||
677 0 : (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.Bottom() )
678 : {
679 : // displacing would leave screen
680 0 : aState.mnX = g.nLeftDecoration ? g.nLeftDecoration : 10; // should result in (0,0)
681 0 : aState.mnY = displacement;
682 0 : if( bWrapped ||
683 0 : (unsigned long) (aState.mnX + displacement + aState.mnWidth + g.nRightDecoration) > (unsigned long) aDesktop.Right() ||
684 0 : (unsigned long) (aState.mnY + displacement + aState.mnHeight + g.nBottomDecoration) > (unsigned long) aDesktop.Bottom() )
685 0 : break; // further displacement not possible -> break
686 : // avoid endless testing
687 0 : bWrapped = true;
688 : }
689 : else
690 : {
691 : // displace
692 0 : aState.mnX += displacement;
693 0 : aState.mnY += displacement;
694 : }
695 0 : pWin = pSVData->maWinData.mpFirstFrame; // check new pos again
696 : }
697 : }
698 0 : pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
699 : }
700 : }
701 :
702 0 : mpWindowImpl->mpFrame->SetWindowState( &aState );
703 :
704 : // do a synchronous resize for layout reasons
705 : // but use rData only when the window is not to be maximized (#i38089#)
706 : // otherwise we have no useful size information
707 0 : if( (rData.GetMask() & WINDOWSTATE_MASK_STATE) && (nState & WINDOWSTATE_STATE_MAXIMIZED) )
708 : {
709 : // query maximized size from frame
710 0 : SalFrameGeometry aGeometry = mpWindowImpl->mpFrame->GetGeometry();
711 :
712 : // but use it only if it is different from the restore size (rData)
713 : // as currently only on windows the exact size of a maximized window
714 : // can be computed without actually showing the window
715 0 : if( aGeometry.nWidth != rData.GetWidth() || aGeometry.nHeight != rData.GetHeight() )
716 0 : ImplHandleResize( pWindow, aGeometry.nWidth, aGeometry.nHeight );
717 : }
718 : else
719 0 : if( rData.GetMask() & (WINDOWSTATE_MASK_WIDTH|WINDOWSTATE_MASK_HEIGHT) )
720 0 : ImplHandleResize( pWindow, aState.mnWidth, aState.mnHeight ); // #i43799# use aState and not rData, see above
721 : }
722 : else
723 : {
724 0 : sal_uInt16 nPosSize = 0;
725 0 : if ( nValidMask & WINDOWSTATE_MASK_X )
726 0 : nPosSize |= WINDOW_POSSIZE_X;
727 0 : if ( nValidMask & WINDOWSTATE_MASK_Y )
728 0 : nPosSize |= WINDOW_POSSIZE_Y;
729 0 : if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
730 0 : nPosSize |= WINDOW_POSSIZE_WIDTH;
731 0 : if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
732 0 : nPosSize |= WINDOW_POSSIZE_HEIGHT;
733 :
734 0 : if( IsRollUp() )
735 0 : RollDown();
736 :
737 0 : long nX = rData.GetX();
738 0 : long nY = rData.GetY();
739 0 : long nWidth = rData.GetWidth();
740 0 : long nHeight = rData.GetHeight();
741 0 : const SalFrameGeometry& rGeom = pWindow->mpWindowImpl->mpFrame->GetGeometry();
742 0 : if( nX < 0 )
743 0 : nX = 0;
744 0 : if( nX + nWidth > (long) rGeom.nWidth )
745 0 : nX = rGeom.nWidth - nWidth;
746 0 : if( nY < 0 )
747 0 : nY = 0;
748 0 : if( nY + nHeight > (long) rGeom.nHeight )
749 0 : nY = rGeom.nHeight - nHeight;
750 0 : setPosSizePixel( nX, nY, nWidth, nHeight, nPosSize );
751 0 : maOrgSize = Size( nWidth, nHeight );
752 :
753 : // 91625 - ignore Minimize
754 0 : if ( nValidMask & WINDOWSTATE_MASK_STATE )
755 : {
756 0 : sal_uLong nState = rData.GetState();
757 0 : if ( nState & WINDOWSTATE_STATE_ROLLUP )
758 0 : RollUp();
759 : else
760 0 : RollDown();
761 : }
762 : }
763 : }
764 :
765 0 : void SystemWindow::GetWindowStateData( WindowStateData& rData ) const
766 : {
767 0 : sal_uLong nValidMask = rData.GetMask();
768 0 : if ( !nValidMask )
769 0 : return;
770 :
771 0 : if ( mbSysChild )
772 0 : return;
773 :
774 0 : const Window* pWindow = this;
775 0 : while ( pWindow->mpWindowImpl->mpBorderWindow )
776 0 : pWindow = pWindow->mpWindowImpl->mpBorderWindow;
777 :
778 0 : if ( pWindow->mpWindowImpl->mbFrame )
779 : {
780 : SalFrameState aState;
781 0 : aState.mnMask = 0xFFFFFFFF;
782 0 : if ( mpWindowImpl->mpFrame->GetWindowState( &aState ) )
783 : {
784 0 : if ( nValidMask & WINDOWSTATE_MASK_X )
785 0 : rData.SetX( aState.mnX );
786 0 : if ( nValidMask & WINDOWSTATE_MASK_Y )
787 0 : rData.SetY( aState.mnY );
788 0 : if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
789 0 : rData.SetWidth( aState.mnWidth );
790 0 : if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
791 0 : rData.SetHeight( aState.mnHeight );
792 0 : if ( aState.mnMask & WINDOWSTATE_MASK_MAXIMIZED_X )
793 : {
794 0 : rData.SetMaximizedX( aState.mnMaximizedX );
795 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_X;
796 : }
797 0 : if ( aState.mnMask & WINDOWSTATE_MASK_MAXIMIZED_Y )
798 : {
799 0 : rData.SetMaximizedY( aState.mnMaximizedY );
800 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_Y;
801 : }
802 0 : if ( aState.mnMask & WINDOWSTATE_MASK_MAXIMIZED_WIDTH )
803 : {
804 0 : rData.SetMaximizedWidth( aState.mnMaximizedWidth );
805 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_WIDTH;
806 : }
807 0 : if ( aState.mnMask & WINDOWSTATE_MASK_MAXIMIZED_HEIGHT )
808 : {
809 0 : rData.SetMaximizedHeight( aState.mnMaximizedHeight );
810 0 : nValidMask |= WINDOWSTATE_MASK_MAXIMIZED_HEIGHT;
811 : }
812 0 : if ( nValidMask & WINDOWSTATE_MASK_STATE )
813 : {
814 : // #94144# allow Minimize again, should be masked out when read from configuration
815 : // 91625 - ignore Minimize
816 0 : if ( !(nValidMask&WINDOWSTATE_MASK_MINIMIZED) )
817 0 : aState.mnState &= ~(WINDOWSTATE_STATE_MINIMIZED);
818 0 : rData.SetState( aState.mnState );
819 : }
820 0 : rData.SetMask( nValidMask );
821 : }
822 : else
823 0 : rData.SetMask( 0 );
824 : }
825 : else
826 : {
827 0 : Point aPos = GetPosPixel();
828 0 : Size aSize = GetSizePixel();
829 0 : sal_uLong nState = 0;
830 :
831 0 : if ( IsRollUp() )
832 : {
833 0 : aSize.Height() += maOrgSize.Height();
834 0 : nState |= WINDOWSTATE_STATE_ROLLUP;
835 : }
836 :
837 0 : if ( nValidMask & WINDOWSTATE_MASK_X )
838 0 : rData.SetX( aPos.X() );
839 0 : if ( nValidMask & WINDOWSTATE_MASK_Y )
840 0 : rData.SetY( aPos.Y() );
841 0 : if ( nValidMask & WINDOWSTATE_MASK_WIDTH )
842 0 : rData.SetWidth( aSize.Width() );
843 0 : if ( nValidMask & WINDOWSTATE_MASK_HEIGHT )
844 0 : rData.SetHeight( aSize.Height() );
845 0 : if ( nValidMask & WINDOWSTATE_MASK_STATE )
846 0 : rData.SetState( nState );
847 : }
848 : }
849 :
850 0 : void SystemWindow::SetWindowState(const OString& rStr)
851 : {
852 0 : if (rStr.isEmpty())
853 0 : return;
854 :
855 0 : WindowStateData aData;
856 0 : ImplWindowStateFromStr( aData, rStr );
857 0 : SetWindowStateData( aData );
858 : }
859 :
860 0 : OString SystemWindow::GetWindowState( sal_uLong nMask ) const
861 : {
862 0 : WindowStateData aData;
863 0 : aData.SetMask( nMask );
864 0 : GetWindowStateData( aData );
865 :
866 0 : return ImplWindowStateToStr(aData);
867 : }
868 :
869 0 : void SystemWindow::SetMenuBar( MenuBar* pMenuBar )
870 : {
871 0 : if ( mpMenuBar != pMenuBar )
872 : {
873 0 : MenuBar* pOldMenuBar = mpMenuBar;
874 0 : Window* pOldWindow = NULL;
875 0 : Window* pNewWindow=NULL;
876 0 : mpMenuBar = pMenuBar;
877 :
878 0 : if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
879 : {
880 0 : if ( pOldMenuBar )
881 0 : pOldWindow = pOldMenuBar->ImplGetWindow();
882 : else
883 0 : pOldWindow = NULL;
884 0 : if ( pOldWindow )
885 : {
886 0 : ImplCallEventListeners( VCLEVENT_WINDOW_MENUBARREMOVED, (void*) pOldMenuBar );
887 0 : pOldWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
888 : }
889 0 : if ( pMenuBar )
890 : {
891 : DBG_ASSERT( !pMenuBar->pWindow, "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
892 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow( pNewWindow = MenuBar::ImplCreate( mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar ) );
893 0 : ImplCallEventListeners( VCLEVENT_WINDOW_MENUBARADDED, (void*) pMenuBar );
894 : }
895 : else
896 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow( NULL );
897 0 : ImplToBottomChild();
898 0 : if ( pOldMenuBar )
899 : {
900 0 : bool bDelete = (pMenuBar == 0) ? true : false;
901 0 : if( bDelete && pOldWindow )
902 : {
903 0 : if( mpImplData->mpTaskPaneList )
904 0 : mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
905 : }
906 0 : MenuBar::ImplDestroy( pOldMenuBar, bDelete );
907 0 : if( bDelete )
908 0 : pOldWindow = NULL; // will be deleted in MenuBar::ImplDestroy,
909 : }
910 :
911 : }
912 : else
913 : {
914 0 : if( pMenuBar )
915 0 : pNewWindow = pMenuBar->ImplGetWindow();
916 0 : if( pOldMenuBar )
917 0 : pOldWindow = pOldMenuBar->ImplGetWindow();
918 : }
919 :
920 : // update taskpane list to make menubar accessible
921 0 : if( mpImplData->mpTaskPaneList )
922 : {
923 0 : if( pOldWindow )
924 0 : mpImplData->mpTaskPaneList->RemoveWindow( pOldWindow );
925 0 : if( pNewWindow )
926 0 : mpImplData->mpTaskPaneList->AddWindow( pNewWindow );
927 : }
928 : }
929 0 : }
930 :
931 0 : void SystemWindow::SetMenuBarMode( sal_uInt16 nMode )
932 : {
933 0 : if ( mnMenuBarMode != nMode )
934 : {
935 0 : mnMenuBarMode = nMode;
936 0 : if ( mpWindowImpl->mpBorderWindow && (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) )
937 : {
938 0 : if ( nMode == MENUBAR_MODE_HIDE )
939 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarMode( true );
940 : else
941 0 : ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarMode( false );
942 : }
943 : }
944 0 : }
945 :
946 0 : bool SystemWindow::ImplIsInTaskPaneList( Window* pWin )
947 : {
948 0 : if( mpImplData && mpImplData->mpTaskPaneList )
949 0 : return mpImplData->mpTaskPaneList->IsInList( pWin );
950 0 : return false;
951 : }
952 :
953 0 : unsigned int SystemWindow::GetScreenNumber() const
954 : {
955 0 : return mpWindowImpl->mpFrame->maGeometry.nDisplayScreenNumber;
956 : }
957 :
958 0 : void SystemWindow::SetScreenNumber(unsigned int nDisplayScreen)
959 : {
960 0 : mpWindowImpl->mpFrame->SetScreenNumber( nDisplayScreen );
961 0 : }
962 :
963 0 : void SystemWindow::SetApplicationID(const OUString &rApplicationID)
964 : {
965 0 : mpWindowImpl->mpFrame->SetApplicationID( rApplicationID );
966 0 : }
967 :
968 0 : void SystemWindow::SetCloseHdl(const Link& rLink)
969 : {
970 0 : mpImplData->maCloseHdl = rLink;
971 0 : }
972 :
973 0 : const Link& SystemWindow::GetCloseHdl() const
974 : {
975 0 : return mpImplData->maCloseHdl;
976 : }
977 :
978 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|