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