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