xref: /trunk/main/vcl/win/source/app/salinfo.cxx (revision 31598a226906602f93ad246cbee896e3caca5f8f)
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