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