1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salinfo.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 // rely on unicows on for multimon functions for older versions
40 #define VCL_NEED_BASETSD
41 #include "tools/presys.h"
43 #pragma warning(push, 1)
50 #include "tools/postsys.h"
52 #include "tools/string.hxx"
56 #include "saldata.hxx"
57 #include "tools/debug.hxx"
58 #include "vcl/svdata.hxx"
59 #include "vcl/window.hxx"
61 #include "rtl/ustrbuf.hxx"
65 SalSystem
* WinSalInstance::CreateSalSystem()
67 return new WinSalSystem();
70 WinSalSystem::~WinSalSystem()
74 // -----------------------------------------------------------------------
76 static WIN_BOOL CALLBACK
ImplEnumMonitorProc( HMONITOR hMonitor
,
81 WinSalSystem
* pSys
= reinterpret_cast<WinSalSystem
*>(dwData
);
82 return pSys
->handleMonitorCallback( reinterpret_cast<sal_IntPtr
>(hMonitor
),
83 reinterpret_cast<sal_IntPtr
>(hDC
),
84 reinterpret_cast<sal_IntPtr
>(lpRect
) );
87 BOOL
WinSalSystem::handleMonitorCallback( sal_IntPtr hMonitor
, sal_IntPtr
, sal_IntPtr
)
90 aInfo
.cbSize
= sizeof( aInfo
);
91 if( GetMonitorInfoW( reinterpret_cast<HMONITOR
>(hMonitor
), &aInfo
) )
93 aInfo
.szDevice
[CCHDEVICENAME
-1] = 0;
94 rtl::OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aInfo
.szDevice
) );
95 std::map
< rtl::OUString
, unsigned int >::const_iterator it
=
96 m_aDeviceNameToMonitor
.find( aDeviceName
);
97 if( it
!= m_aDeviceNameToMonitor
.end() )
99 DisplayMonitor
& rMon( m_aMonitors
[ it
->second
] );
100 rMon
.m_aArea
= Rectangle( Point( aInfo
.rcMonitor
.left
,
101 aInfo
.rcMonitor
.top
),
102 Size( aInfo
.rcMonitor
.right
- aInfo
.rcMonitor
.left
,
103 aInfo
.rcMonitor
.bottom
- aInfo
.rcMonitor
.top
) );
104 rMon
.m_aWorkArea
= Rectangle( Point( aInfo
.rcWork
.left
,
106 Size( aInfo
.rcWork
.right
- aInfo
.rcWork
.left
,
107 aInfo
.rcWork
.bottom
- aInfo
.rcWork
.top
) );
108 if( (aInfo
.dwFlags
& MONITORINFOF_PRIMARY
) != 0 )
109 m_nPrimary
= it
->second
;
115 void WinSalSystem::clearMonitors()
121 bool WinSalSystem::initMonitors()
123 if( m_aMonitors
.size() > 0 )
126 bool winVerOk
= true;
128 // multi monitor calls not available on Win95/NT
129 if ( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
131 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
<= 4 )
132 winVerOk
= false; // NT
134 else if( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
136 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
== 4 && aSalShlData
.maVersionInfo
.dwMinorVersion
== 0 )
137 winVerOk
= false; // Win95
141 int nMonitors
= GetSystemMetrics( SM_CMONITORS
);
144 int w
= GetSystemMetrics( SM_CXSCREEN
);
145 int h
= GetSystemMetrics( SM_CYSCREEN
);
146 m_aMonitors
.push_back( DisplayMonitor( rtl::OUString(),
148 Rectangle( Point(), Size( w
, h
) ),
149 Rectangle( Point(), Size( w
, h
) ),
151 m_aDeviceNameToMonitor
[ rtl::OUString() ] = 0;
154 if( SystemParametersInfo( SPI_GETWORKAREA
, 0, &aWorkRect
, 0 ) )
155 m_aMonitors
.back().m_aWorkArea
= Rectangle( aWorkRect
.left
, aWorkRect
.top
,
156 aWorkRect
.right
, aWorkRect
.bottom
);
160 DISPLAY_DEVICEW aDev
;
161 aDev
.cb
= sizeof( aDev
);
163 std::hash_map
< rtl::OUString
, int, rtl::OUStringHash
> aDeviceStringCount
;
164 while( EnumDisplayDevicesW( NULL
, nDevice
++, &aDev
, 0 ) )
166 if( (aDev
.StateFlags
& DISPLAY_DEVICE_MIRRORING_DRIVER
) == 0 ) // sort out non monitors
168 aDev
.DeviceName
[31] = 0;
169 aDev
.DeviceString
[127] = 0;
170 rtl::OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceName
) );
171 rtl::OUString
aDeviceString( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceString
) );
172 if( aDeviceStringCount
.find( aDeviceString
) == aDeviceStringCount
.end() )
173 aDeviceStringCount
[ aDeviceString
] = 1;
175 aDeviceStringCount
[ aDeviceString
]++;
176 m_aDeviceNameToMonitor
[ aDeviceName
] = m_aMonitors
.size();
177 m_aMonitors
.push_back( DisplayMonitor( aDeviceString
,
184 HDC aDesktopRC
= GetDC( NULL
);
185 EnumDisplayMonitors( aDesktopRC
, NULL
, ImplEnumMonitorProc
, reinterpret_cast<LPARAM
>(this) );
187 // append monitor numbers to name strings
188 std::hash_map
< rtl::OUString
, int, rtl::OUStringHash
> aDevCount( aDeviceStringCount
);
189 unsigned int nMonitors
= m_aMonitors
.size();
190 for( unsigned int i
= 0; i
< nMonitors
; i
++ )
192 const rtl::OUString
& rDev( m_aMonitors
[i
].m_aName
);
193 if( aDeviceStringCount
[ rDev
] > 1 )
195 int nInstance
= aDeviceStringCount
[ rDev
] - (-- aDevCount
[ rDev
] );
196 rtl::OUStringBuffer
aBuf( rDev
.getLength() + 8 );
198 aBuf
.appendAscii( " (" );
199 aBuf
.append( sal_Int32( nInstance
) );
200 aBuf
.append( sal_Unicode(')') );
201 m_aMonitors
[ i
].m_aName
= aBuf
.makeStringAndClear();
208 int w
= GetSystemMetrics( SM_CXSCREEN
);
209 int h
= GetSystemMetrics( SM_CYSCREEN
);
210 m_aMonitors
.push_back( DisplayMonitor( rtl::OUString(),
212 Rectangle( Point(), Size( w
, h
) ),
213 Rectangle( Point(), Size( w
, h
) ),
215 m_aDeviceNameToMonitor
[ rtl::OUString() ] = 0;
218 if( SystemParametersInfo( SPI_GETWORKAREA
, 0, &aWorkRect
, 0 ) )
219 m_aMonitors
.back().m_aWorkArea
= Rectangle( aWorkRect
.left
, aWorkRect
.top
,
220 aWorkRect
.right
, aWorkRect
.bottom
);
223 return m_aMonitors
.size() > 0;
226 unsigned int WinSalSystem::GetDisplayScreenCount()
229 return m_aMonitors
.size();
232 bool WinSalSystem::IsMultiDisplay()
237 unsigned int WinSalSystem::GetDefaultDisplayNumber()
243 Rectangle
WinSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen
)
246 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aArea
: Rectangle();
249 Rectangle
WinSalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen
)
252 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aWorkArea
: Rectangle();
255 rtl::OUString
WinSalSystem::GetScreenName( unsigned int nScreen
)
258 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aName
: rtl::OUString();
261 // -----------------------------------------------------------------------
262 /* We have to map the button identifier to the identifier used by the Win32
263 Platform SDK to specify the default button for the MessageBox API.
264 The first dimension is the button combination, the second dimension
265 is the button identifier.
267 static int DEFAULT_BTN_MAPPING_TABLE
[][8] =
269 // Undefined OK CANCEL ABORT RETRY IGNORE YES NO
270 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK
271 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK_CANCEL
272 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //ABORT_RETRY_IGNO
273 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO_CANCEL
274 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO
275 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
} //RETRY_CANCEL
278 int WinSalSystem::ShowNativeMessageBox(const String
& rTitle
, const String
& rMessage
, int nButtonCombination
, int nDefaultButton
)
280 DBG_ASSERT( nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
281 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
282 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
283 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
, "Invalid arguments!" );
285 int nFlags
= MB_TASKMODAL
| MB_SETFOREGROUND
| MB_ICONWARNING
| nButtonCombination
;
287 if (nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
288 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
289 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
290 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
)
291 nFlags
|= DEFAULT_BTN_MAPPING_TABLE
[nButtonCombination
][nDefaultButton
];
293 //#107209 hide the splash screen if active
294 ImplSVData
* pSVData
= ImplGetSVData();
295 if (pSVData
->mpIntroWindow
)
296 pSVData
->mpIntroWindow
->Hide();
300 reinterpret_cast<LPCWSTR
>(rMessage
.GetBuffer()),
301 reinterpret_cast<LPCWSTR
>(rTitle
.GetBuffer()),