1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*9f62ea84SAndrew Rist * distributed with this work for additional information
6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
10*9f62ea84SAndrew Rist *
11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*9f62ea84SAndrew Rist *
13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
17*9f62ea84SAndrew Rist * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist * under the License.
19*9f62ea84SAndrew Rist *
20*9f62ea84SAndrew Rist *************************************************************/
21*9f62ea84SAndrew Rist
22*9f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include "svsys.h"
28cdf0e10cSrcweir #include "rtl/ustrbuf.hxx"
29cdf0e10cSrcweir
30cdf0e10cSrcweir #include "tools/debug.hxx"
31cdf0e10cSrcweir #include "tools/string.hxx"
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include "vcl/window.hxx"
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include "win/salsys.h"
36cdf0e10cSrcweir #include "win/salframe.h"
37cdf0e10cSrcweir #include "win/salinst.h"
38cdf0e10cSrcweir #include "win/saldata.hxx"
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include "svdata.hxx"
41cdf0e10cSrcweir
42cdf0e10cSrcweir #include <hash_map>
43cdf0e10cSrcweir
CreateSalSystem()44cdf0e10cSrcweir SalSystem* WinSalInstance::CreateSalSystem()
45cdf0e10cSrcweir {
46cdf0e10cSrcweir return new WinSalSystem();
47cdf0e10cSrcweir }
48cdf0e10cSrcweir
~WinSalSystem()49cdf0e10cSrcweir WinSalSystem::~WinSalSystem()
50cdf0e10cSrcweir {
51cdf0e10cSrcweir }
52cdf0e10cSrcweir
53cdf0e10cSrcweir // -----------------------------------------------------------------------
54cdf0e10cSrcweir
ImplEnumMonitorProc(HMONITOR hMonitor,HDC hDC,LPRECT lpRect,LPARAM dwData)55cdf0e10cSrcweir static BOOL CALLBACK ImplEnumMonitorProc( HMONITOR hMonitor,
56cdf0e10cSrcweir HDC hDC,
57cdf0e10cSrcweir LPRECT lpRect,
58cdf0e10cSrcweir LPARAM dwData )
59cdf0e10cSrcweir {
60cdf0e10cSrcweir WinSalSystem* pSys = reinterpret_cast<WinSalSystem*>(dwData);
61cdf0e10cSrcweir return pSys->handleMonitorCallback( reinterpret_cast<sal_IntPtr>(hMonitor),
62cdf0e10cSrcweir reinterpret_cast<sal_IntPtr>(hDC),
63cdf0e10cSrcweir reinterpret_cast<sal_IntPtr>(lpRect) );
64cdf0e10cSrcweir }
65cdf0e10cSrcweir
handleMonitorCallback(sal_IntPtr hMonitor,sal_IntPtr,sal_IntPtr)66cdf0e10cSrcweir sal_Bool WinSalSystem::handleMonitorCallback( sal_IntPtr hMonitor, sal_IntPtr, sal_IntPtr )
67cdf0e10cSrcweir {
68cdf0e10cSrcweir MONITORINFOEXW aInfo;
69cdf0e10cSrcweir aInfo.cbSize = sizeof( aInfo );
70cdf0e10cSrcweir if( GetMonitorInfoW( reinterpret_cast<HMONITOR>(hMonitor), &aInfo ) )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir aInfo.szDevice[CCHDEVICENAME-1] = 0;
73cdf0e10cSrcweir rtl::OUString aDeviceName( reinterpret_cast<const sal_Unicode *>(aInfo.szDevice) );
74cdf0e10cSrcweir std::map< rtl::OUString, unsigned int >::const_iterator it =
75cdf0e10cSrcweir m_aDeviceNameToMonitor.find( aDeviceName );
76cdf0e10cSrcweir if( it != m_aDeviceNameToMonitor.end() )
77cdf0e10cSrcweir {
78cdf0e10cSrcweir DisplayMonitor& rMon( m_aMonitors[ it->second ] );
79cdf0e10cSrcweir rMon.m_aArea = Rectangle( Point( aInfo.rcMonitor.left,
80cdf0e10cSrcweir aInfo.rcMonitor.top ),
81cdf0e10cSrcweir Size( aInfo.rcMonitor.right - aInfo.rcMonitor.left,
82cdf0e10cSrcweir aInfo.rcMonitor.bottom - aInfo.rcMonitor.top ) );
83cdf0e10cSrcweir rMon.m_aWorkArea = Rectangle( Point( aInfo.rcWork.left,
84cdf0e10cSrcweir aInfo.rcWork.top ),
85cdf0e10cSrcweir Size( aInfo.rcWork.right - aInfo.rcWork.left,
86cdf0e10cSrcweir aInfo.rcWork.bottom - aInfo.rcWork.top ) );
87cdf0e10cSrcweir if( (aInfo.dwFlags & MONITORINFOF_PRIMARY) != 0 )
88cdf0e10cSrcweir m_nPrimary = it->second;
89cdf0e10cSrcweir }
90cdf0e10cSrcweir }
91cdf0e10cSrcweir return sal_True;
92cdf0e10cSrcweir }
93cdf0e10cSrcweir
clearMonitors()94cdf0e10cSrcweir void WinSalSystem::clearMonitors()
95cdf0e10cSrcweir {
96cdf0e10cSrcweir m_aMonitors.clear();
97cdf0e10cSrcweir m_nPrimary = 0;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir
initMonitors()100cdf0e10cSrcweir bool WinSalSystem::initMonitors()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir if( m_aMonitors.size() > 0 )
103cdf0e10cSrcweir return true;
104cdf0e10cSrcweir
105cdf0e10cSrcweir bool winVerOk = true;
106cdf0e10cSrcweir
107cdf0e10cSrcweir // multi monitor calls not available on Win95/NT
108cdf0e10cSrcweir if ( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
109cdf0e10cSrcweir {
110cdf0e10cSrcweir if ( aSalShlData.maVersionInfo.dwMajorVersion <= 4 )
111cdf0e10cSrcweir winVerOk = false; // NT
112cdf0e10cSrcweir }
113cdf0e10cSrcweir else if( aSalShlData.maVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
114cdf0e10cSrcweir {
115cdf0e10cSrcweir if ( aSalShlData.maVersionInfo.dwMajorVersion == 4 && aSalShlData.maVersionInfo.dwMinorVersion == 0 )
116cdf0e10cSrcweir winVerOk = false; // Win95
117cdf0e10cSrcweir }
118cdf0e10cSrcweir if( winVerOk )
119cdf0e10cSrcweir {
120cdf0e10cSrcweir int nMonitors = GetSystemMetrics( SM_CMONITORS );
121cdf0e10cSrcweir if( nMonitors == 1 )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir int w = GetSystemMetrics( SM_CXSCREEN );
124cdf0e10cSrcweir int h = GetSystemMetrics( SM_CYSCREEN );
125cdf0e10cSrcweir m_aMonitors.push_back( DisplayMonitor( rtl::OUString(),
126cdf0e10cSrcweir rtl::OUString(),
127cdf0e10cSrcweir Rectangle( Point(), Size( w, h ) ),
128cdf0e10cSrcweir Rectangle( Point(), Size( w, h ) ),
129cdf0e10cSrcweir 0 ) );
130cdf0e10cSrcweir m_aDeviceNameToMonitor[ rtl::OUString() ] = 0;
131cdf0e10cSrcweir m_nPrimary = 0;
132cdf0e10cSrcweir RECT aWorkRect;
133cdf0e10cSrcweir if( SystemParametersInfo( SPI_GETWORKAREA, 0, &aWorkRect, 0 ) )
134cdf0e10cSrcweir m_aMonitors.back().m_aWorkArea = Rectangle( aWorkRect.left, aWorkRect.top,
135cdf0e10cSrcweir aWorkRect.right, aWorkRect.bottom );
136cdf0e10cSrcweir }
137cdf0e10cSrcweir else
138cdf0e10cSrcweir {
139cdf0e10cSrcweir DISPLAY_DEVICEW aDev;
140cdf0e10cSrcweir aDev.cb = sizeof( aDev );
141cdf0e10cSrcweir DWORD nDevice = 0;
142cdf0e10cSrcweir std::hash_map< rtl::OUString, int, rtl::OUStringHash > aDeviceStringCount;
143cdf0e10cSrcweir while( EnumDisplayDevicesW( NULL, nDevice++, &aDev, 0 ) )
144cdf0e10cSrcweir {
145cdf0e10cSrcweir if( (aDev.StateFlags & DISPLAY_DEVICE_ACTIVE)
146cdf0e10cSrcweir && !(aDev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ) // sort out non/disabled monitors
147cdf0e10cSrcweir {
148cdf0e10cSrcweir aDev.DeviceName[31] = 0;
149cdf0e10cSrcweir aDev.DeviceString[127] = 0;
150cdf0e10cSrcweir rtl::OUString aDeviceName( reinterpret_cast<const sal_Unicode *>(aDev.DeviceName) );
151cdf0e10cSrcweir rtl::OUString aDeviceString( reinterpret_cast<const sal_Unicode *>(aDev.DeviceString) );
152cdf0e10cSrcweir if( aDeviceStringCount.find( aDeviceString ) == aDeviceStringCount.end() )
153cdf0e10cSrcweir aDeviceStringCount[ aDeviceString ] = 1;
154cdf0e10cSrcweir else
155cdf0e10cSrcweir aDeviceStringCount[ aDeviceString ]++;
156cdf0e10cSrcweir m_aDeviceNameToMonitor[ aDeviceName ] = m_aMonitors.size();
157cdf0e10cSrcweir m_aMonitors.push_back( DisplayMonitor( aDeviceString,
158cdf0e10cSrcweir aDeviceName,
159cdf0e10cSrcweir Rectangle(),
160cdf0e10cSrcweir Rectangle(),
161cdf0e10cSrcweir aDev.StateFlags ) );
162cdf0e10cSrcweir }
163cdf0e10cSrcweir }
164cdf0e10cSrcweir HDC aDesktopRC = GetDC( NULL );
165cdf0e10cSrcweir EnumDisplayMonitors( aDesktopRC, NULL, ImplEnumMonitorProc, reinterpret_cast<LPARAM>(this) );
166cdf0e10cSrcweir
167cdf0e10cSrcweir // append monitor numbers to name strings
168cdf0e10cSrcweir std::hash_map< rtl::OUString, int, rtl::OUStringHash > aDevCount( aDeviceStringCount );
169cdf0e10cSrcweir unsigned int nMonitors = m_aMonitors.size();
170cdf0e10cSrcweir for( unsigned int i = 0; i < nMonitors; i++ )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir const rtl::OUString& rDev( m_aMonitors[i].m_aName );
173cdf0e10cSrcweir if( aDeviceStringCount[ rDev ] > 1 )
174cdf0e10cSrcweir {
175cdf0e10cSrcweir int nInstance = aDeviceStringCount[ rDev ] - (-- aDevCount[ rDev ] );
176cdf0e10cSrcweir rtl::OUStringBuffer aBuf( rDev.getLength() + 8 );
177cdf0e10cSrcweir aBuf.append( rDev );
178cdf0e10cSrcweir aBuf.appendAscii( " (" );
179cdf0e10cSrcweir aBuf.append( sal_Int32( nInstance ) );
180cdf0e10cSrcweir aBuf.append( sal_Unicode(')') );
181cdf0e10cSrcweir m_aMonitors[ i ].m_aName = aBuf.makeStringAndClear();
182cdf0e10cSrcweir }
183cdf0e10cSrcweir }
184cdf0e10cSrcweir }
185cdf0e10cSrcweir }
186cdf0e10cSrcweir else
187cdf0e10cSrcweir {
188cdf0e10cSrcweir int w = GetSystemMetrics( SM_CXSCREEN );
189cdf0e10cSrcweir int h = GetSystemMetrics( SM_CYSCREEN );
190cdf0e10cSrcweir m_aMonitors.push_back( DisplayMonitor( rtl::OUString(),
191cdf0e10cSrcweir rtl::OUString(),
192cdf0e10cSrcweir Rectangle( Point(), Size( w, h ) ),
193cdf0e10cSrcweir Rectangle( Point(), Size( w, h ) ),
194cdf0e10cSrcweir 0 ) );
195cdf0e10cSrcweir m_aDeviceNameToMonitor[ rtl::OUString() ] = 0;
196cdf0e10cSrcweir m_nPrimary = 0;
197cdf0e10cSrcweir RECT aWorkRect;
198cdf0e10cSrcweir if( SystemParametersInfo( SPI_GETWORKAREA, 0, &aWorkRect, 0 ) )
199cdf0e10cSrcweir m_aMonitors.back().m_aWorkArea = Rectangle( aWorkRect.left, aWorkRect.top,
200cdf0e10cSrcweir aWorkRect.right, aWorkRect.bottom );
201cdf0e10cSrcweir }
202cdf0e10cSrcweir
203cdf0e10cSrcweir return m_aMonitors.size() > 0;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir
GetDisplayScreenCount()206cdf0e10cSrcweir unsigned int WinSalSystem::GetDisplayScreenCount()
207cdf0e10cSrcweir {
208cdf0e10cSrcweir initMonitors();
209cdf0e10cSrcweir return m_aMonitors.size();
210cdf0e10cSrcweir }
211cdf0e10cSrcweir
IsMultiDisplay()212cdf0e10cSrcweir bool WinSalSystem::IsMultiDisplay()
213cdf0e10cSrcweir {
214cdf0e10cSrcweir return false;
215cdf0e10cSrcweir }
216cdf0e10cSrcweir
GetDefaultDisplayNumber()217cdf0e10cSrcweir unsigned int WinSalSystem::GetDefaultDisplayNumber()
218cdf0e10cSrcweir {
219cdf0e10cSrcweir initMonitors();
220cdf0e10cSrcweir return m_nPrimary;
221cdf0e10cSrcweir }
222cdf0e10cSrcweir
GetDisplayScreenPosSizePixel(unsigned int nScreen)223cdf0e10cSrcweir Rectangle WinSalSystem::GetDisplayScreenPosSizePixel( unsigned int nScreen )
224cdf0e10cSrcweir {
225cdf0e10cSrcweir initMonitors();
226cdf0e10cSrcweir return (nScreen < m_aMonitors.size()) ? m_aMonitors[nScreen].m_aArea : Rectangle();
227cdf0e10cSrcweir }
228cdf0e10cSrcweir
GetDisplayWorkAreaPosSizePixel(unsigned int nScreen)229cdf0e10cSrcweir Rectangle WinSalSystem::GetDisplayWorkAreaPosSizePixel( unsigned int nScreen )
230cdf0e10cSrcweir {
231cdf0e10cSrcweir initMonitors();
232cdf0e10cSrcweir return (nScreen < m_aMonitors.size()) ? m_aMonitors[nScreen].m_aWorkArea : Rectangle();
233cdf0e10cSrcweir }
234cdf0e10cSrcweir
GetScreenName(unsigned int nScreen)235cdf0e10cSrcweir rtl::OUString WinSalSystem::GetScreenName( unsigned int nScreen )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir initMonitors();
238cdf0e10cSrcweir return (nScreen < m_aMonitors.size()) ? m_aMonitors[nScreen].m_aName : rtl::OUString();
239cdf0e10cSrcweir }
240cdf0e10cSrcweir
241cdf0e10cSrcweir // -----------------------------------------------------------------------
242cdf0e10cSrcweir /* We have to map the button identifier to the identifier used by the Win32
243cdf0e10cSrcweir Platform SDK to specify the default button for the MessageBox API.
244cdf0e10cSrcweir The first dimension is the button combination, the second dimension
245cdf0e10cSrcweir is the button identifier.
246cdf0e10cSrcweir */
247cdf0e10cSrcweir static int DEFAULT_BTN_MAPPING_TABLE[][8] =
248cdf0e10cSrcweir {
249cdf0e10cSrcweir // Undefined OK CANCEL ABORT RETRY IGNORE YES NO
250cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK
251cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //OK_CANCEL
252cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1 }, //ABORT_RETRY_IGNO
253cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON3, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO_CANCEL
254cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2 }, //YES_NO
255cdf0e10cSrcweir { MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1, MB_DEFBUTTON1 } //RETRY_CANCEL
256cdf0e10cSrcweir };
257cdf0e10cSrcweir
ShowNativeMessageBox(const String & rTitle,const String & rMessage,int nButtonCombination,int nDefaultButton)258cdf0e10cSrcweir int WinSalSystem::ShowNativeMessageBox(const String& rTitle, const String& rMessage, int nButtonCombination, int nDefaultButton)
259cdf0e10cSrcweir {
260cdf0e10cSrcweir DBG_ASSERT( nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
261cdf0e10cSrcweir nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
262cdf0e10cSrcweir nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
263cdf0e10cSrcweir nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO, "Invalid arguments!" );
264cdf0e10cSrcweir
265cdf0e10cSrcweir int nFlags = MB_TASKMODAL | MB_SETFOREGROUND | MB_ICONWARNING | nButtonCombination;
266cdf0e10cSrcweir
267cdf0e10cSrcweir if (nButtonCombination >= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK &&
268cdf0e10cSrcweir nButtonCombination <= SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_RETRY_CANCEL &&
269cdf0e10cSrcweir nDefaultButton >= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK &&
270cdf0e10cSrcweir nDefaultButton <= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_NO)
271cdf0e10cSrcweir nFlags |= DEFAULT_BTN_MAPPING_TABLE[nButtonCombination][nDefaultButton];
272cdf0e10cSrcweir
273cdf0e10cSrcweir //#107209 hide the splash screen if active
274cdf0e10cSrcweir ImplSVData* pSVData = ImplGetSVData();
275cdf0e10cSrcweir if (pSVData->mpIntroWindow)
276cdf0e10cSrcweir pSVData->mpIntroWindow->Hide();
277cdf0e10cSrcweir
278cdf0e10cSrcweir return MessageBoxW(
279cdf0e10cSrcweir 0,
280cdf0e10cSrcweir reinterpret_cast<LPCWSTR>(rMessage.GetBuffer()),
281cdf0e10cSrcweir reinterpret_cast<LPCWSTR>(rTitle.GetBuffer()),
282cdf0e10cSrcweir nFlags);
283cdf0e10cSrcweir }
284