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