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 #if OSL_DEBUG_LEVEL > 1 32 #include <stdio.h> 33 #endif 34 #include <tools/debug.hxx> 35 36 #include <vcl/keycodes.hxx> 37 38 #include <tools/prex.h> 39 #include <X11/Xlib.h> 40 #include <X11/extensions/shape.h> 41 #include <tools/postx.h> 42 43 #include <unx/salunx.h> 44 #include <unx/salstd.hxx> 45 #include <unx/saldata.hxx> 46 #include <unx/salinst.h> 47 #include <unx/saldisp.hxx> 48 #include <unx/salframe.h> 49 #include <unx/salobj.h> 50 51 #include <salwtype.hxx> 52 53 54 // ======================================================================= 55 // SalInstance member to create and destroy a SalObject 56 57 SalObject* X11SalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow ) 58 { 59 return X11SalObject::CreateObject( pParent, pWindowData, bShow ); 60 } 61 62 X11SalObject* X11SalObject::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, sal_Bool bShow ) 63 { 64 int error_base, event_base; 65 X11SalObject* pObject = new X11SalObject(); 66 SystemChildData* pObjData = const_cast<SystemChildData*>(pObject->GetSystemData()); 67 68 if ( ! XShapeQueryExtension( (Display*)pObjData->pDisplay, 69 &event_base, &error_base ) ) 70 { 71 delete pObject; 72 return NULL; 73 } 74 75 pObject->mpParent = pParent; 76 77 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 78 const SystemEnvData* pEnv = pParent->GetSystemData(); 79 Display* pDisp = pSalDisp->GetDisplay(); 80 XLIB_Window aObjectParent = (XLIB_Window)pEnv->aWindow; 81 82 // find out on which screen that window is 83 XWindowAttributes aParentAttr; 84 XGetWindowAttributes( pDisp, aObjectParent, &aParentAttr ); 85 int nScreen = XScreenNumberOfScreen( aParentAttr.screen ); 86 Visual* pVisual = (pWindowData && pWindowData->pVisual) ? 87 (Visual*)pWindowData->pVisual : 88 pSalDisp->GetVisual( nScreen ).GetVisual(); 89 // get visual info 90 VisualID aVisID = XVisualIDFromVisual( pVisual ); 91 XVisualInfo aTemplate; 92 aTemplate.visualid = aVisID; 93 int nVisuals = 0; 94 XVisualInfo* pInfos = XGetVisualInfo( pDisp, VisualIDMask, &aTemplate, &nVisuals ); 95 // only one VisualInfo structure can match the visual id 96 DBG_ASSERT( nVisuals == 1, "match count for visual id is not 1" ); 97 unsigned int nDepth = pInfos->depth; 98 XFree( pInfos ); 99 XSetWindowAttributes aAttribs; 100 aAttribs.event_mask = StructureNotifyMask 101 | ButtonPressMask 102 | ButtonReleaseMask 103 | PointerMotionMask 104 | EnterWindowMask 105 | LeaveWindowMask 106 | FocusChangeMask 107 | ExposureMask 108 ; 109 110 pObject->maPrimary = 111 XCreateSimpleWindow( pDisp, 112 aObjectParent, 113 0, 0, 114 1, 1, 0, 115 pSalDisp->GetColormap( nScreen ).GetBlackPixel(), 116 pSalDisp->GetColormap( nScreen ).GetWhitePixel() 117 ); 118 if( aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() ) 119 { 120 pObject->maSecondary = 121 XCreateSimpleWindow( pDisp, 122 pObject->maPrimary, 123 0, 0, 124 1, 1, 0, 125 pSalDisp->GetColormap( nScreen ).GetBlackPixel(), 126 pSalDisp->GetColormap( nScreen ).GetWhitePixel() 127 ); 128 } 129 else 130 { 131 #if OSL_DEBUG_LEVEL > 1 132 fprintf( stderr, "visual id of vcl %x, of visual %x\n", 133 static_cast<unsigned int> (pSalDisp->GetVisual( nScreen ).GetVisualId()), 134 static_cast<unsigned int> (aVisID) ); 135 #endif 136 pSalDisp->GetXLib()->PushXErrorLevel( true ); 137 138 // create colormap for visual - there might not be one 139 pObject->maColormap = aAttribs.colormap = XCreateColormap( 140 pDisp, 141 pSalDisp->GetRootWindow( nScreen ), 142 pVisual, 143 AllocNone ); 144 145 pObject->maSecondary = 146 XCreateWindow( pDisp, 147 pSalDisp->GetRootWindow( nScreen ), 148 0, 0, 149 1, 1, 0, 150 nDepth, InputOutput, 151 pVisual, 152 CWEventMask|CWColormap, &aAttribs ); 153 XSync( pDisp, False ); 154 sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured(); 155 pSalDisp->GetXLib()->PopXErrorLevel(); 156 if( bWasXError ) 157 { 158 pObject->maSecondary = None; 159 delete pObject; 160 return NULL; 161 } 162 XReparentWindow( pDisp, pObject->maSecondary, pObject->maPrimary, 0, 0 ); 163 } 164 165 pSalDisp->GetXLib()->PushXErrorLevel( true ); 166 if( bShow ) { 167 XMapWindow( pDisp, pObject->maSecondary ); 168 XMapWindow( pDisp, pObject->maPrimary ); 169 } 170 171 pObjData->pDisplay = pDisp; 172 pObjData->aWindow = pObject->maSecondary; 173 pObjData->pWidget = NULL; 174 pObjData->pVisual = pVisual; 175 pObjData->nDepth = nDepth; 176 pObjData->aColormap = aVisID == pSalDisp->GetVisual( nScreen ).GetVisualId() ? 177 pSalDisp->GetColormap( nScreen ).GetXColormap() : None; 178 pObjData->pAppContext = NULL; 179 180 XSync(pDisp, False); 181 sal_Bool bWasXError = pSalDisp->GetXLib()->HasXErrorOccured(); 182 pSalDisp->GetXLib()->PopXErrorLevel(); 183 if( bWasXError ) 184 { 185 delete pObject; 186 return NULL; 187 } 188 189 return pObject; 190 } 191 192 193 void X11SalInstance::DestroyObject( SalObject* pObject ) 194 { 195 delete pObject; 196 } 197 198 199 // ====================================================================== 200 // SalClipRegion is a member of SalObject 201 // definition of SalClipRegion my be found in unx/inc/salobj.h 202 203 204 SalClipRegion::SalClipRegion() 205 { 206 ClipRectangleList = NULL; 207 numClipRectangles = 0; 208 maxClipRectangles = 0; 209 nClipRegionType = SAL_OBJECT_CLIP_INCLUDERECTS; 210 } 211 212 213 SalClipRegion::~SalClipRegion() 214 { 215 if ( ClipRectangleList ) 216 delete [] ClipRectangleList; 217 } 218 219 220 void 221 SalClipRegion::BeginSetClipRegion( sal_uLong nRects ) 222 { 223 if (ClipRectangleList) 224 delete [] ClipRectangleList; 225 226 ClipRectangleList = new XRectangle[nRects]; 227 numClipRectangles = 0; 228 maxClipRectangles = nRects; 229 } 230 231 232 void 233 SalClipRegion::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 234 { 235 if ( nWidth && nHeight && (numClipRectangles < maxClipRectangles) ) 236 { 237 XRectangle *aRect = ClipRectangleList + numClipRectangles; 238 239 aRect->x = (short) nX; 240 aRect->y = (short) nY; 241 aRect->width = (unsigned short) nWidth; 242 aRect->height= (unsigned short) nHeight; 243 244 numClipRectangles++; 245 } 246 } 247 248 249 // ======================================================================= 250 // SalObject Implementation 251 252 253 X11SalObject::X11SalObject() 254 { 255 maSystemChildData.nSize = sizeof( SystemChildData ); 256 maSystemChildData.pDisplay = GetX11SalData()->GetDisplay()->GetDisplay(); 257 maSystemChildData.aWindow = None; 258 maSystemChildData.pSalFrame = 0; 259 maSystemChildData.pWidget = 0; 260 maSystemChildData.pVisual = 0; 261 maSystemChildData.nDepth = 0; 262 maSystemChildData.aColormap = 0; 263 maSystemChildData.pAppContext = NULL; 264 maSystemChildData.aShellWindow = 0; 265 maSystemChildData.pShellWidget = NULL; 266 maPrimary = 0; 267 maSecondary = 0; 268 maColormap = 0; 269 270 std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects(); 271 rObjects.push_back( this ); 272 } 273 274 275 X11SalObject::~X11SalObject() 276 { 277 std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects(); 278 rObjects.remove( this ); 279 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 280 pSalDisp->GetXLib()->PushXErrorLevel( true ); 281 if ( maSecondary ) 282 XDestroyWindow( (Display*)maSystemChildData.pDisplay, maSecondary ); 283 if ( maPrimary ) 284 XDestroyWindow( (Display*)maSystemChildData.pDisplay, maPrimary ); 285 if ( maColormap ) 286 XFreeColormap((Display*)maSystemChildData.pDisplay, maColormap); 287 XSync( (Display*)maSystemChildData.pDisplay, False ); 288 pSalDisp->GetXLib()->PopXErrorLevel(); 289 } 290 291 292 void 293 X11SalObject::ResetClipRegion() 294 { 295 maClipRegion.ResetClipRegion(); 296 297 const int dest_kind = ShapeBounding; 298 const int op = ShapeSet; 299 const int ordering = YSorted; 300 301 XWindowAttributes win_attrib; 302 XRectangle win_size; 303 304 XLIB_Window aShapeWindow = maPrimary; 305 306 XGetWindowAttributes ( (Display*)maSystemChildData.pDisplay, 307 aShapeWindow, 308 &win_attrib ); 309 310 win_size.x = 0; 311 win_size.y = 0; 312 win_size.width = win_attrib.width; 313 win_size.height = win_attrib.height; 314 315 XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay, 316 aShapeWindow, 317 dest_kind, 318 0, 0, // x_off, y_off 319 &win_size, // list of rectangles 320 1, // number of rectangles 321 op, ordering ); 322 } 323 324 325 void 326 X11SalObject::BeginSetClipRegion( sal_uLong nRectCount ) 327 { 328 maClipRegion.BeginSetClipRegion ( nRectCount ); 329 } 330 331 332 void 333 X11SalObject::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 334 { 335 maClipRegion.UnionClipRegion ( nX, nY, nWidth, nHeight ); 336 } 337 338 339 void 340 X11SalObject::EndSetClipRegion() 341 { 342 XRectangle *pRectangles = maClipRegion.EndSetClipRegion (); 343 const int nType = maClipRegion.GetClipRegionType(); 344 const int nRectangles = maClipRegion.GetRectangleCount(); 345 346 const int dest_kind = ShapeBounding; 347 const int ordering = YSorted; 348 int op; 349 350 switch ( nType ) 351 { 352 case SAL_OBJECT_CLIP_INCLUDERECTS : 353 op = ShapeSet; 354 break; 355 case SAL_OBJECT_CLIP_EXCLUDERECTS : 356 op = ShapeSubtract; 357 break; 358 case SAL_OBJECT_CLIP_ABSOLUTE : 359 op = ShapeSet; 360 break; 361 default : 362 op = ShapeUnion; 363 } 364 365 XLIB_Window aShapeWindow = maPrimary; 366 367 XShapeCombineRectangles ( (Display*)maSystemChildData.pDisplay, 368 aShapeWindow, 369 dest_kind, 370 0, 0, // x_off, y_off 371 pRectangles, 372 nRectangles, 373 op, ordering ); 374 } 375 376 377 sal_uInt16 378 X11SalObject::GetClipRegionType() 379 { 380 return maClipRegion.GetClipRegionType(); 381 } 382 383 // ----------------------------------------------------------------------- 384 385 void 386 X11SalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight ) 387 { 388 if ( maPrimary && maSecondary && nWidth && nHeight ) 389 { 390 XMoveResizeWindow( (Display*)maSystemChildData.pDisplay, 391 maPrimary, 392 nX, nY, nWidth, nHeight ); 393 XMoveResizeWindow( (Display*)maSystemChildData.pDisplay, 394 maSecondary, 395 0, 0, nWidth, nHeight ); 396 } 397 } 398 399 400 void 401 X11SalObject::Show( sal_Bool bVisible ) 402 { 403 if ( ! maSystemChildData.aWindow ) 404 return; 405 406 if ( bVisible ) { 407 XMapWindow( (Display*)maSystemChildData.pDisplay, 408 maSecondary ); 409 XMapWindow( (Display*)maSystemChildData.pDisplay, 410 maPrimary ); 411 } else { 412 XUnmapWindow( (Display*)maSystemChildData.pDisplay, 413 maPrimary ); 414 XUnmapWindow( (Display*)maSystemChildData.pDisplay, 415 maSecondary ); 416 } 417 mbVisible = bVisible; 418 } 419 420 // ----------------------------------------------------------------------- 421 422 void X11SalObject::Enable( sal_Bool ) 423 { 424 } 425 426 // ----------------------------------------------------------------------- 427 428 void X11SalObject::GrabFocus() 429 { 430 if( mbVisible ) 431 XSetInputFocus( (Display*)maSystemChildData.pDisplay, 432 maSystemChildData.aWindow, 433 RevertToNone, 434 CurrentTime ); 435 } 436 437 // ----------------------------------------------------------------------- 438 439 void X11SalObject::SetBackground() 440 { 441 } 442 443 // ----------------------------------------------------------------------- 444 445 void X11SalObject::SetBackground( SalColor ) 446 { 447 } 448 449 // ----------------------------------------------------------------------- 450 451 const SystemChildData* X11SalObject::GetSystemData() const 452 { 453 return &maSystemChildData; 454 } 455 456 static sal_uInt16 sal_GetCode( int state ) 457 { 458 sal_uInt16 nCode = 0; 459 460 if( state & Button1Mask ) 461 nCode |= MOUSE_LEFT; 462 if( state & Button2Mask ) 463 nCode |= MOUSE_MIDDLE; 464 if( state & Button3Mask ) 465 nCode |= MOUSE_RIGHT; 466 467 if( state & ShiftMask ) 468 nCode |= KEY_SHIFT; 469 if( state & ControlMask ) 470 nCode |= KEY_MOD1; 471 if( state & Mod1Mask ) 472 nCode |= KEY_MOD2; 473 if( state & Mod3Mask ) 474 nCode |= KEY_MOD3; 475 476 return nCode; 477 } 478 479 long X11SalObject::Dispatch( XEvent* pEvent ) 480 { 481 std::list< SalObject* >& rObjects = GetX11SalData()->GetDisplay()->getSalObjects(); 482 483 for( std::list< SalObject* >::iterator it = rObjects.begin(); it != rObjects.end(); ++it ) 484 { 485 X11SalObject* pObject = static_cast<X11SalObject*>(*it); 486 if( pEvent->xany.window == pObject->maPrimary || 487 pEvent->xany.window == pObject->maSecondary ) 488 { 489 if( pObject->IsMouseTransparent() && ( 490 pEvent->type == ButtonPress || 491 pEvent->type == ButtonRelease || 492 pEvent->type == EnterNotify || 493 pEvent->type == LeaveNotify || 494 pEvent->type == MotionNotify 495 ) 496 ) 497 { 498 SalMouseEvent aEvt; 499 const SystemEnvData* pParentData = pObject->mpParent->GetSystemData(); 500 int dest_x, dest_y; 501 XLIB_Window aChild = None; 502 XTranslateCoordinates( pEvent->xbutton.display, 503 pEvent->xbutton.root, 504 pParentData->aWindow, 505 pEvent->xbutton.x_root, 506 pEvent->xbutton.y_root, 507 &dest_x, &dest_y, 508 &aChild ); 509 aEvt.mnX = dest_x; 510 aEvt.mnY = dest_y; 511 aEvt.mnTime = pEvent->xbutton.time; 512 aEvt.mnCode = sal_GetCode( pEvent->xbutton.state ); 513 aEvt.mnButton = 0; 514 sal_uInt16 nEvent = 0; 515 if( pEvent->type == ButtonPress || 516 pEvent->type == ButtonRelease ) 517 { 518 switch( pEvent->xbutton.button ) 519 { 520 case Button1: aEvt.mnButton = MOUSE_LEFT;break; 521 case Button2: aEvt.mnButton = MOUSE_MIDDLE;break; 522 case Button3: aEvt.mnButton = MOUSE_RIGHT;break; 523 } 524 nEvent = (pEvent->type == ButtonPress) ? 525 SALEVENT_MOUSEBUTTONDOWN : 526 SALEVENT_MOUSEBUTTONUP; 527 } 528 else if( pEvent->type == EnterNotify ) 529 nEvent = SALEVENT_MOUSELEAVE; 530 else 531 nEvent = SALEVENT_MOUSEMOVE; 532 pObject->mpParent->CallCallback( nEvent, &aEvt ); 533 } 534 else 535 { 536 switch( pEvent->type ) 537 { 538 case UnmapNotify: 539 pObject->mbVisible = sal_False; 540 return 1; 541 case MapNotify: 542 pObject->mbVisible = sal_True; 543 return 1; 544 case ButtonPress: 545 pObject->CallCallback( SALOBJ_EVENT_TOTOP, NULL ); 546 return 1; 547 case FocusIn: 548 pObject->CallCallback( SALOBJ_EVENT_GETFOCUS, NULL ); 549 return 1; 550 case FocusOut: 551 pObject->CallCallback( SALOBJ_EVENT_LOSEFOCUS, NULL ); 552 return 1; 553 default: break; 554 } 555 } 556 return 0; 557 } 558 } 559 return 0; 560 } 561 562 // ----------------------------------------------------------------------- 563 564 void X11SalObject::InterceptChildWindowKeyDown( sal_Bool /*bIntercept*/ ) 565 { 566 } 567 568