1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 // rely on unicows on for multimon functions for older versions
37 #define VCL_NEED_BASETSD
38 #include "tools/presys.h"
40 #pragma warning(push, 1)
47 #include "tools/postsys.h"
49 #include "tools/string.hxx"
53 #include "saldata.hxx"
54 #include "tools/debug.hxx"
55 #include "vcl/svdata.hxx"
56 #include "vcl/window.hxx"
58 #include "rtl/ustrbuf.hxx"
62 SalSystem
* WinSalInstance::CreateSalSystem()
64 return new WinSalSystem();
67 WinSalSystem::~WinSalSystem()
71 // -----------------------------------------------------------------------
73 static BOOL CALLBACK
ImplEnumMonitorProc( HMONITOR hMonitor
,
78 WinSalSystem
* pSys
= reinterpret_cast<WinSalSystem
*>(dwData
);
79 return pSys
->handleMonitorCallback( reinterpret_cast<sal_IntPtr
>(hMonitor
),
80 reinterpret_cast<sal_IntPtr
>(hDC
),
81 reinterpret_cast<sal_IntPtr
>(lpRect
) );
84 sal_Bool
WinSalSystem::handleMonitorCallback( sal_IntPtr hMonitor
, sal_IntPtr
, sal_IntPtr
)
87 aInfo
.cbSize
= sizeof( aInfo
);
88 if( GetMonitorInfoW( reinterpret_cast<HMONITOR
>(hMonitor
), &aInfo
) )
90 aInfo
.szDevice
[CCHDEVICENAME
-1] = 0;
91 rtl::OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aInfo
.szDevice
) );
92 std::map
< rtl::OUString
, unsigned int >::const_iterator it
=
93 m_aDeviceNameToMonitor
.find( aDeviceName
);
94 if( it
!= m_aDeviceNameToMonitor
.end() )
96 DisplayMonitor
& rMon( m_aMonitors
[ it
->second
] );
97 rMon
.m_aArea
= Rectangle( Point( aInfo
.rcMonitor
.left
,
98 aInfo
.rcMonitor
.top
),
99 Size( aInfo
.rcMonitor
.right
- aInfo
.rcMonitor
.left
,
100 aInfo
.rcMonitor
.bottom
- aInfo
.rcMonitor
.top
) );
101 rMon
.m_aWorkArea
= Rectangle( Point( aInfo
.rcWork
.left
,
103 Size( aInfo
.rcWork
.right
- aInfo
.rcWork
.left
,
104 aInfo
.rcWork
.bottom
- aInfo
.rcWork
.top
) );
105 if( (aInfo
.dwFlags
& MONITORINFOF_PRIMARY
) != 0 )
106 m_nPrimary
= it
->second
;
112 void WinSalSystem::clearMonitors()
118 bool WinSalSystem::initMonitors()
120 if( m_aMonitors
.size() > 0 )
123 bool winVerOk
= true;
125 // multi monitor calls not available on Win95/NT
126 if ( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
128 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
<= 4 )
129 winVerOk
= false; // NT
131 else if( aSalShlData
.maVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
)
133 if ( aSalShlData
.maVersionInfo
.dwMajorVersion
== 4 && aSalShlData
.maVersionInfo
.dwMinorVersion
== 0 )
134 winVerOk
= false; // Win95
138 int nMonitors
= GetSystemMetrics( SM_CMONITORS
);
141 int w
= GetSystemMetrics( SM_CXSCREEN
);
142 int h
= GetSystemMetrics( SM_CYSCREEN
);
143 m_aMonitors
.push_back( DisplayMonitor( rtl::OUString(),
145 Rectangle( Point(), Size( w
, h
) ),
146 Rectangle( Point(), Size( w
, h
) ),
148 m_aDeviceNameToMonitor
[ rtl::OUString() ] = 0;
151 if( SystemParametersInfo( SPI_GETWORKAREA
, 0, &aWorkRect
, 0 ) )
152 m_aMonitors
.back().m_aWorkArea
= Rectangle( aWorkRect
.left
, aWorkRect
.top
,
153 aWorkRect
.right
, aWorkRect
.bottom
);
157 DISPLAY_DEVICEW aDev
;
158 aDev
.cb
= sizeof( aDev
);
160 std::hash_map
< rtl::OUString
, int, rtl::OUStringHash
> aDeviceStringCount
;
161 while( EnumDisplayDevicesW( NULL
, nDevice
++, &aDev
, 0 ) )
163 if( (aDev
.StateFlags
& DISPLAY_DEVICE_ACTIVE
)
164 && !(aDev
.StateFlags
& DISPLAY_DEVICE_MIRRORING_DRIVER
) ) // sort out non/disabled monitors
166 aDev
.DeviceName
[31] = 0;
167 aDev
.DeviceString
[127] = 0;
168 rtl::OUString
aDeviceName( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceName
) );
169 rtl::OUString
aDeviceString( reinterpret_cast<const sal_Unicode
*>(aDev
.DeviceString
) );
170 if( aDeviceStringCount
.find( aDeviceString
) == aDeviceStringCount
.end() )
171 aDeviceStringCount
[ aDeviceString
] = 1;
173 aDeviceStringCount
[ aDeviceString
]++;
174 m_aDeviceNameToMonitor
[ aDeviceName
] = m_aMonitors
.size();
175 m_aMonitors
.push_back( DisplayMonitor( aDeviceString
,
182 HDC aDesktopRC
= GetDC( NULL
);
183 EnumDisplayMonitors( aDesktopRC
, NULL
, ImplEnumMonitorProc
, reinterpret_cast<LPARAM
>(this) );
185 // append monitor numbers to name strings
186 std::hash_map
< rtl::OUString
, int, rtl::OUStringHash
> aDevCount( aDeviceStringCount
);
187 unsigned int nMonitors
= m_aMonitors
.size();
188 for( unsigned int i
= 0; i
< nMonitors
; i
++ )
190 const rtl::OUString
& rDev( m_aMonitors
[i
].m_aName
);
191 if( aDeviceStringCount
[ rDev
] > 1 )
193 int nInstance
= aDeviceStringCount
[ rDev
] - (-- aDevCount
[ rDev
] );
194 rtl::OUStringBuffer
aBuf( rDev
.getLength() + 8 );
196 aBuf
.appendAscii( " (" );
197 aBuf
.append( sal_Int32( nInstance
) );
198 aBuf
.append( sal_Unicode(')') );
199 m_aMonitors
[ i
].m_aName
= aBuf
.makeStringAndClear();
206 int w
= GetSystemMetrics( SM_CXSCREEN
);
207 int h
= GetSystemMetrics( SM_CYSCREEN
);
208 m_aMonitors
.push_back( DisplayMonitor( rtl::OUString(),
210 Rectangle( Point(), Size( w
, h
) ),
211 Rectangle( Point(), Size( w
, h
) ),
213 m_aDeviceNameToMonitor
[ rtl::OUString() ] = 0;
216 if( SystemParametersInfo( SPI_GETWORKAREA
, 0, &aWorkRect
, 0 ) )
217 m_aMonitors
.back().m_aWorkArea
= Rectangle( aWorkRect
.left
, aWorkRect
.top
,
218 aWorkRect
.right
, aWorkRect
.bottom
);
221 return m_aMonitors
.size() > 0;
224 unsigned int WinSalSystem::GetDisplayScreenCount()
227 return m_aMonitors
.size();
230 bool WinSalSystem::IsMultiDisplay()
235 unsigned int WinSalSystem::GetDefaultDisplayNumber()
241 Rectangle
WinSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen
)
244 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aArea
: Rectangle();
247 Rectangle
WinSalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen
)
250 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aWorkArea
: Rectangle();
253 rtl::OUString
WinSalSystem::GetScreenName( unsigned int nScreen
)
256 return (nScreen
< m_aMonitors
.size()) ? m_aMonitors
[nScreen
].m_aName
: rtl::OUString();
259 // -----------------------------------------------------------------------
260 /* We have to map the button identifier to the identifier used by the Win32
261 Platform SDK to specify the default button for the MessageBox API.
262 The first dimension is the button combination, the second dimension
263 is the button identifier.
265 static int DEFAULT_BTN_MAPPING_TABLE
[][8] =
267 // Undefined OK CANCEL ABORT RETRY IGNORE YES NO
268 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK
269 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //OK_CANCEL
270 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
}, //ABORT_RETRY_IGNO
271 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON3
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO_CANCEL
272 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
}, //YES_NO
273 { MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON2
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
, MB_DEFBUTTON1
} //RETRY_CANCEL
276 int WinSalSystem::ShowNativeMessageBox(const String
& rTitle
, const String
& rMessage
, int nButtonCombination
, int nDefaultButton
)
278 DBG_ASSERT( nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
279 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
280 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
281 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
, "Invalid arguments!" );
283 int nFlags
= MB_TASKMODAL
| MB_SETFOREGROUND
| MB_ICONWARNING
| nButtonCombination
;
285 if (nButtonCombination
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
&&
286 nButtonCombination
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL
&&
287 nDefaultButton
>= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
&&
288 nDefaultButton
<= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO
)
289 nFlags
|= DEFAULT_BTN_MAPPING_TABLE
[nButtonCombination
][nDefaultButton
];
291 //#107209 hide the splash screen if active
292 ImplSVData
* pSVData
= ImplGetSVData();
293 if (pSVData
->mpIntroWindow
)
294 pSVData
->mpIntroWindow
->Hide();
298 reinterpret_cast<LPCWSTR
>(rMessage
.GetBuffer()),
299 reinterpret_cast<LPCWSTR
>(rTitle
.GetBuffer()),