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