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