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 #define SAL_XT 28 29 // -=-= #includes =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 30 #include <string.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <math.h> 34 #include <sys/time.h> 35 #include <pthread.h> 36 #include <unistd.h> 37 #include <ctype.h> 38 #include <string.h> 39 40 #if defined(SOLARIS) 41 #include <sal/alloca.h> 42 #include <osl/module.h> 43 #endif 44 45 #include <tools/prex.h> 46 #include <X11/cursorfont.h> 47 #include "unx/x11_cursors/salcursors.h" 48 #include "unx/x11_cursors/invert50.h" 49 #ifdef SOLARIS 50 #define XK_KOREAN 51 #endif 52 #include <X11/keysym.h> 53 54 #include <X11/Xatom.h> 55 56 #ifdef USE_XINERAMA 57 #ifdef USE_XINERAMA_XORG 58 #include <X11/extensions/Xinerama.h> 59 #elif defined USE_XINERAMA_XSUN 60 #if defined(SOLARIS) && defined(INTEL) // missing extension header in standard installation 61 #define MAXFRAMEBUFFERS 16 62 Bool XineramaGetState(Display*, int); 63 Status XineramaGetInfo(Display*, int, XRectangle*, unsigned char*, int*); 64 #else 65 #include <X11/extensions/xinerama.h> 66 #endif 67 #else 68 #error USE_XINERAMA but no xinerama version 69 #endif 70 #endif 71 72 #include <tools/postx.h> 73 74 #include <unx/salunx.h> 75 #include <sal/types.h> 76 #include "unx/i18n_im.hxx" 77 #include "unx/i18n_xkb.hxx" 78 #include <unx/saldisp.hxx> 79 #include <unx/saldata.hxx> 80 #include <salinst.hxx> 81 #include <unx/salgdi.h> 82 #include <unx/salframe.h> 83 #include <vcl/keycodes.hxx> 84 #include <vcl/salbtype.hxx> 85 #include <unx/salbmp.h> 86 #ifndef _OSL_THREADMUTEX_H_ 87 #include <osl/mutex.h> 88 #endif 89 #include <unx/salobj.h> 90 #include <unx/sm.hxx> 91 #include <unx/wmadaptor.hxx> 92 #include <unx/dtint.hxx> 93 94 #include <osl/socket.h> 95 #include <poll.h> 96 97 using namespace rtl; 98 using namespace vcl_sal; 99 100 // -=-= #defines -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 101 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 102 #define PSEUDOCOLOR12 103 #define PSEUDOCOLOR8 104 #define TRUECOLOR24 105 #define TRUECOLOR16 106 #define TRUECOLOR15 107 #define TRUECOLOR12 108 #define TRUECOLOR8 109 110 #define SALCOLOR_WHITE MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) 111 #define SALCOLOR_BLACK MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) 112 113 // -=-= Prototyps =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 114 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 115 // -=-= static variables -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 116 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 117 static const char* const VisualClassName[] = { 118 "StaticGray", 119 "GrayScale", 120 "StaticColor", 121 "PseudoColor", 122 "TrueColor", 123 "DirectColor" 124 }; 125 126 static const char* const EventNames[] = 127 { 128 NULL, 129 NULL, 130 "KeyPress", 131 "KeyRelease", 132 "ButtonPress", 133 "ButtonRelease", 134 "MotionNotify", 135 "EnterNotify", 136 "LeaveNotify", 137 "FocusIn", 138 "FocusOut", 139 "KeymapNotify", 140 "Expose", 141 "GraphicsExpose", 142 "NoExpose", 143 "VisibilityNotify", 144 "CreateNotify", 145 "DestroyNotify", 146 "UnmapNotify", 147 "MapNotify", 148 "MapRequest", 149 "ReparentNotify", 150 "ConfigureNotify", 151 "ConfigureRequest", 152 "GravityNotify", 153 "ResizeRequest", 154 "CirculateNotify", 155 "CirculateRequest", 156 "PropertyNotify", 157 "SelectionClear", 158 "SelectionRequest", 159 "SelectionNotify", 160 "ColormapNotify", 161 "ClientMessage", 162 "MappingNotify" 163 }; 164 165 // -=-= global inline =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 166 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 167 inline const char *Null( const char *p ) { return p ? p : ""; } 168 inline const char *GetEnv( const char *p ) { return Null( getenv( p ) ); } 169 inline const char *KeyStr( KeySym n ) { return Null( XKeysymToString( n ) ); } 170 171 inline const char *GetAtomName( Display *d, Atom a ) 172 { return Null( XGetAtomName( d, a ) ); } 173 174 inline double Hypothenuse( long w, long h ) 175 { return sqrt( (double)((w*w)+(h*h)) ); } 176 177 inline int ColorDiff( int r, int g, int b ) 178 { return (r*r)+(g*g)+(b*b); } 179 180 inline int ColorDiff( SalColor c1, int r, int g, int b ) 181 { return ColorDiff( (int)SALCOLOR_RED (c1)-r, 182 (int)SALCOLOR_GREEN(c1)-g, 183 (int)SALCOLOR_BLUE (c1)-b ); } 184 185 // -=-= global functions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 186 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 187 static int sal_Shift( Pixel nMask ) 188 { 189 int i = 24; 190 if( nMask < 0x00010000 ) { nMask <<= 16; i -= 16; } 191 if( nMask < 0x01000000 ) { nMask <<= 8; i -= 8; } 192 if( nMask < 0x10000000 ) { nMask <<= 4; i -= 4; } 193 if( nMask < 0x40000000 ) { nMask <<= 2; i -= 2; } 194 if( nMask < 0x80000000 ) { nMask <<= 1; i -= 1; } 195 return i; 196 } 197 198 static int sal_significantBits( Pixel nMask ) 199 { 200 int nRotate = sizeof(Pixel)*4; 201 int nBits = 0; 202 while( nRotate-- ) 203 { 204 if( nMask & 1 ) 205 nBits++; 206 nMask >>= 1; 207 } 208 return nBits; 209 } 210 211 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 212 static sal_Bool sal_GetVisualInfo( Display *pDisplay, XID nVID, XVisualInfo &rVI ) 213 { 214 int nInfos; 215 XVisualInfo aTemplate; 216 XVisualInfo*pInfos; 217 218 aTemplate.visualid = nVID; 219 220 pInfos = XGetVisualInfo( pDisplay, VisualIDMask, &aTemplate, &nInfos ); 221 if( !pInfos ) 222 return sal_False; 223 224 rVI = *pInfos; 225 XFree( pInfos ); 226 227 DBG_ASSERT( rVI.visualid == nVID, 228 "sal_GetVisualInfo: could not get correct visual by visualId" ); 229 return sal_True; 230 } 231 232 // --------------------------------------------------------------------------- 233 234 // check wether displaystring is in format N.M or N. or just N 235 // with N and M beeing natural numbers 236 static sal_Bool 237 sal_IsDisplayNumber( const char *pDisplayString ) 238 { 239 if ( ! isdigit(*pDisplayString) ) 240 return sal_False; 241 while ( isdigit(*(++pDisplayString)) ) 242 ; /* do nothing */ 243 244 if ( *pDisplayString == '.' ) 245 { 246 while ( isdigit(*(++pDisplayString)) ) 247 ; /* do nothing */ 248 } 249 250 return (*pDisplayString == '\0'); 251 } 252 253 // check whether host1 and host2 point to the same ip address 254 static sal_Bool 255 sal_EqualHosts( const OUString& Host1, const OUString& Host2) 256 { 257 oslSocketAddr pHostAddr1; 258 oslSocketAddr pHostAddr2; 259 sal_Bool bEqualAddress = sal_False; 260 261 if ( Host1.toChar() >= '0' && Host1.toChar() <= '9' ) 262 pHostAddr1 = osl_createInetSocketAddr( Host1.pData, 0 ); 263 else 264 pHostAddr1 = osl_resolveHostname( Host1.pData ); 265 266 if ( Host2.toChar() >= '0' && Host2.toChar() <= '9' ) 267 pHostAddr2 = osl_createInetSocketAddr( Host2.pData, 0 ); 268 else 269 pHostAddr2 = osl_resolveHostname( Host2.pData ); 270 271 if( pHostAddr1 && pHostAddr2 ) 272 bEqualAddress = osl_isEqualSocketAddr( pHostAddr1, pHostAddr2 ) ? sal_True : sal_False; 273 274 if( pHostAddr1 ) 275 osl_destroySocketAddr( pHostAddr1 ); 276 if( pHostAddr2 ) 277 osl_destroySocketAddr( pHostAddr2 ); 278 279 return bEqualAddress; 280 } 281 282 static sal_Bool 283 sal_IsLocalDisplay( Display *pDisplay ) 284 { 285 const char *pDisplayString = DisplayString( pDisplay ); 286 287 // no string, no idea 288 if ( pDisplayString == NULL || pDisplayString[ 0 ] == '\0') 289 return sal_False; 290 291 // check for ":x.y" 292 if ( pDisplayString[ 0 ] == ':' ) 293 return sal_IsDisplayNumber( pDisplayString + 1 ); 294 295 // check for fixed token which all mean localhost:x.y 296 const char pLocal[] = "localhost:"; 297 const int nLocalLen = sizeof(pLocal) - 1; 298 if ( strncmp(pDisplayString, pLocal, nLocalLen) == 0 ) 299 return sal_IsDisplayNumber( pDisplayString + nLocalLen ); 300 301 const char pUnix[] = "unix:"; 302 const int nUnixLen = sizeof(pUnix) - 1; 303 if ( strncmp(pDisplayString, pUnix, nUnixLen) == 0 ) 304 return sal_IsDisplayNumber( pDisplayString + nUnixLen ); 305 306 const char pLoopback[] = "127.0.0.1:"; 307 const int nLoopbackLen= sizeof(pLoopback) - 1; 308 if ( strncmp(pDisplayString, pLoopback, nLoopbackLen) == 0 ) 309 return sal_IsDisplayNumber( pDisplayString + nLoopbackLen ); 310 311 // compare local hostname to displaystring, both may be ip address or 312 // hostname 313 sal_Bool bEqual = sal_False; 314 char *pDisplayHost = strdup( pDisplayString ); 315 char *pPtr = strrchr( pDisplayHost, ':' ); 316 317 if( pPtr != NULL ) 318 { 319 const OUString& rLocalHostname( GetX11SalData()->GetLocalHostName() ); 320 if( rLocalHostname.getLength() ) 321 { 322 *pPtr = '\0'; 323 OUString aDisplayHostname( pDisplayHost, strlen( pDisplayHost ), osl_getThreadTextEncoding() ); 324 bEqual = sal_EqualHosts( rLocalHostname, aDisplayHostname ); 325 bEqual = bEqual && sal_IsDisplayNumber( pPtr + 1 ); 326 } 327 } 328 free( pDisplayHost ); 329 330 return bEqual; 331 } 332 333 // --------------------------------------------------------------------------- 334 // IsLocal means soffice is running on the same host as the xserver 335 // since it is not called very often and sal_IsLocalDisplay() is relative 336 // expensive bLocal_ is initialized on first call 337 338 sal_Bool SalDisplay::IsLocal() 339 { 340 if ( ! mbLocalIsValid ) 341 { 342 bLocal_ = sal_IsLocalDisplay( pDisp_ ); 343 mbLocalIsValid = sal_True; 344 } 345 return (sal_Bool)bLocal_; 346 } 347 348 // --------------------------------------------------------------------------- 349 extern "C" srv_vendor_t 350 sal_GetServerVendor( Display *p_display ) 351 { 352 typedef struct { 353 srv_vendor_t e_vendor; // vendor as enum 354 const char *p_name; // vendor name as returned by VendorString() 355 unsigned int n_len; // number of chars to compare 356 } vendor_t; 357 358 const vendor_t p_vendorlist[] = { 359 { vendor_xfree, "The XFree86 Project, Inc", 13 }, 360 { vendor_sun, "Sun Microsystems, Inc.", 10 }, 361 { vendor_attachmate, "Attachmate Corporation", 10 }, 362 { vendor_excursion, 363 "DECWINDOWS DigitalEquipmentCorporation, eXcursion", 42 }, 364 { vendor_hp, "Hewlett-Packard Company", 17 }, 365 { vendor_hummingbird, "Hummingbird Communications Ltd.", 11 }, 366 { vendor_ibm, "International Business Machines", 24 }, 367 { vendor_sgi, "Silicon Graphics", 9 }, 368 { vendor_sco, "The Santa Cruz Operation", 16 }, 369 { vendor_xinside, "X Inside Inc.", 10 }, 370 // allways the last entry: vendor_none to indicate eol 371 { vendor_none, NULL, 0 }, 372 }; 373 374 // handle regular server vendors 375 char *p_name = ServerVendor( p_display ); 376 vendor_t *p_vendor; 377 for (p_vendor = const_cast<vendor_t*>(p_vendorlist); p_vendor->e_vendor != vendor_none; p_vendor++) 378 { 379 if ( strncmp (p_name, p_vendor->p_name, p_vendor->n_len) == 0 ) 380 return p_vendor->e_vendor; 381 } 382 383 // vendor not found in list 384 return vendor_unknown; 385 } 386 387 static sal_Bool sal_IsTrustedSolaris (Display *p_display) 388 { 389 int n_numextensions = 0; 390 char **p_extensions = XListExtensions (p_display, &n_numextensions); 391 sal_Bool b_is = sal_False; 392 393 if (p_extensions != NULL) 394 { 395 for (int i = 0; !b_is && i < n_numextensions; i++) 396 b_is = (strcmp (p_extensions[i], "SUN_TSOL") == 0); 397 XFreeExtensionList (p_extensions); 398 } 399 400 return b_is; 401 } 402 403 // -=-= SalDisplay -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 404 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 405 sal_Bool SalDisplay::BestVisual( Display *pDisplay, 406 int nScreen, 407 XVisualInfo &rVI ) 408 { 409 VisualID nDefVID = XVisualIDFromVisual( DefaultVisual( pDisplay, nScreen ) ); 410 VisualID nVID = 0; 411 char *pVID = getenv( "SAL_VISUAL" ); 412 if( pVID ) 413 sscanf( pVID, "%li", &nVID ); 414 415 if( nVID && sal_GetVisualInfo( pDisplay, nVID, rVI ) ) 416 return rVI.visualid == nDefVID; 417 418 XVisualInfo aVI; 419 aVI.screen = nScreen; 420 // get all visuals 421 int nVisuals; 422 XVisualInfo* pVInfos = XGetVisualInfo( pDisplay, VisualScreenMask, 423 &aVI, &nVisuals ); 424 // pVInfos should contain at least one visual, otherwise 425 // we're in trouble 426 int* pWeight = (int*)alloca( sizeof(int)*nVisuals ); 427 int i; 428 for( i = 0; i < nVisuals; i++ ) 429 { 430 sal_Bool bUsable = sal_False; 431 int nTrueColor = 1; 432 433 if ( pVInfos[i].screen != nScreen ) 434 { 435 bUsable = sal_False; 436 } 437 else 438 if( pVInfos[i].c_class == TrueColor ) 439 { 440 nTrueColor = 2048; 441 if( pVInfos[i].depth == 24 ) 442 bUsable = sal_True; 443 #ifdef sal_TrueCOLOR8 444 else if( pVInfos[i].depth == 8 ) 445 { 446 nTrueColor = -1; // strongly discourage 8 bit true color 447 bUsable = sal_True; 448 } 449 #endif 450 #ifdef sal_TrueCOLOR15 451 else if( pVInfos[i].depth == 15 ) 452 bUsable = sal_True; 453 #endif 454 #ifdef sal_TrueCOLOR16 455 else if( pVInfos[i].depth == 16 ) 456 bUsable = sal_True; 457 #endif 458 #ifdef sal_TrueCOLOR32 459 else if( pVInfos[i].depth == 32 ) 460 { 461 nTrueColor = 256; 462 // we do not have use for an alpha channel 463 // better use a 24 or 16 bit truecolor visual if possible 464 bUsable = sal_True; 465 } 466 #endif 467 } 468 else if( pVInfos[i].c_class == PseudoColor ) 469 { 470 if( pVInfos[i].depth <= 8 ) 471 bUsable = sal_True; 472 #ifdef PSEUDOCOLOR12 473 else if( pVInfos[i].depth == 12 ) 474 bUsable = sal_True; 475 #endif 476 } 477 pWeight[ i ] = bUsable ? nTrueColor*pVInfos[i].depth : -1024; 478 pWeight[ i ] -= pVInfos[ i ].visualid; 479 } 480 481 int nBestVisual = 0; 482 int nBestWeight = -1024; 483 for( i = 0; i < nVisuals; i++ ) 484 { 485 if( pWeight[ i ] > nBestWeight ) 486 { 487 nBestWeight = pWeight[ i ]; 488 nBestVisual = i; 489 } 490 } 491 492 rVI = pVInfos[ nBestVisual ]; 493 494 XFree( pVInfos ); 495 return rVI.visualid == nDefVID; 496 } 497 498 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 499 500 SalDisplay::SalDisplay( Display *display ) : 501 mpInputMethod( NULL ), 502 pDisp_( display ), 503 m_pWMAdaptor( NULL ), 504 m_pDtIntegrator( NULL ), 505 m_bUseRandRWrapper( true ), 506 m_nLastUserEventTime( CurrentTime ) 507 { 508 #if OSL_DEBUG_LEVEL > 1 509 fprintf( stderr, "SalDisplay::SalDisplay()\n" ); 510 #endif 511 X11SalData *pSalData = GetX11SalData(); 512 513 DBG_ASSERT( ! pSalData->GetDisplay(), "Second SalDisplay created !!!\n" ); 514 pSalData->SetSalDisplay( this ); 515 516 pXLib_ = pSalData->GetLib(); 517 m_nDefaultScreen = DefaultScreen( pDisp_ ); 518 519 } 520 521 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 522 SalDisplay::~SalDisplay( ) 523 { 524 #if OSL_DEBUG_LEVEL > 1 525 fprintf( stderr, "SalDisplay::~SalDisplay()\n" ); 526 #endif 527 if( pDisp_ ) 528 { 529 doDestruct(); 530 #if OSL_DEBUG_LEVEL > 1 531 fprintf( stderr, "display %p closed\n", pDisp_ ); 532 #endif 533 pDisp_ = NULL; 534 } 535 // don't do this in doDestruct since RandR extension adds hooks into Display 536 // that is XCloseDisplay still needs the RandR library if it was used 537 DeInitRandR(); 538 } 539 540 void SalDisplay::doDestruct() 541 { 542 X11SalData *pSalData = GetX11SalData(); 543 544 delete m_pWMAdaptor; 545 m_pWMAdaptor = NULL; 546 delete m_pDtIntegrator; 547 m_pDtIntegrator = NULL; 548 X11SalBitmap::ImplDestroyCache(); 549 X11SalGraphics::releaseGlyphPeer(); 550 551 if( IsDisplay() ) 552 { 553 delete mpInputMethod, mpInputMethod = (SalI18N_InputMethod*)ILLEGAL_POINTER; 554 delete mpKbdExtension, mpKbdExtension = (SalI18N_KeyboardExtension*)ILLEGAL_POINTER; 555 556 // do not call anything that could implicitly call back into 557 // this object after this point 558 osl_destroyMutex( hEventGuard_ ); 559 560 for( unsigned int i = 0; i < m_aScreens.size(); i++ ) 561 { 562 ScreenData& rData = m_aScreens[i]; 563 if( rData.m_bInit ) 564 { 565 if( rData.m_aMonoGC != rData.m_aCopyGC ) 566 XFreeGC( pDisp_, rData.m_aMonoGC ); 567 XFreeGC( pDisp_, rData.m_aCopyGC ); 568 XFreeGC( pDisp_, rData.m_aAndInvertedGC ); 569 XFreeGC( pDisp_, rData.m_aAndGC ); 570 XFreeGC( pDisp_, rData.m_aOrGC ); 571 XFreeGC( pDisp_, rData.m_aStippleGC ); 572 XFreePixmap( pDisp_, rData.m_hInvert50 ); 573 XDestroyWindow( pDisp_, rData.m_aRefWindow ); 574 Colormap aColMap = rData.m_aColormap.GetXColormap(); 575 if( aColMap != None && aColMap != DefaultColormap( pDisp_, i ) ) 576 XFreeColormap( pDisp_, aColMap ); 577 } 578 } 579 580 hEventGuard_ = (oslMutex)ILLEGAL_POINTER; 581 582 for( size_t i = 0; i < POINTER_COUNT; i++ ) 583 { 584 if( aPointerCache_[i] ) 585 XFreeCursor( pDisp_, aPointerCache_[i] ); 586 } 587 588 pXLib_->Remove( ConnectionNumber( pDisp_ ) ); 589 } 590 591 if( pSalData->GetDisplay() == this ) 592 pSalData->SetSalDisplay( NULL ); 593 } 594 595 static int DisplayHasEvent( int 596 #ifdef DBG_UTIL 597 fd 598 #endif 599 , SalX11Display *pDisplay ) 600 { 601 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, 602 "wrong fd in DisplayHasEvent" ); 603 if( ! pDisplay->IsDisplay() ) 604 return 0; 605 606 vos::IMutex* pSalInstYieldMutex = 607 GetSalData()->m_pInstance->GetYieldMutex(); 608 ::vos::OGuard aGuard( *pSalInstYieldMutex ); 609 return pDisplay->IsEvent(); 610 } 611 static int DisplayQueue( int 612 #ifdef DBG_UTIL 613 fd 614 #endif 615 , SalX11Display *pDisplay ) 616 { 617 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, 618 "wrong fd in DisplayHasEvent" ); 619 vos::IMutex* pSalInstYieldMutex = 620 GetSalData()->m_pInstance->GetYieldMutex(); 621 ::vos::OGuard aGuard( *pSalInstYieldMutex ); 622 return XEventsQueued( pDisplay->GetDisplay(), 623 QueuedAfterReading ); 624 } 625 static int DisplayYield( int 626 #ifdef DBG_UTIL 627 fd 628 #endif 629 , SalX11Display *pDisplay ) 630 { 631 DBG_ASSERT( ConnectionNumber( pDisplay->GetDisplay() ) == fd, 632 "wrong fd in DisplayHasEvent" ); 633 vos::IMutex* pSalInstYieldMutex = 634 GetSalData()->m_pInstance->GetYieldMutex(); 635 ::vos::OGuard aGuard( *pSalInstYieldMutex ); 636 pDisplay->Yield(); 637 return sal_True; 638 } 639 640 SalX11Display::SalX11Display( Display *display ) 641 : SalDisplay( display ) 642 { 643 Init(); 644 645 pXLib_->Insert( ConnectionNumber( pDisp_ ), 646 this, 647 (YieldFunc) DisplayHasEvent, 648 (YieldFunc) DisplayQueue, 649 (YieldFunc) DisplayYield ); 650 } 651 652 SalX11Display::~SalX11Display() 653 { 654 #if OSL_DEBUG_LEVEL > 1 655 fprintf( stderr, "SalX11Display::~SalX11Display()\n" ); 656 #endif 657 if( pDisp_ ) 658 { 659 doDestruct(); 660 XCloseDisplay( pDisp_ ); 661 pDisp_ = NULL; 662 } 663 } 664 665 void SalDisplay::initScreen( int nScreen ) const 666 { 667 if( nScreen < 0 || nScreen >= static_cast<int>(m_aScreens.size()) ) 668 nScreen = m_nDefaultScreen; 669 ScreenData& rSD = const_cast<ScreenData&>(m_aScreens[nScreen]); 670 if( rSD.m_bInit ) 671 return; 672 rSD.m_bInit = true; 673 674 XVisualInfo aVI; 675 Colormap aColMap; 676 677 if( SalDisplay::BestVisual( pDisp_, nScreen, aVI ) ) // DefaultVisual 678 aColMap = DefaultColormap( pDisp_, nScreen ); 679 else 680 aColMap = XCreateColormap( pDisp_, 681 RootWindow( pDisp_, nScreen ), 682 aVI.visual, 683 AllocNone ); 684 685 Screen* pScreen = ScreenOfDisplay( pDisp_, nScreen ); 686 687 rSD.m_aSize = Size( WidthOfScreen( pScreen ), HeightOfScreen( pScreen ) ); 688 rSD.m_aRoot = RootWindow( pDisp_, nScreen ); 689 rSD.m_aVisual = SalVisual( &aVI ); 690 rSD.m_aColormap = SalColormap( this, aColMap, nScreen ); 691 692 // we're interested in configure notification of root windows 693 InitRandR( rSD.m_aRoot ); 694 695 // - - - - - - - - - - Reference Window/Default Drawable - - 696 XSetWindowAttributes aXWAttributes; 697 aXWAttributes.border_pixel = 0; 698 aXWAttributes.background_pixel = 0; 699 aXWAttributes.colormap = aColMap; 700 rSD.m_aRefWindow = XCreateWindow( pDisp_, 701 rSD.m_aRoot, 702 0,0, 16,16, 0, 703 rSD.m_aVisual.GetDepth(), 704 InputOutput, 705 rSD.m_aVisual.GetVisual(), 706 CWBorderPixel|CWBackPixel|CWColormap, 707 &aXWAttributes ); 708 709 // set client leader (session id gets set when session is started) 710 if( rSD.m_aRefWindow ) 711 { 712 // client leader must have WM_CLIENT_LEADER pointing to itself 713 XChangeProperty( pDisp_, 714 rSD.m_aRefWindow, 715 XInternAtom( pDisp_, "WM_CLIENT_LEADER", False ), 716 XA_WINDOW, 717 32, 718 PropModeReplace, 719 (unsigned char*)&rSD.m_aRefWindow, 720 1 721 ); 722 723 ByteString aExec( SessionManagerClient::getExecName(), osl_getThreadTextEncoding() ); 724 const char* argv[2]; 725 argv[0] = "/bin/sh"; 726 argv[1] = aExec.GetBuffer(); 727 XSetCommand( pDisp_, rSD.m_aRefWindow, const_cast<char**>(argv), 2 ); 728 XSelectInput( pDisp_, rSD.m_aRefWindow, PropertyChangeMask ); 729 730 // - - - - - - - - - - GCs - - - - - - - - - - - - - - - - - 731 XGCValues values; 732 values.graphics_exposures = False; 733 values.fill_style = FillOpaqueStippled; 734 values.background = (1<<rSD.m_aVisual.GetDepth())-1; 735 values.foreground = 0; 736 737 rSD.m_aCopyGC = XCreateGC( pDisp_, 738 rSD.m_aRefWindow, 739 GCGraphicsExposures 740 | GCForeground 741 | GCBackground, 742 &values ); 743 rSD.m_aAndInvertedGC= XCreateGC( pDisp_, 744 rSD.m_aRefWindow, 745 GCGraphicsExposures 746 | GCForeground 747 | GCBackground, 748 &values ); 749 rSD.m_aAndGC = XCreateGC( pDisp_, 750 rSD.m_aRefWindow, 751 GCGraphicsExposures 752 | GCForeground 753 | GCBackground, 754 &values ); 755 rSD.m_aOrGC = XCreateGC( pDisp_, 756 rSD.m_aRefWindow, 757 GCGraphicsExposures 758 | GCForeground 759 | GCBackground, 760 &values ); 761 rSD.m_aStippleGC = XCreateGC( pDisp_, 762 rSD.m_aRefWindow, 763 GCGraphicsExposures 764 | GCFillStyle 765 | GCForeground 766 | GCBackground, 767 &values ); 768 769 XSetFunction( pDisp_, rSD.m_aAndInvertedGC, GXandInverted ); 770 XSetFunction( pDisp_, rSD.m_aAndGC, GXand ); 771 // #44556# PowerPC Solaris 2.5 (XSun 3500) Bug: GXor = GXnop 772 //XSetFunction( pDisp_, pOrGC_, GXor ); 773 XSetFunction( pDisp_, rSD.m_aOrGC, GXxor ); 774 775 if( 1 == rSD.m_aVisual.GetDepth() ) 776 { 777 XSetFunction( pDisp_, rSD.m_aCopyGC, GXcopyInverted ); 778 rSD.m_aMonoGC = rSD.m_aCopyGC; 779 } 780 else 781 { 782 Pixmap hPixmap = XCreatePixmap( pDisp_, rSD.m_aRefWindow, 1, 1, 1 ); 783 rSD.m_aMonoGC = XCreateGC( pDisp_, 784 hPixmap, 785 GCGraphicsExposures, 786 &values ); 787 XFreePixmap( pDisp_, hPixmap ); 788 } 789 rSD.m_hInvert50 = XCreateBitmapFromData( pDisp_, 790 rSD.m_aRefWindow, 791 (const char*)invert50_bits, 792 invert50_width, 793 invert50_height ); 794 } 795 } 796 797 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 798 void SalDisplay::Init() 799 { 800 for( size_t i = 0; i < POINTER_COUNT; i++ ) 801 aPointerCache_[i] = None; 802 803 eWindowManager_ = otherwm; 804 nProperties_ = PROPERTY_DEFAULT; 805 hEventGuard_ = NULL; 806 mpFactory = (AttributeProvider*)NULL; 807 m_pCapture = NULL; 808 m_bXinerama = false; 809 810 int nDisplayScreens = ScreenCount( pDisp_ ); 811 m_aScreens = std::vector<ScreenData>(nDisplayScreens); 812 813 mbExactResolution = false; 814 /* #i15507# 815 * Xft resolution should take precedence since 816 * it is what modern desktops use. 817 */ 818 const char* pValStr = XGetDefault( pDisp_, "Xft", "dpi" ); 819 if( pValStr != NULL ) 820 { 821 const rtl::OString aValStr( pValStr ); 822 const long nDPI = (long) aValStr.toDouble(); 823 // guard against insane resolution 824 if( (nDPI >= 50) && (nDPI <= 500) ) 825 { 826 aResolution_ = Pair( nDPI, nDPI ); 827 mbExactResolution = true; 828 } 829 } 830 if( mbExactResolution == false ) 831 { 832 aResolution_ = 833 Pair( DPI( WidthOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayWidthMM ( pDisp_, m_nDefaultScreen ) ), 834 DPI( HeightOfScreen( DefaultScreenOfDisplay( pDisp_ ) ), DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) ); 835 } 836 837 nMaxRequestSize_ = XExtendedMaxRequestSize( pDisp_ ) * 4; 838 if( !nMaxRequestSize_ ) 839 nMaxRequestSize_ = XMaxRequestSize( pDisp_ ) * 4; 840 841 SetServerVendor(); 842 X11SalBitmap::ImplCreateCache(); 843 844 hEventGuard_ = osl_createMutex(); 845 bLocal_ = sal_False; /* dont care, initialize later by 846 calling SalDisplay::IsLocal() */ 847 mbLocalIsValid = sal_False; /* bLocal_ is not yet initialized */ 848 849 // - - - - - - - - - - Synchronize - - - - - - - - - - - - - 850 if( getenv( "SAL_SYNCHRONIZE" ) ) 851 XSynchronize( pDisp_, True ); 852 853 // - - - - - - - - - - Keyboardmapping - - - - - - - - - - - 854 ModifierMapping(); 855 856 // - - - - - - - - - - Window Manager - - - - - - - - - - - 857 m_pWMAdaptor = ::vcl_sal::WMAdaptor::createWMAdaptor( this ); 858 const char *pWM = getenv( "SAL_WM" ); 859 if( pWM ) 860 { 861 long int nWM = 0; 862 sscanf( pWM, "%li", &nWM ); 863 eWindowManager_ = SalWM(nWM); 864 } 865 else if( XInternAtom( pDisp_, "_SGI_TELL_WM", True ) ) 866 eWindowManager_ = FourDwm; 867 else if( XInternAtom( pDisp_, "KWM_RUNNING", True ) ) 868 eWindowManager_ = mwm; // naja, eigentlich kwm ... 869 else if( XInternAtom( pDisp_, "_OL_WIN_ATTR", True ) ) 870 eWindowManager_ = olwm; 871 else if( m_pWMAdaptor->getWindowManagerName().EqualsAscii( "Dtwm" ) ) 872 eWindowManager_ = dtwm; 873 874 // - - - - - - - - - - Properties - - - - - - - - - - - - - 875 const char *pProperties = getenv( "SAL_PROPERTIES" ); 876 if( pProperties ) 877 sscanf( pProperties, "%li", &nProperties_ ); 878 else 879 { 880 #if defined DBG_UTIL || defined SUN || defined LINUX || defined FREEBSD 881 nProperties_ |= PROPERTY_FEATURE_Maximize; 882 #endif 883 // Server Bugs & Properties 884 if( GetServerVendor() == vendor_excursion ) 885 { 886 nProperties_ |= PROPERTY_BUG_Stipple; 887 nProperties_ |= PROPERTY_BUG_DrawLine; 888 nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; 889 } 890 else 891 if( GetServerVendor() == vendor_attachmate ) 892 { 893 nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel; 894 } 895 else 896 if( GetServerVendor() == vendor_ibm ) 897 { 898 nProperties_ |= PROPERTY_BUG_XA_FAMILY_NAME_nil; 899 900 if( otherwm == eWindowManager_ ) eWindowManager_ = mwm; 901 } 902 else 903 if( GetServerVendor() == vendor_xfree ) 904 { 905 nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor; 906 #if defined LINUX || defined FREEBSD 907 // otherwm and olwm are a kind of default, which are not detected 908 // carefully. if we are running linux (i.e. not netbsd) on an xfree 909 // display, fvwm is most probable the wm to choose, confusing with mwm 910 // doesn't harm. #57791# start maximized if possible 911 if( (otherwm == eWindowManager_) 912 || (olwm == eWindowManager_ )) 913 { 914 eWindowManager_ = fvwm; // ??? 915 nProperties_ |= PROPERTY_FEATURE_Maximize; 916 } 917 #else 918 if( otherwm == eWindowManager_ ) eWindowManager_ = winmgr; 919 #endif 920 #if defined SOLARIS && defined SPARC 921 nProperties_ |= PROPERTY_BUG_Bitmap_Bit_Order; 922 // solaris xlib seems to have problems with putting images 923 // in correct bit order to xfree 8 bit displays 924 #endif 925 } 926 else 927 if( GetServerVendor() == vendor_sun ) 928 { 929 // nicht alle! (bekannt: nur Sparc II CG3, CG6?) 930 nProperties_ &= ~PROPERTY_SUPPORT_XSetClipMask; 931 932 // trusted solaris doesn't allow to change properties on the 933 // wm decoration window 934 if (sal_IsTrustedSolaris (pDisp_)) 935 nProperties_ |= PROPERTY_FEATURE_TrustedSolaris; 936 937 // Fehler im Sun-Solaris X86 Server ! 938 if (ImageByteOrder(GetDisplay()) == LSBFirst) 939 { 940 nProperties_ |= PROPERTY_BUG_Tile; 941 nProperties_ |= PROPERTY_SUPPORT_3ButtonMouse; 942 } 943 else // MSBFirst Sun-Solaris Sparc Server 944 { 945 // XCopyPlane reverts black and white for 1bit bitmaps 946 // only sun, only 8bit pseudocolor target 947 if ( (GetVisual(m_nDefaultScreen).GetDepth() == 8) 948 && (GetVisual(m_nDefaultScreen).GetClass() == PseudoColor)) 949 nProperties_ |= PROPERTY_BUG_CopyPlane_RevertBWPixel; 950 // Fehler in Solaris 2.5.1 951 if (VendorRelease ( GetDisplay() ) < 3600) 952 nProperties_ |= PROPERTY_BUG_FillPolygon_Tile; 953 } 954 955 if( otherwm == eWindowManager_ ) 956 eWindowManager_ = olwm; 957 } 958 else 959 if( GetServerVendor() == vendor_sco ) 960 { 961 if( otherwm == eWindowManager_ ) eWindowManager_ = pmwm; 962 } 963 else 964 if( GetServerVendor() == vendor_sgi ) 965 { 966 if( GetVisual( m_nDefaultScreen ).GetDepth() > 8 && GetVisual( m_nDefaultScreen ).GetDepth() <= 16 ) 967 nProperties_ |= PROPERTY_BUG_XCopyArea_GXxor; 968 nProperties_ |= PROPERTY_SUPPORT_XSetClipMask; 969 970 if( otherwm == eWindowManager_ ) 971 eWindowManager_ = FourDwm; 972 } 973 else 974 if( GetServerVendor() == vendor_hp ) 975 { 976 if( otherwm == eWindowManager_ ) eWindowManager_ = dtwm; 977 } 978 else 979 if( GetServerVendor() == vendor_hummingbird ) 980 { 981 if (GetVisual(m_nDefaultScreen).GetDepth() == 24) 982 nProperties_ |= PROPERTY_BUG_CopyArea_OnlySmallSlices; 983 } 984 985 if( otherwm == eWindowManager_ ) 986 { 987 if( !XInternAtom( pDisp_, "_MOTIF_WM_INFO", True ) ) 988 eWindowManager_ = olwm; 989 // ??? 990 } 991 992 if( winmgr == eWindowManager_ ) 993 { 994 nProperties_ &= ~PROPERTY_SUPPORT_WM_SetPos; 995 nProperties_ &= ~PROPERTY_SUPPORT_WM_Screen; 996 nProperties_ |= PROPERTY_FEATURE_Maximize; 997 } 998 else if( dtwm == eWindowManager_ ) 999 { 1000 nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos; 1001 } 1002 else if( pmwm == eWindowManager_ ) 1003 { 1004 nProperties_ &= ~PROPERTY_SUPPORT_WM_ClientPos; 1005 } 1006 } 1007 1008 InitXinerama(); 1009 1010 // initialize system settings update 1011 m_pDtIntegrator = DtIntegrator::CreateDtIntegrator(); 1012 1013 #ifdef DBG_UTIL 1014 PrintInfo(); 1015 #endif 1016 } 1017 1018 // Sound 1019 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1020 void SalDisplay::Beep() const 1021 { 1022 XBell( pDisp_, 0 ); 1023 } 1024 1025 // Keyboard 1026 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1027 String SalDisplay::GetKeyNameFromKeySym( KeySym nKeySym ) const 1028 { 1029 String aRet; 1030 1031 // return an empty string for keysyms that are not bound to 1032 // any key code 1033 XLIB_KeyCode aKeyCode = XKeysymToKeycode( GetDisplay(), nKeySym ); 1034 if( aKeyCode != 0 && aKeyCode != NoSymbol ) 1035 { 1036 if( !nKeySym ) 1037 aRet = String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "???" ) ); 1038 else 1039 { 1040 aRet = ::vcl_sal::getKeysymReplacementName( const_cast<SalDisplay*>(this)->GetKeyboardName(), nKeySym ); 1041 if( ! aRet.Len() ) 1042 { 1043 const char *pString = XKeysymToString( nKeySym ); 1044 int n = strlen( pString ); 1045 if( n > 2 && pString[n-2] == '_' ) 1046 aRet = String( pString, n-2, RTL_TEXTENCODING_ISO_8859_1 ); 1047 else 1048 aRet = String( pString, n, RTL_TEXTENCODING_ISO_8859_1 ); 1049 } 1050 } 1051 } 1052 return aRet; 1053 } 1054 1055 inline KeySym sal_XModifier2Keysym( Display *pDisplay, 1056 XModifierKeymap *pXModMap, 1057 int n ) 1058 { 1059 return XkbKeycodeToKeysym( pDisplay, 1060 pXModMap->modifiermap[n*pXModMap->max_keypermod], 1061 0, 0 ); 1062 } 1063 1064 void SalDisplay::ModifierMapping() 1065 { 1066 XModifierKeymap *pXModMap = XGetModifierMapping( pDisp_ ); 1067 1068 bNumLockFromXS_ = True; 1069 nShiftKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ShiftMapIndex ); 1070 nCtrlKeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, ControlMapIndex ); 1071 nMod1KeySym_ = sal_XModifier2Keysym( pDisp_, pXModMap, Mod1MapIndex ); 1072 // Auf Sun-Servern und SCO-Severn beruecksichtigt XLookupString 1073 // nicht den NumLock Modifier. 1074 if( (GetServerVendor() == vendor_sun) 1075 || (GetServerVendor() == vendor_sco) ) 1076 { 1077 XLIB_KeyCode aNumLock = XKeysymToKeycode( pDisp_, XK_Num_Lock ); 1078 1079 if( aNumLock ) for( int i = ShiftMapIndex; i <= Mod5MapIndex; i++ ) 1080 { 1081 if( pXModMap->modifiermap[i*pXModMap->max_keypermod] == aNumLock ) 1082 { 1083 bNumLockFromXS_ = False; 1084 nNumLockIndex_ = i; 1085 nNumLockMask_ = 1<<i; 1086 break; 1087 } 1088 } 1089 } 1090 1091 XFreeModifiermap( pXModMap ); 1092 } 1093 1094 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1095 XubString SalDisplay::GetKeyName( sal_uInt16 nKeyCode ) const 1096 { 1097 String aStrMap; 1098 1099 if( nKeyCode & KEY_MOD1 ) 1100 aStrMap += GetKeyNameFromKeySym( nCtrlKeySym_ ); 1101 1102 if( nKeyCode & KEY_MOD2 ) 1103 { 1104 if( aStrMap.Len() ) 1105 aStrMap += '+'; 1106 aStrMap += GetKeyNameFromKeySym( nMod1KeySym_ ); 1107 } 1108 1109 if( nKeyCode & KEY_SHIFT ) 1110 { 1111 if( aStrMap.Len() ) 1112 aStrMap += '+'; 1113 aStrMap += GetKeyNameFromKeySym( nShiftKeySym_ ); 1114 } 1115 nKeyCode &= 0x0FFF; 1116 1117 KeySym nKeySym = 0; 1118 1119 if( KEY_0 <= nKeyCode && nKeyCode <= KEY_9 ) 1120 nKeySym = XK_0 + (nKeyCode - KEY_0); 1121 else if( KEY_A <= nKeyCode && nKeyCode <= KEY_Z ) 1122 nKeySym = XK_A + (nKeyCode - KEY_A); 1123 else if( KEY_F1 <= nKeyCode && nKeyCode <= KEY_F26 ) // Existiert die Taste 1124 nKeySym = XK_F1 + (nKeyCode - KEY_F1); 1125 else switch( nKeyCode ) 1126 { 1127 case KEY_DOWN: 1128 nKeySym = XK_Down; 1129 break; 1130 case KEY_UP: 1131 nKeySym = XK_Up; 1132 break; 1133 case KEY_LEFT: 1134 nKeySym = XK_Left; 1135 break; 1136 case KEY_RIGHT: 1137 nKeySym = XK_Right; 1138 break; 1139 case KEY_HOME: 1140 nKeySym = XK_Home; 1141 break; 1142 case KEY_END: 1143 nKeySym = XK_End; 1144 break; 1145 case KEY_PAGEUP: 1146 nKeySym = XK_Prior; 1147 break; 1148 case KEY_PAGEDOWN: 1149 nKeySym = XK_Next; 1150 break; 1151 case KEY_RETURN: 1152 nKeySym = XK_Return; 1153 break; 1154 case KEY_ESCAPE: 1155 nKeySym = XK_Escape; 1156 break; 1157 case KEY_TAB: 1158 nKeySym = XK_Tab; 1159 break; 1160 case KEY_BACKSPACE: 1161 nKeySym = XK_BackSpace; 1162 break; 1163 case KEY_SPACE: 1164 nKeySym = XK_space; 1165 break; 1166 case KEY_INSERT: 1167 nKeySym = XK_Insert; 1168 break; 1169 case KEY_DELETE: 1170 nKeySym = XK_Delete; 1171 break; 1172 1173 #if !defined (SunXK_Undo) 1174 #define SunXK_Stop 0x0000FF69 // XK_Cancel 1175 #define SunXK_Props 0x1005FF70 1176 #define SunXK_Front 0x1005FF71 1177 #define SunXK_Copy 0x1005FF72 1178 #define SunXK_Open 0x1005FF73 1179 #define SunXK_Paste 0x1005FF74 1180 #define SunXK_Cut 0x1005FF75 1181 #endif 1182 1183 case KEY_REPEAT: 1184 nKeySym = XK_Redo; 1185 break; 1186 case KEY_PROPERTIES: 1187 nKeySym = SunXK_Props; 1188 break; 1189 case KEY_UNDO: 1190 nKeySym = XK_Undo; 1191 break; 1192 case KEY_FRONT: 1193 nKeySym = SunXK_Front; 1194 break; 1195 case KEY_COPY: 1196 nKeySym = SunXK_Copy; 1197 break; 1198 case KEY_OPEN: 1199 nKeySym = SunXK_Open; 1200 break; 1201 case KEY_PASTE: 1202 nKeySym = SunXK_Paste; 1203 break; 1204 case KEY_FIND: 1205 nKeySym = XK_Find; 1206 break; 1207 case KEY_CUT: 1208 nKeySym = GetServerVendor() == vendor_sun ? SunXK_Cut : XK_L10; 1209 break; 1210 case KEY_ADD: 1211 nKeySym = XK_plus; 1212 break; 1213 case KEY_SUBTRACT: 1214 nKeySym = XK_minus; 1215 break; 1216 case KEY_MULTIPLY: 1217 nKeySym = XK_asterisk; 1218 break; 1219 case KEY_DIVIDE: 1220 nKeySym = XK_slash; 1221 break; 1222 case KEY_POINT: 1223 nKeySym = XK_period; 1224 break; 1225 case KEY_COMMA: 1226 nKeySym = XK_comma; 1227 break; 1228 case KEY_LESS: 1229 nKeySym = XK_less; 1230 break; 1231 case KEY_GREATER: 1232 nKeySym = XK_greater; 1233 break; 1234 case KEY_EQUAL: 1235 nKeySym = XK_equal; 1236 break; 1237 case KEY_HELP: 1238 nKeySym = XK_Help; 1239 break; 1240 case KEY_HANGUL_HANJA: 1241 nKeySym = XK_Hangul_Hanja; 1242 break; 1243 case KEY_TILDE: 1244 nKeySym = XK_asciitilde; 1245 break; 1246 case KEY_QUOTELEFT: 1247 nKeySym = XK_grave; 1248 break; 1249 1250 default: 1251 nKeySym = 0; 1252 break; 1253 } 1254 1255 if( nKeySym ) 1256 { 1257 String aKeyName = GetKeyNameFromKeySym( nKeySym ); 1258 if( aKeyName.Len() ) 1259 { 1260 if( aStrMap.Len() ) 1261 aStrMap += '+'; 1262 aStrMap += aKeyName; 1263 } 1264 else 1265 aStrMap.Erase(); 1266 } 1267 else 1268 aStrMap.Erase(); 1269 1270 return aStrMap; 1271 } 1272 1273 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1274 #ifndef IsISOKey 1275 #define IsISOKey( n ) (0x0000FE00==((n)&0xFFFFFF00)) 1276 #endif 1277 1278 sal_uInt16 SalDisplay::GetKeyCode( KeySym keysym, char*pcPrintable ) const 1279 { 1280 sal_uInt16 nKey = 0; 1281 1282 if( XK_a <= keysym && XK_z >= keysym ) 1283 nKey = (sal_uInt16)(KEY_A + (keysym - XK_a)); 1284 else if( XK_A <= keysym && XK_Z >= keysym ) 1285 nKey = (sal_uInt16)(KEY_A + (keysym - XK_A)); 1286 else if( XK_0 <= keysym && XK_9 >= keysym ) 1287 nKey = (sal_uInt16)(KEY_0 + (keysym - XK_0)); 1288 else if( IsModifierKey( keysym ) ) 1289 ; 1290 else if( IsKeypadKey( keysym ) ) 1291 { 1292 if( (keysym >= XK_KP_0) && (keysym <= XK_KP_9) ) 1293 { 1294 nKey = (sal_uInt16)(KEY_0 + (keysym - XK_KP_0)); 1295 *pcPrintable = '0' + nKey - KEY_0; 1296 } 1297 else if( IsPFKey( keysym ) ) 1298 nKey = (sal_uInt16)(KEY_F1 + (keysym - XK_KP_F1)); 1299 else switch( keysym ) 1300 { 1301 case XK_KP_Space: 1302 nKey = KEY_SPACE; 1303 *pcPrintable = ' '; 1304 break; 1305 case XK_KP_Tab: 1306 nKey = KEY_TAB; 1307 break; 1308 case XK_KP_Enter: 1309 nKey = KEY_RETURN; 1310 break; 1311 case XK_KP_Begin: 1312 case XK_KP_Home: 1313 nKey = KEY_HOME; 1314 break; 1315 case XK_KP_Left: 1316 nKey = KEY_LEFT; 1317 break; 1318 case XK_KP_Up: 1319 nKey = KEY_UP; 1320 break; 1321 case XK_KP_Right: 1322 nKey = KEY_RIGHT; 1323 break; 1324 case XK_KP_Down: 1325 nKey = KEY_DOWN; 1326 break; 1327 case XK_KP_Prior: // XK_KP_Page_Up 1328 nKey = KEY_PAGEUP; 1329 break; 1330 case XK_KP_Next: // XK_KP_Page_Down 1331 nKey = KEY_PAGEDOWN; 1332 break; 1333 case XK_KP_End: 1334 nKey = KEY_END; 1335 break; 1336 case XK_KP_Insert: 1337 nKey = KEY_INSERT; 1338 break; 1339 case XK_KP_Delete: 1340 nKey = KEY_DELETE; 1341 break; 1342 case XK_KP_Equal: 1343 nKey = KEY_EQUAL; 1344 *pcPrintable = '='; 1345 break; 1346 case XK_KP_Multiply: 1347 nKey = KEY_MULTIPLY; 1348 *pcPrintable = '*'; 1349 break; 1350 case XK_KP_Add: 1351 nKey = KEY_ADD; 1352 *pcPrintable = '+'; 1353 break; 1354 case XK_KP_Separator: 1355 nKey = KEY_DECIMAL; 1356 *pcPrintable = ','; 1357 break; 1358 case XK_KP_Subtract: 1359 nKey = KEY_SUBTRACT; 1360 *pcPrintable = '-'; 1361 break; 1362 case XK_KP_Decimal: 1363 nKey = KEY_DECIMAL; 1364 *pcPrintable = '.'; 1365 break; 1366 case XK_KP_Divide: 1367 nKey = KEY_DIVIDE; 1368 *pcPrintable = '/'; 1369 break; 1370 } 1371 } 1372 else if( IsFunctionKey( keysym ) ) 1373 { 1374 if( bNumLockFromXS_ ) 1375 { 1376 if( keysym >= XK_F1 && keysym <= XK_F26 ) 1377 nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1); 1378 } 1379 else switch( keysym ) 1380 { 1381 // - - - - - Sun X-Server Tastatur ohne Cursorblock ??? - - - 1382 case XK_R7: // XK_F27: 1383 nKey = KEY_HOME; 1384 break; 1385 case XK_R8: // XK_F28: 1386 nKey = KEY_UP; 1387 break; 1388 case XK_R9: // XK_F29: 1389 nKey = KEY_PAGEUP; 1390 break; 1391 case XK_R10: // XK_F30: 1392 nKey = KEY_LEFT; 1393 break; 1394 case XK_R11: // XK_F31: 1395 nKey = 0; // KEY_F31 1396 break; 1397 case XK_R12: // XK_F32: 1398 nKey = KEY_RIGHT; 1399 break; 1400 case XK_R13: // XK_F33: 1401 nKey = KEY_END; 1402 break; 1403 case XK_R14: // XK_F34: 1404 nKey = KEY_DOWN; 1405 break; 1406 case XK_R15: // XK_F35: 1407 nKey = KEY_PAGEDOWN; 1408 break; 1409 // - - - - - Sun X-Server Tastatur ??? - - - - - - - - - - - - 1410 case XK_L1: // XK_F11: 1411 nKey = KEY_F11; // on a sun keyboard this actually is usally SunXK_Stop, 1412 // but VCL doesn't have a key defintion for that 1413 break; 1414 case XK_L2: // XK_F12: 1415 if ( GetServerVendor() == vendor_sun ) 1416 nKey = KEY_REPEAT; 1417 else 1418 nKey = KEY_F12; 1419 break; 1420 case XK_L3: // XK_F13: 1421 nKey = KEY_PROPERTIES; // KEY_F13 1422 break; 1423 case XK_L4: // XK_F14: 1424 nKey = KEY_UNDO; // KEY_F14 1425 break; 1426 case XK_L5: // XK_F15: 1427 nKey = KEY_F15; // KEY_FRONT 1428 break; 1429 case XK_L6: // XK_F16: 1430 nKey = KEY_COPY; // KEY_F16 1431 break; 1432 case XK_L7: // XK_F17: 1433 nKey = KEY_F17; // KEY_OPEN 1434 break; 1435 case XK_L8: // XK_F18: 1436 nKey = KEY_PASTE; // KEY_F18 1437 break; 1438 case XK_L9: // XK_F19: 1439 nKey = KEY_F19; // KEY_FIND 1440 break; 1441 case XK_L10: // XK_F20: 1442 nKey = KEY_CUT; // KEY_F20 1443 break; 1444 default: 1445 if( keysym >= XK_F1 && keysym <= XK_F26 ) 1446 nKey = (sal_uInt16)(KEY_F1 + keysym - XK_F1); 1447 break; 1448 } 1449 } 1450 else if( IsCursorKey( keysym ) ) 1451 { 1452 switch( keysym ) 1453 { 1454 case XK_Begin: 1455 case XK_Home: 1456 nKey = KEY_HOME; 1457 break; 1458 case XK_Left: 1459 nKey = KEY_LEFT; 1460 break; 1461 case XK_Up: 1462 nKey = KEY_UP; 1463 break; 1464 case XK_Right: 1465 nKey = KEY_RIGHT; 1466 break; 1467 case XK_Down: 1468 nKey = KEY_DOWN; 1469 break; 1470 case XK_Prior: // XK_Page_Up 1471 nKey = KEY_PAGEUP; 1472 break; 1473 case XK_Next: // XK_Page_Down 1474 nKey = KEY_PAGEDOWN; 1475 break; 1476 case XK_End: 1477 nKey = KEY_END; 1478 break; 1479 } 1480 } 1481 else if( IsMiscFunctionKey( keysym ) ) 1482 { 1483 switch( keysym ) 1484 { 1485 case XK_Insert: 1486 nKey = KEY_INSERT; 1487 break; 1488 case XK_Redo: 1489 nKey = KEY_REPEAT; 1490 break; 1491 case XK_Undo: 1492 nKey = KEY_UNDO; 1493 break; 1494 case XK_Find: 1495 nKey = KEY_FIND; 1496 break; 1497 case XK_Help: 1498 nKey = KEY_HELP; 1499 break; 1500 case XK_Menu: 1501 nKey = KEY_CONTEXTMENU; 1502 break; 1503 /* 1504 case XK_Break: 1505 case XK_Select: 1506 case XK_Execute: 1507 case XK_Print: 1508 case XK_Cancel: 1509 */ 1510 } 1511 } 1512 else if( IsISOKey( keysym ) ) // XK_ISO_ 1513 { 1514 switch( keysym ) 1515 { 1516 case 0xFE20: // XK_ISO_Left_Tab: 1517 nKey = KEY_TAB; 1518 break; 1519 } 1520 } 1521 else switch( keysym ) 1522 { 1523 case XK_Return: 1524 nKey = KEY_RETURN; 1525 break; 1526 case XK_BackSpace: 1527 nKey = KEY_BACKSPACE; 1528 break; 1529 case XK_Delete: 1530 nKey = KEY_DELETE; 1531 break; 1532 case XK_space: 1533 nKey = KEY_SPACE; 1534 break; 1535 case XK_Tab: 1536 nKey = KEY_TAB; 1537 break; 1538 case XK_Escape: 1539 nKey = KEY_ESCAPE; 1540 break; 1541 case XK_plus: 1542 nKey = KEY_ADD; 1543 break; 1544 case XK_minus: 1545 nKey = KEY_SUBTRACT; 1546 break; 1547 case XK_asterisk: 1548 nKey = KEY_MULTIPLY; 1549 break; 1550 case XK_slash: 1551 nKey = KEY_DIVIDE; 1552 break; 1553 case XK_period: 1554 nKey = KEY_POINT; 1555 break; 1556 case XK_comma: 1557 nKey = KEY_COMMA; 1558 break; 1559 case XK_less: 1560 nKey = KEY_LESS; 1561 break; 1562 case XK_greater: 1563 nKey = KEY_GREATER; 1564 break; 1565 case XK_equal: 1566 nKey = KEY_EQUAL; 1567 break; 1568 case XK_Hangul_Hanja: 1569 nKey = KEY_HANGUL_HANJA; 1570 break; 1571 case XK_asciitilde: 1572 nKey = KEY_TILDE; 1573 *pcPrintable = '~'; 1574 break; 1575 case XK_grave: 1576 nKey = KEY_QUOTELEFT; 1577 *pcPrintable = '`'; 1578 break; 1579 // case XK_Linefeed: 1580 // *pcPrintable = '\n'; 1581 // break; 1582 // - - - - - - - - - - - - - Apollo - - - - - - - - - - - - - 0x1000 1583 case 0x1000FF02: // apXK_Copy 1584 nKey = KEY_COPY; 1585 break; 1586 case 0x1000FF03: // apXK_Cut 1587 nKey = KEY_CUT; 1588 break; 1589 case 0x1000FF04: // apXK_Paste 1590 nKey = KEY_PASTE; 1591 break; 1592 case 0x1000FF14: // apXK_Repeat 1593 nKey = KEY_REPEAT; 1594 break; 1595 // Exit, Save 1596 // - - - - - - - - - - - - - - D E C - - - - - - - - - - - - - 0x1000 1597 case 0x1000FF00: 1598 nKey = KEY_DELETE; 1599 break; 1600 // - - - - - - - - - - - - - - H P - - - - - - - - - - - - - 0x1000 1601 case 0x1000FF73: // hpXK_DeleteChar 1602 nKey = KEY_DELETE; 1603 break; 1604 case 0x1000FF74: // hpXK_BackTab 1605 case 0x1000FF75: // hpXK_KP_BackTab 1606 nKey = KEY_TAB; 1607 break; 1608 // - - - - - - - - - - - - - - I B M - - - - - - - - - - - - - 1609 // - - - - - - - - - - - - - - O S F - - - - - - - - - - - - - 0x1004 1610 case 0x1004FF02: // osfXK_Copy 1611 nKey = KEY_COPY; 1612 break; 1613 case 0x1004FF03: // osfXK_Cut 1614 nKey = KEY_CUT; 1615 break; 1616 case 0x1004FF04: // osfXK_Paste 1617 nKey = KEY_PASTE; 1618 break; 1619 case 0x1004FF07: // osfXK_BackTab 1620 nKey = KEY_TAB; 1621 break; 1622 case 0x1004FF08: // osfXK_BackSpace 1623 nKey = KEY_BACKSPACE; 1624 break; 1625 case 0x1004FF1B: // osfXK_Escape 1626 nKey = KEY_ESCAPE; 1627 break; 1628 // Up, Down, Left, Right, PageUp, PageDown 1629 // - - - - - - - - - - - - - - S C O - - - - - - - - - - - - - 1630 // - - - - - - - - - - - - - - S G I - - - - - - - - - - - - - 0x1007 1631 // - - - - - - - - - - - - - - S N I - - - - - - - - - - - - - 1632 // - - - - - - - - - - - - - - S U N - - - - - - - - - - - - - 0x1005 1633 case 0x1005FF10: // SunXK_F36 1634 nKey = KEY_F11; 1635 break; 1636 case 0x1005FF11: // SunXK_F37 1637 nKey = KEY_F12; 1638 break; 1639 case 0x1005FF70: // SunXK_Props 1640 nKey = KEY_PROPERTIES; 1641 break; 1642 case 0x1005FF71: // SunXK_Front 1643 nKey = KEY_FRONT; 1644 break; 1645 case 0x1005FF72: // SunXK_Copy 1646 nKey = KEY_COPY; 1647 break; 1648 case 0x1005FF73: // SunXK_Open 1649 nKey = KEY_OPEN; 1650 break; 1651 case 0x1005FF74: // SunXK_Paste 1652 nKey = KEY_PASTE; 1653 break; 1654 case 0x1005FF75: // SunXK_Cut 1655 nKey = KEY_CUT; 1656 break; 1657 } 1658 return nKey; 1659 } 1660 1661 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1662 KeySym SalDisplay::GetKeySym( XKeyEvent *pEvent, 1663 unsigned char *pPrintable, 1664 int *pLen, 1665 KeySym *pUnmodifiedKeySym, 1666 Status *pStatusReturn, 1667 XIC aInputContext ) const 1668 { 1669 KeySym nKeySym = 0; 1670 memset( pPrintable, 0, *pLen ); 1671 *pStatusReturn = 0; 1672 1673 // first get the printable of the possibly modified KeySym 1674 if ( (aInputContext == 0) 1675 || (pEvent->type == KeyRelease) 1676 || (mpInputMethod != NULL && mpInputMethod->PosixLocale()) ) 1677 { 1678 // XmbLookupString must not be called for KeyRelease events 1679 // Cannot enter space in c locale problem #89616# #88978# btraq #4478197 1680 *pLen = XLookupString( pEvent, (char*)pPrintable, 1, &nKeySym, NULL ); 1681 } 1682 else 1683 { 1684 *pLen = XmbLookupString( aInputContext, 1685 pEvent, (char*)pPrintable, *pLen - 1, &nKeySym, pStatusReturn ); 1686 1687 // Lookup the string again, now with appropriate size 1688 if ( *pStatusReturn == XBufferOverflow ) 1689 { 1690 pPrintable[ 0 ] = (char)0; 1691 return 0; 1692 } 1693 1694 switch ( *pStatusReturn ) 1695 { 1696 case XBufferOverflow: 1697 /* unhandled error */ 1698 break; 1699 case XLookupNone: 1700 /* unhandled error */ 1701 break; 1702 case XLookupKeySym: 1703 /* #72223# this is a strange one: on exceed sometimes 1704 * no printable is returned for the first char entered, 1705 * just to retry lookup solves the problem. The problem 1706 * is not yet fully understood, so restrict 2nd lookup 1707 * to 7bit ascii chars */ 1708 if ( (XK_space <= nKeySym) && (XK_asciitilde >= nKeySym) ) 1709 { 1710 *pLen = 1; 1711 pPrintable[ 0 ] = (char)nKeySym; 1712 } 1713 break; 1714 case XLookupBoth: 1715 case XLookupChars: 1716 1717 /* nothing to, char allready in pPrintable */ 1718 break; 1719 } 1720 } 1721 1722 if( !bNumLockFromXS_ 1723 && (IsCursorKey(nKeySym) 1724 || IsFunctionKey(nKeySym) 1725 || IsKeypadKey(nKeySym) 1726 || XK_Delete == nKeySym ) ) 1727 { 1728 // Bei einigen X-Servern muss man bei den Keypadtasten 1729 // schon sehr genau hinschauen. ZB. Solaris XServer: 1730 // 2, 4, 6, 8 werden als Cursorkeys klassifiziert (Up, Down, Left, Right 1731 // 1, 3, 5, 9 werden als Functionkeys klassifiziert (F27,F29,F33,F35) 1732 // 0 als Keypadkey und der Dezimalpunkt gar nicht (KP_Insert) 1733 KeySym nNewKeySym = XLookupKeysym( pEvent, nNumLockIndex_ ); 1734 if( nNewKeySym != NoSymbol ) 1735 nKeySym = nNewKeySym; 1736 } 1737 1738 // Now get the unmodified KeySym for KeyCode retrieval 1739 // try to strip off modifiers, e.g. Ctrl-$ becomes Ctrl-Shift-4 1740 *pUnmodifiedKeySym = XkbKeycodeToKeysym( GetDisplay(), pEvent->keycode, 0, 0 ); 1741 1742 return nKeySym; 1743 } 1744 1745 // Pointer 1746 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1747 #define MAKE_BITMAP( name ) \ 1748 XCreateBitmapFromData( pDisp_, \ 1749 DefaultRootWindow( pDisp_ ), \ 1750 (const char*)name##_bits, \ 1751 name##_width, \ 1752 name##_height ) 1753 1754 #define MAKE_CURSOR( name ) \ 1755 aCursBitmap = MAKE_BITMAP( name##curs ); \ 1756 aMaskBitmap = MAKE_BITMAP( name##mask ); \ 1757 nXHot = name##curs_x_hot; \ 1758 nYHot = name##curs_y_hot 1759 1760 XLIB_Cursor SalDisplay::GetPointer( int ePointerStyle ) 1761 { 1762 if( ePointerStyle >= POINTER_COUNT ) 1763 return 0; 1764 1765 XLIB_Cursor &aCur = aPointerCache_[ePointerStyle]; 1766 1767 if( aCur != None ) 1768 return aCur; 1769 1770 Pixmap aCursBitmap = None, aMaskBitmap = None; 1771 unsigned int nXHot = 0, nYHot = 0; 1772 1773 switch( ePointerStyle ) 1774 { 1775 case POINTER_NULL: 1776 MAKE_CURSOR( null ); 1777 break; 1778 case POINTER_ARROW: 1779 aCur = XCreateFontCursor( pDisp_, XC_left_ptr ); 1780 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1781 break; 1782 case POINTER_WAIT: 1783 aCur = XCreateFontCursor( pDisp_, XC_watch ); 1784 break; 1785 case POINTER_TEXT: // Mouse Pointer ist ein "I" Beam 1786 aCur = XCreateFontCursor( pDisp_, XC_xterm ); 1787 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1788 break; 1789 case POINTER_HELP: 1790 aCur = XCreateFontCursor( pDisp_, XC_question_arrow ); 1791 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1792 break; 1793 case POINTER_CROSS: // Mouse Pointer ist ein Kreuz 1794 aCur = XCreateFontCursor( pDisp_, XC_crosshair ); 1795 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1796 break; 1797 case POINTER_NSIZE: 1798 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); 1799 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1800 break; 1801 case POINTER_SSIZE: 1802 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); 1803 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1804 break; 1805 case POINTER_WSIZE: 1806 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); 1807 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1808 break; 1809 case POINTER_ESIZE: 1810 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); 1811 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1812 break; 1813 case POINTER_WINDOW_NSIZE: 1814 aCur = XCreateFontCursor( pDisp_, XC_top_side ); 1815 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1816 break; 1817 case POINTER_WINDOW_SSIZE: 1818 aCur = XCreateFontCursor( pDisp_, XC_bottom_side ); 1819 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1820 break; 1821 case POINTER_WINDOW_WSIZE: 1822 aCur = XCreateFontCursor( pDisp_, XC_left_side ); 1823 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1824 break; 1825 case POINTER_WINDOW_ESIZE: 1826 aCur = XCreateFontCursor( pDisp_, XC_right_side ); 1827 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1828 break; 1829 case POINTER_NWSIZE: 1830 aCur = XCreateFontCursor( pDisp_, XC_top_left_corner ); 1831 break; 1832 case POINTER_NESIZE: 1833 aCur = XCreateFontCursor( pDisp_, XC_top_right_corner ); 1834 break; 1835 case POINTER_SWSIZE: 1836 aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner ); 1837 break; 1838 case POINTER_SESIZE: 1839 aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner ); 1840 break; 1841 case POINTER_WINDOW_NWSIZE: 1842 aCur = XCreateFontCursor( pDisp_, XC_top_left_corner ); 1843 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1844 break; 1845 case POINTER_WINDOW_NESIZE: 1846 aCur = XCreateFontCursor( pDisp_, XC_top_right_corner ); 1847 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1848 break; 1849 case POINTER_WINDOW_SWSIZE: 1850 aCur = XCreateFontCursor( pDisp_, XC_bottom_left_corner ); 1851 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1852 break; 1853 case POINTER_WINDOW_SESIZE: 1854 aCur = XCreateFontCursor( pDisp_, XC_bottom_right_corner ); 1855 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1856 break; 1857 case POINTER_HSPLIT: 1858 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); 1859 break; 1860 case POINTER_VSPLIT: 1861 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); 1862 break; 1863 case POINTER_HSIZEBAR: 1864 aCur = XCreateFontCursor( pDisp_, XC_sb_h_double_arrow ); // ??? 1865 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1866 break; 1867 case POINTER_VSIZEBAR: 1868 aCur = XCreateFontCursor( pDisp_, XC_sb_v_double_arrow ); // ??? 1869 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1870 break; 1871 case POINTER_REFHAND: 1872 aCur = XCreateFontCursor( pDisp_, XC_hand1 ); 1873 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1874 break; 1875 case POINTER_HAND: 1876 aCur = XCreateFontCursor( pDisp_, XC_hand2 ); 1877 break; 1878 case POINTER_MAGNIFY: 1879 MAKE_CURSOR( magnify_ ); 1880 break; 1881 case POINTER_FILL: 1882 MAKE_CURSOR( fill_ ); 1883 break; 1884 case POINTER_MOVE: 1885 aCur = XCreateFontCursor( pDisp_, XC_fleur ); 1886 break; 1887 case POINTER_MOVEDATA: 1888 MAKE_CURSOR( movedata_ ); 1889 break; 1890 case POINTER_COPYDATA: 1891 MAKE_CURSOR( copydata_ ); 1892 break; 1893 case POINTER_MOVEFILE: 1894 MAKE_CURSOR( movefile_ ); 1895 break; 1896 case POINTER_COPYFILE: 1897 MAKE_CURSOR( copyfile_ ); 1898 break; 1899 case POINTER_MOVEFILES: 1900 MAKE_CURSOR( movefiles_ ); 1901 break; 1902 case POINTER_COPYFILES: 1903 MAKE_CURSOR( copyfiles_ ); 1904 break; 1905 case POINTER_NOTALLOWED: 1906 MAKE_CURSOR( nodrop_ ); 1907 break; 1908 case POINTER_ROTATE: 1909 MAKE_CURSOR( rotate_ ); 1910 break; 1911 case POINTER_HSHEAR: 1912 MAKE_CURSOR( hshear_ ); 1913 break; 1914 case POINTER_VSHEAR: 1915 MAKE_CURSOR( vshear_ ); 1916 break; 1917 case POINTER_DRAW_LINE: 1918 MAKE_CURSOR( drawline_ ); 1919 break; 1920 case POINTER_DRAW_RECT: 1921 MAKE_CURSOR( drawrect_ ); 1922 break; 1923 case POINTER_DRAW_POLYGON: 1924 MAKE_CURSOR( drawpolygon_ ); 1925 break; 1926 case POINTER_DRAW_BEZIER: 1927 MAKE_CURSOR( drawbezier_ ); 1928 break; 1929 case POINTER_DRAW_ARC: 1930 MAKE_CURSOR( drawarc_ ); 1931 break; 1932 case POINTER_DRAW_PIE: 1933 MAKE_CURSOR( drawpie_ ); 1934 break; 1935 case POINTER_DRAW_CIRCLECUT: 1936 MAKE_CURSOR( drawcirclecut_ ); 1937 break; 1938 case POINTER_DRAW_ELLIPSE: 1939 MAKE_CURSOR( drawellipse_ ); 1940 break; 1941 case POINTER_DRAW_CONNECT: 1942 MAKE_CURSOR( drawconnect_ ); 1943 break; 1944 case POINTER_DRAW_TEXT: 1945 MAKE_CURSOR( drawtext_ ); 1946 break; 1947 case POINTER_MIRROR: 1948 MAKE_CURSOR( mirror_ ); 1949 break; 1950 case POINTER_CROOK: 1951 MAKE_CURSOR( crook_ ); 1952 break; 1953 case POINTER_CROP: 1954 MAKE_CURSOR( crop_ ); 1955 break; 1956 case POINTER_MOVEPOINT: 1957 MAKE_CURSOR( movepoint_ ); 1958 break; 1959 case POINTER_MOVEBEZIERWEIGHT: 1960 MAKE_CURSOR( movebezierweight_ ); 1961 break; 1962 case POINTER_DRAW_FREEHAND: 1963 MAKE_CURSOR( drawfreehand_ ); 1964 break; 1965 case POINTER_DRAW_CAPTION: 1966 MAKE_CURSOR( drawcaption_ ); 1967 break; 1968 case POINTER_PEN: // Mouse Pointer ist ein Stift 1969 aCur = XCreateFontCursor( pDisp_, XC_pencil ); 1970 DBG_ASSERT( aCur != None, "GetPointer: Could not define cursor" ); 1971 break; 1972 case POINTER_LINKDATA: 1973 MAKE_CURSOR( linkdata_ ); 1974 break; 1975 case POINTER_MOVEDATALINK: 1976 MAKE_CURSOR( movedlnk_ ); 1977 break; 1978 case POINTER_COPYDATALINK: 1979 MAKE_CURSOR( copydlnk_ ); 1980 break; 1981 case POINTER_LINKFILE: 1982 MAKE_CURSOR( linkfile_ ); 1983 break; 1984 case POINTER_MOVEFILELINK: 1985 MAKE_CURSOR( moveflnk_ ); 1986 break; 1987 case POINTER_COPYFILELINK: 1988 MAKE_CURSOR( copyflnk_ ); 1989 break; 1990 case POINTER_CHART: 1991 MAKE_CURSOR( chart_ ); 1992 break; 1993 case POINTER_DETECTIVE: 1994 MAKE_CURSOR( detective_ ); 1995 break; 1996 case POINTER_PIVOT_COL: 1997 MAKE_CURSOR( pivotcol_ ); 1998 break; 1999 case POINTER_PIVOT_ROW: 2000 MAKE_CURSOR( pivotrow_ ); 2001 break; 2002 case POINTER_PIVOT_FIELD: 2003 MAKE_CURSOR( pivotfld_ ); 2004 break; 2005 case POINTER_PIVOT_DELETE: 2006 MAKE_CURSOR( pivotdel_ ); 2007 break; 2008 case POINTER_CHAIN: 2009 MAKE_CURSOR( chain_ ); 2010 break; 2011 case POINTER_CHAIN_NOTALLOWED: 2012 MAKE_CURSOR( chainnot_ ); 2013 break; 2014 case POINTER_TIMEEVENT_MOVE: 2015 MAKE_CURSOR( timemove_ ); 2016 break; 2017 case POINTER_TIMEEVENT_SIZE: 2018 MAKE_CURSOR( timesize_ ); 2019 break; 2020 case POINTER_AUTOSCROLL_N: 2021 MAKE_CURSOR(asn_ ); 2022 break; 2023 case POINTER_AUTOSCROLL_S: 2024 MAKE_CURSOR( ass_ ); 2025 break; 2026 case POINTER_AUTOSCROLL_W: 2027 MAKE_CURSOR( asw_ ); 2028 break; 2029 case POINTER_AUTOSCROLL_E: 2030 MAKE_CURSOR( ase_ ); 2031 break; 2032 case POINTER_AUTOSCROLL_NW: 2033 MAKE_CURSOR( asnw_ ); 2034 break; 2035 case POINTER_AUTOSCROLL_NE: 2036 MAKE_CURSOR( asne_ ); 2037 break; 2038 case POINTER_AUTOSCROLL_SW: 2039 MAKE_CURSOR( assw_ ); 2040 break; 2041 case POINTER_AUTOSCROLL_SE: 2042 MAKE_CURSOR( asse_ ); 2043 break; 2044 case POINTER_AUTOSCROLL_NS: 2045 MAKE_CURSOR( asns_ ); 2046 break; 2047 case POINTER_AUTOSCROLL_WE: 2048 MAKE_CURSOR( aswe_ ); 2049 break; 2050 case POINTER_AUTOSCROLL_NSWE: 2051 MAKE_CURSOR( asnswe_ ); 2052 break; 2053 case POINTER_AIRBRUSH: 2054 MAKE_CURSOR( airbrush_ ); 2055 break; 2056 case POINTER_TEXT_VERTICAL: 2057 MAKE_CURSOR( vertcurs_ ); 2058 break; 2059 2060 // --> FME 2004-07-30 #i32329# Enhanced table selection 2061 case POINTER_TAB_SELECT_S: 2062 MAKE_CURSOR( tblsels_ ); 2063 break; 2064 case POINTER_TAB_SELECT_E: 2065 MAKE_CURSOR( tblsele_ ); 2066 break; 2067 case POINTER_TAB_SELECT_SE: 2068 MAKE_CURSOR( tblselse_ ); 2069 break; 2070 case POINTER_TAB_SELECT_W: 2071 MAKE_CURSOR( tblselw_ ); 2072 break; 2073 case POINTER_TAB_SELECT_SW: 2074 MAKE_CURSOR( tblselsw_ ); 2075 break; 2076 // <-- 2077 2078 // --> FME 2004-08-16 #i20119# Paintbrush tool 2079 case POINTER_PAINTBRUSH : 2080 MAKE_CURSOR( paintbrush_ ); 2081 break; 2082 // <-- 2083 2084 default: 2085 DBG_ERROR("pointer not implemented"); 2086 aCur = XCreateFontCursor( pDisp_, XC_arrow ); 2087 break; 2088 } 2089 2090 if( None == aCur ) 2091 { 2092 XColor aBlack, aWhite, aDummy; 2093 Colormap hColormap = GetColormap(m_nDefaultScreen).GetXColormap(); 2094 2095 XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy ); 2096 XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy ); 2097 2098 aCur = XCreatePixmapCursor( pDisp_, 2099 aCursBitmap, aMaskBitmap, 2100 &aBlack, &aWhite, 2101 nXHot, nYHot ); 2102 2103 XFreePixmap( pDisp_, aCursBitmap ); 2104 XFreePixmap( pDisp_, aMaskBitmap ); 2105 } 2106 2107 return aCur; 2108 } 2109 2110 int SalDisplay::CaptureMouse( SalFrame *pCapture ) 2111 { 2112 if( !pCapture ) 2113 { 2114 m_pCapture = NULL; 2115 XUngrabPointer( GetDisplay(), CurrentTime ); 2116 XFlush( GetDisplay() ); 2117 return 0; 2118 } 2119 2120 m_pCapture = NULL; 2121 2122 // FIXME: get rid of X11SalFrame 2123 const SystemEnvData* pEnvData = pCapture->GetSystemData(); 2124 int ret = XGrabPointer( GetDisplay(), 2125 (XLIB_Window)pEnvData->aWindow, 2126 False, 2127 PointerMotionMask| ButtonPressMask|ButtonReleaseMask, 2128 GrabModeAsync, 2129 GrabModeAsync, 2130 None, 2131 static_cast<X11SalFrame*>(pCapture)->GetCursor(), 2132 CurrentTime ); 2133 2134 if( ret != GrabSuccess ) 2135 { 2136 DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n"); 2137 return -1; 2138 } 2139 2140 m_pCapture = pCapture; 2141 return 1; 2142 } 2143 2144 // Events 2145 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2146 2147 void SalDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 2148 { 2149 if( osl_acquireMutex( hEventGuard_ ) ) 2150 { 2151 m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) ); 2152 2153 // Notify SalXLib::Yield() of a pending event. 2154 pXLib_->PostUserEvent(); 2155 2156 osl_releaseMutex( hEventGuard_ ); 2157 } 2158 else { 2159 DBG_ASSERT( 1, "SalDisplay::SendInternalEvent !acquireMutex\n" ); 2160 } 2161 } 2162 2163 void SalDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 2164 { 2165 if( osl_acquireMutex( hEventGuard_ ) ) 2166 { 2167 if( ! m_aUserEvents.empty() ) 2168 { 2169 std::list< SalUserEvent >::iterator it, next; 2170 next = m_aUserEvents.begin(); 2171 do 2172 { 2173 it = next++; 2174 if( it->m_pFrame == pFrame && 2175 it->m_pData == pData && 2176 it->m_nEvent == nEvent ) 2177 { 2178 m_aUserEvents.erase( it ); 2179 } 2180 } while( next != m_aUserEvents.end() ); 2181 } 2182 2183 osl_releaseMutex( hEventGuard_ ); 2184 } 2185 else { 2186 DBG_ASSERT( 1, "SalDisplay::CancelInternalEvent !acquireMutex\n" ); 2187 } 2188 } 2189 2190 sal_Bool SalX11Display::IsEvent() 2191 { 2192 sal_Bool bRet = sal_False; 2193 2194 if( osl_acquireMutex( hEventGuard_ ) ) 2195 { 2196 if( m_aUserEvents.begin() != m_aUserEvents.end() ) 2197 bRet = sal_True; 2198 osl_releaseMutex( hEventGuard_ ); 2199 } 2200 2201 if( bRet || XEventsQueued( pDisp_, QueuedAlready ) ) 2202 return sal_True; 2203 2204 XFlush( pDisp_ ); 2205 return sal_False; 2206 } 2207 2208 bool SalDisplay::DispatchInternalEvent() 2209 { 2210 SalFrame* pFrame = NULL; 2211 void* pData = NULL; 2212 sal_uInt16 nEvent = 0; 2213 2214 if( osl_acquireMutex( hEventGuard_ ) ) 2215 { 2216 if( m_aUserEvents.begin() != m_aUserEvents.end() ) 2217 { 2218 pFrame = m_aUserEvents.front().m_pFrame; 2219 pData = m_aUserEvents.front().m_pData; 2220 nEvent = m_aUserEvents.front().m_nEvent; 2221 2222 m_aUserEvents.pop_front(); 2223 } 2224 osl_releaseMutex( hEventGuard_ ); 2225 } 2226 else { 2227 DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" ); 2228 } 2229 2230 if( pFrame ) 2231 pFrame->CallCallback( nEvent, pData ); 2232 2233 return pFrame != NULL; 2234 } 2235 2236 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2237 2238 void SalX11Display::Yield() 2239 { 2240 if( DispatchInternalEvent() ) 2241 return; 2242 2243 XEvent aEvent; 2244 DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() == 2245 vos::OThread::getCurrentIdentifier(), 2246 "will crash soon since solar mutex not locked in SalDisplay::Yield" ); 2247 2248 XNextEvent( pDisp_, &aEvent ); 2249 2250 Dispatch( &aEvent ); 2251 2252 #ifdef DBG_UTIL 2253 if( pXLib_->HasXErrorOccured() ) 2254 { 2255 XFlush( pDisp_ ); 2256 PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent ); 2257 } 2258 #endif 2259 pXLib_->ResetXErrorOccured(); 2260 } 2261 2262 long SalX11Display::Dispatch( XEvent *pEvent ) 2263 { 2264 if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease ) 2265 { 2266 XLIB_Window aWindow = pEvent->xkey.window; 2267 2268 std::list< SalFrame* >::const_iterator it; 2269 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2270 { 2271 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); 2272 if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow ) 2273 { 2274 aWindow = pFrame->GetWindow(); 2275 break; 2276 } 2277 } 2278 if( it != m_aFrames.end() ) 2279 { 2280 if ( mpInputMethod->FilterEvent( pEvent , aWindow ) ) 2281 return 0; 2282 } 2283 } 2284 else 2285 if ( mpInputMethod->FilterEvent( pEvent, None ) ) 2286 return 0; 2287 2288 SalInstance* pInstance = GetSalData()->m_pInstance; 2289 pInstance->CallEventCallback( pEvent, sizeof( XEvent ) ); 2290 2291 switch( pEvent->type ) 2292 { 2293 case MotionNotify: 2294 while( XCheckWindowEvent( pEvent->xany.display, 2295 pEvent->xany.window, 2296 ButtonMotionMask, 2297 pEvent ) ) 2298 ; 2299 m_nLastUserEventTime = pEvent->xmotion.time; 2300 break; 2301 case PropertyNotify: 2302 if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) ) 2303 { 2304 for( unsigned int i = 0; i < m_aScreens.size(); i++ ) 2305 { 2306 if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow ) 2307 { 2308 std::list< SalFrame* >::const_iterator it; 2309 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2310 (*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); 2311 return 0; 2312 } 2313 } 2314 } 2315 break; 2316 case MappingNotify: 2317 if( MappingKeyboard == pEvent->xmapping.request || 2318 MappingModifier == pEvent->xmapping.request ) 2319 { 2320 XRefreshKeyboardMapping( &pEvent->xmapping ); 2321 if( MappingModifier == pEvent->xmapping.request ) 2322 ModifierMapping(); 2323 if( MappingKeyboard == pEvent->xmapping.request ) // refresh mapping 2324 GetKeyboardName( sal_True ); 2325 } 2326 break; 2327 case ButtonPress: 2328 case ButtonRelease: 2329 m_nLastUserEventTime = pEvent->xbutton.time; 2330 break; 2331 case XLIB_KeyPress: 2332 case KeyRelease: 2333 m_nLastUserEventTime = pEvent->xkey.time; 2334 break; 2335 default: 2336 2337 if ( GetKbdExtension()->UseExtension() 2338 && GetKbdExtension()->GetEventBase() == pEvent->type ) 2339 { 2340 GetKbdExtension()->Dispatch( pEvent ); 2341 return 1; 2342 } 2343 break; 2344 } 2345 2346 std::list< SalFrame* >::iterator it; 2347 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2348 { 2349 X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it); 2350 XLIB_Window aDispatchWindow = pEvent->xany.window; 2351 if( pFrame->GetWindow() == aDispatchWindow 2352 || pFrame->GetShellWindow() == aDispatchWindow 2353 || pFrame->GetForeignParent() == aDispatchWindow 2354 ) 2355 { 2356 return pFrame->Dispatch( pEvent ); 2357 } 2358 if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() ) 2359 { 2360 return pFrame->Dispatch( pEvent ); 2361 } 2362 } 2363 2364 // dispatch to salobjects 2365 X11SalObject::Dispatch( pEvent ); 2366 2367 // is this perhaps a root window that changed size ? 2368 processRandREvent( pEvent ); 2369 2370 return 0; 2371 } 2372 2373 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2374 void SalDisplay::PrintEvent( const ByteString &rComment, 2375 XEvent *pEvent ) const 2376 { 2377 if( pEvent->type <= MappingNotify ) 2378 { 2379 fprintf( stderr, "[%s] %s s=%d w=%ld\n", 2380 rComment.GetBuffer(), 2381 EventNames[pEvent->type], 2382 pEvent->xany.send_event, 2383 pEvent->xany.window ); 2384 2385 switch( pEvent->type ) 2386 { 2387 case XLIB_KeyPress: 2388 case KeyRelease: 2389 fprintf( stderr, "\t\ts=%d c=%d\n", 2390 pEvent->xkey.state, 2391 pEvent->xkey.keycode ); 2392 break; 2393 2394 case ButtonPress: 2395 case ButtonRelease: 2396 fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n", 2397 pEvent->xbutton.state, 2398 pEvent->xbutton.button, 2399 pEvent->xbutton.x, 2400 pEvent->xbutton.y, 2401 pEvent->xbutton.x_root, 2402 pEvent->xbutton.y_root ); 2403 break; 2404 2405 case MotionNotify: 2406 fprintf( stderr, "\t\ts=%d x=%d y=%d\n", 2407 pEvent->xmotion.state, 2408 pEvent->xmotion.x, 2409 pEvent->xmotion.y ); 2410 break; 2411 2412 case EnterNotify: 2413 case LeaveNotify: 2414 fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n", 2415 pEvent->xcrossing.mode, 2416 pEvent->xcrossing.focus, 2417 pEvent->xcrossing.x, 2418 pEvent->xcrossing.y ); 2419 break; 2420 2421 case FocusIn: 2422 case FocusOut: 2423 fprintf( stderr, "\t\tm=%d d=%d\n", 2424 pEvent->xfocus.mode, 2425 pEvent->xfocus.detail ); 2426 break; 2427 2428 case Expose: 2429 case GraphicsExpose: 2430 fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n", 2431 pEvent->xexpose.count, 2432 pEvent->xexpose.width, 2433 pEvent->xexpose.height, 2434 pEvent->xexpose.x, 2435 pEvent->xexpose.y ); 2436 break; 2437 2438 case VisibilityNotify: 2439 fprintf( stderr, "\t\ts=%d\n", 2440 pEvent->xvisibility.state ); 2441 break; 2442 2443 case CreateNotify: 2444 case DestroyNotify: 2445 break; 2446 2447 case MapNotify: 2448 case UnmapNotify: 2449 break; 2450 2451 case ReparentNotify: 2452 fprintf( stderr, "\t\tp=%d x=%d y=%d\n", 2453 sal::static_int_cast< int >(pEvent->xreparent.parent), 2454 pEvent->xreparent.x, 2455 pEvent->xreparent.y ); 2456 break; 2457 2458 case ConfigureNotify: 2459 fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n", 2460 pEvent->xconfigure.border_width, 2461 pEvent->xconfigure.width, 2462 pEvent->xconfigure.height, 2463 pEvent->xconfigure.x, 2464 pEvent->xconfigure.y ); 2465 break; 2466 2467 case PropertyNotify: 2468 fprintf( stderr, "\t\ta=%s (0x%X)\n", 2469 GetAtomName( pDisp_, pEvent->xproperty.atom ), 2470 sal::static_int_cast< unsigned int >( 2471 pEvent->xproperty.atom) ); 2472 break; 2473 2474 case ColormapNotify: 2475 fprintf( stderr, "\t\tc=%ld n=%d s=%d\n", 2476 pEvent->xcolormap.colormap, 2477 pEvent->xcolormap.c_new, 2478 pEvent->xcolormap.state ); 2479 break; 2480 2481 case ClientMessage: 2482 fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n", 2483 GetAtomName( pDisp_, pEvent->xclient.message_type ), 2484 sal::static_int_cast< unsigned int >( 2485 pEvent->xclient.message_type), 2486 pEvent->xclient.format, 2487 pEvent->xclient.data.l[0], 2488 pEvent->xclient.data.l[1], 2489 pEvent->xclient.data.l[2], 2490 pEvent->xclient.data.l[3], 2491 pEvent->xclient.data.l[4] ); 2492 break; 2493 2494 case MappingNotify: 2495 fprintf( stderr, "\t\tr=%sd\n", 2496 MappingModifier == pEvent->xmapping.request 2497 ? "MappingModifier" 2498 : MappingKeyboard == pEvent->xmapping.request 2499 ? "MappingKeyboard" 2500 : "MappingPointer" ); 2501 2502 break; 2503 } 2504 } 2505 else 2506 fprintf( stderr, "[%s] %d s=%d w=%ld\n", 2507 rComment.GetBuffer(), 2508 pEvent->type, 2509 pEvent->xany.send_event, 2510 pEvent->xany.window ); 2511 } 2512 2513 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2514 void SalDisplay::PrintInfo() const 2515 { 2516 if( IsDisplay() ) 2517 { 2518 fprintf( stderr, "\n" ); 2519 fprintf( stderr, "Environment\n" ); 2520 fprintf( stderr, "\t$XENVIRONMENT \t\"%s\"\n", 2521 GetEnv( "XENVIRONMENT" ) ); 2522 fprintf( stderr, "\t$DISPLAY \t\"%s\"\n", 2523 GetEnv( "DISPLAY" ) ); 2524 fprintf( stderr, "\t$SAL_VISUAL \t\"%s\"\n", 2525 GetEnv( "SAL_VISUAL" ) ); 2526 fprintf( stderr, "\t$SAL_FONTPATH \t\"%s\"\n", 2527 GetEnv( "SAL_FONTPATH" ) ); 2528 fprintf( stderr, "\t$SAL_NOSEGV \t\"%s\"\n", 2529 GetEnv( "SAL_NOSEGV" ) ); 2530 fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n", 2531 GetEnv( "SAL_IGNOREXERRORS" ) ); 2532 fprintf( stderr, "\t$SAL_PROPERTIES \t\"%s\"\n", 2533 GetEnv( "SAL_PROPERTIES" ) ); 2534 fprintf( stderr, "\t$SAL_WM \t\"%s\"\n", 2535 GetEnv( "SAL_WM" ) ); 2536 fprintf( stderr, "\t$SAL_SYNCHRONIZE \t\"%s\"\n", 2537 GetEnv( "SAL_SYNCHRONIZE" ) ); 2538 2539 char sHostname[ 120 ]; 2540 gethostname (sHostname, 120 ); 2541 fprintf( stderr, "Client\n" ); 2542 fprintf( stderr, "\tHost \t\"%s\"\n", 2543 sHostname ); 2544 2545 fprintf( stderr, "Display\n" ); 2546 fprintf( stderr, "\tHost \t\"%s\"\n", 2547 DisplayString(pDisp_) ); 2548 fprintf( stderr, "\tVendor (Release) \t\"%s (%d)\"\n", 2549 ServerVendor(pDisp_), VendorRelease(pDisp_) ); 2550 fprintf( stderr, "\tProtocol \t%d.%d\n", 2551 ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) ); 2552 fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n", 2553 m_nDefaultScreen, ScreenCount(pDisp_), DefaultScreen(pDisp_) ); 2554 fprintf( stderr, "\tshift ctrl alt \t%s (0x%X) %s (0x%X) %s (0x%X)\n", 2555 KeyStr( nShiftKeySym_ ), sal::static_int_cast< unsigned int >(nShiftKeySym_), 2556 KeyStr( nCtrlKeySym_ ), sal::static_int_cast< unsigned int >(nCtrlKeySym_), 2557 KeyStr( nMod1KeySym_ ), sal::static_int_cast< unsigned int >(nMod1KeySym_) ); 2558 if( XExtendedMaxRequestSize(pDisp_) * 4 ) 2559 fprintf( stderr, "\tXMaxRequestSize \t%ld %ld [bytes]\n", 2560 XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 ); 2561 if( GetProperties() != PROPERTY_DEFAULT ) 2562 fprintf( stderr, "\tProperties \t0x%lX\n", GetProperties() ); 2563 if( eWindowManager_ != otherwm ) 2564 fprintf( stderr, "\tWindowmanager \t%d\n", eWindowManager_ ); 2565 fprintf( stderr, "\tWMName \t%s\n", rtl::OUStringToOString( getWMAdaptor()->getWindowManagerName(), osl_getThreadTextEncoding() ).getStr() ); 2566 } 2567 fprintf( stderr, "Screen\n" ); 2568 fprintf( stderr, "\tResolution/Size \t%ld*%ld %ld*%ld %.1lf\"\n", 2569 aResolution_.A(), aResolution_.B(), 2570 m_aScreens[m_nDefaultScreen].m_aSize.Width(), m_aScreens[m_nDefaultScreen].m_aSize.Height(), 2571 Hypothenuse( DisplayWidthMM ( pDisp_, m_nDefaultScreen ), 2572 DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) / 25.4 ); 2573 fprintf( stderr, "\tBlack&White \t%lu %lu\n", 2574 GetColormap(m_nDefaultScreen).GetBlackPixel(), GetColormap(m_nDefaultScreen).GetWhitePixel() ); 2575 fprintf( stderr, "\tRGB \t0x%lx 0x%lx 0x%lx\n", 2576 GetVisual(m_nDefaultScreen).red_mask, GetVisual(m_nDefaultScreen).green_mask, GetVisual(m_nDefaultScreen).blue_mask ); 2577 fprintf( stderr, "\tVisual \t%d-bit %s ID=0x%x\n", 2578 GetVisual(m_nDefaultScreen).GetDepth(), 2579 VisualClassName[ GetVisual(m_nDefaultScreen).GetClass() ], 2580 sal::static_int_cast< unsigned int >(GetVisual(m_nDefaultScreen).GetVisualId()) ); 2581 } 2582 2583 int SalDisplay::addXineramaScreenUnique( long i_nX, long i_nY, long i_nWidth, long i_nHeight ) 2584 { 2585 // see if any frame buffers are at the same coordinates 2586 // this can happen with weird configuration e.g. on 2587 // XFree86 and Clone displays 2588 const size_t nScreens = m_aXineramaScreens.size(); 2589 for( size_t n = 0; n < nScreens; n++ ) 2590 { 2591 if( m_aXineramaScreens[n].Left() == i_nX && 2592 m_aXineramaScreens[n].Top() == i_nY ) 2593 { 2594 if( m_aXineramaScreens[n].GetWidth() < i_nWidth || 2595 m_aXineramaScreens[n].GetHeight() < i_nHeight ) 2596 { 2597 m_aXineramaScreens[n].SetSize( Size( i_nWidth, i_nHeight ) ); 2598 } 2599 return (int)n; 2600 } 2601 } 2602 m_aXineramaScreens.push_back( Rectangle( Point( i_nX, i_nY ), Size( i_nWidth, i_nHeight ) ) ); 2603 return (int)m_aXineramaScreens.size()-1; 2604 } 2605 2606 void SalDisplay::InitXinerama() 2607 { 2608 if( m_aScreens.size() > 1 ) 2609 { 2610 m_bXinerama = false; 2611 return; // multiple screens mean no xinerama 2612 } 2613 #ifdef USE_XINERAMA 2614 #if defined(USE_XINERAMA_XSUN) 2615 int nFramebuffers = 1; 2616 if( XineramaGetState( pDisp_, m_nDefaultScreen ) ) 2617 { 2618 XRectangle pFramebuffers[MAXFRAMEBUFFERS]; 2619 unsigned char hints[MAXFRAMEBUFFERS]; 2620 int result = XineramaGetInfo( pDisp_, 2621 m_nDefaultScreen, 2622 pFramebuffers, 2623 hints, 2624 &nFramebuffers ); 2625 if( result > 0 && nFramebuffers > 1 ) 2626 { 2627 m_bXinerama = true; 2628 m_aXineramaScreens = std::vector<Rectangle>(); 2629 for( int i = 0; i < nFramebuffers; i++ ) 2630 addXineramaScreenUnique( pFramebuffers[i].x, 2631 pFramebuffers[i].y, 2632 pFramebuffers[i].width, 2633 pFramebuffers[i].height ); 2634 } 2635 } 2636 #elif defined(USE_XINERAMA_XORG) 2637 if( XineramaIsActive( pDisp_ ) ) 2638 { 2639 int nFramebuffers = 1; 2640 XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers ); 2641 if( pScreens ) 2642 { 2643 if( nFramebuffers > 1 ) 2644 { 2645 m_aXineramaScreens = std::vector<Rectangle>(); 2646 for( int i = 0; i < nFramebuffers; i++ ) 2647 { 2648 addXineramaScreenUnique( pScreens[i].x_org, 2649 pScreens[i].y_org, 2650 pScreens[i].width, 2651 pScreens[i].height ); 2652 } 2653 m_bXinerama = m_aXineramaScreens.size() > 1; 2654 } 2655 XFree( pScreens ); 2656 } 2657 } 2658 #endif 2659 #if OSL_DEBUG_LEVEL > 1 2660 if( m_bXinerama ) 2661 { 2662 for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it ) 2663 fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() ); 2664 } 2665 #endif 2666 #endif // USE_XINERAMA 2667 } 2668 2669 void SalDisplay::registerFrame( SalFrame* pFrame ) 2670 { 2671 m_aFrames.push_front( pFrame ); 2672 } 2673 2674 void SalDisplay::deregisterFrame( SalFrame* pFrame ) 2675 { 2676 if( osl_acquireMutex( hEventGuard_ ) ) 2677 { 2678 std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); 2679 while ( it != m_aUserEvents.end() ) 2680 { 2681 if( it->m_pFrame == pFrame ) 2682 it = m_aUserEvents.erase( it ); 2683 else 2684 ++it; 2685 } 2686 osl_releaseMutex( hEventGuard_ ); 2687 } 2688 else { 2689 DBG_ERROR( "SalDisplay::deregisterFrame !acquireMutex\n" ); 2690 } 2691 2692 m_aFrames.remove( pFrame ); 2693 } 2694 2695 2696 extern "C" 2697 { 2698 static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg ) 2699 { 2700 SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg); 2701 if( i_pEvent->type == PropertyNotify && 2702 i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) && 2703 i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ) 2704 ) 2705 return True; 2706 2707 return False; 2708 } 2709 } 2710 2711 XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const 2712 { 2713 if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget ) 2714 { 2715 // get current server time 2716 unsigned char c = 0; 2717 XEvent aEvent; 2718 Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ); 2719 XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ), 2720 nAtom, nAtom, 8, PropModeReplace, &c, 1 ); 2721 XFlush( GetDisplay() ); 2722 2723 if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) ) 2724 { 2725 // this should not happen at all; still sometimes it happens 2726 aEvent.xproperty.time = CurrentTime; 2727 } 2728 2729 m_nLastUserEventTime = aEvent.xproperty.time; 2730 } 2731 return m_nLastUserEventTime; 2732 } 2733 2734 bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData, 2735 X_if_predicate i_pPredicate, long i_nTimeout ) const 2736 { 2737 /* #i99360# ugly workaround an X11 library bug 2738 this replaces the following call: 2739 XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ); 2740 */ 2741 bool bRet = true; 2742 2743 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2744 { 2745 // wait for some event to arrive 2746 struct pollfd aFD; 2747 aFD.fd = ConnectionNumber(GetDisplay()); 2748 aFD.events = POLLIN; 2749 aFD.revents = 0; 2750 poll( &aFD, 1, i_nTimeout ); 2751 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2752 { 2753 poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver 2754 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2755 { 2756 bRet = false; 2757 } 2758 } 2759 } 2760 return bRet; 2761 } 2762 2763 // -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2764 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2765 SalVisual::SalVisual() 2766 { 2767 rtl_zeroMemory( this, sizeof( SalVisual ) ); 2768 } 2769 2770 SalVisual::SalVisual( const XVisualInfo* pXVI ) 2771 { 2772 *(XVisualInfo*)this = *pXVI; 2773 if( GetClass() == TrueColor ) 2774 { 2775 nRedShift_ = sal_Shift( red_mask ); 2776 nGreenShift_ = sal_Shift( green_mask ); 2777 nBlueShift_ = sal_Shift( blue_mask ); 2778 2779 nRedBits_ = sal_significantBits( red_mask ); 2780 nGreenBits_ = sal_significantBits( green_mask ); 2781 nBlueBits_ = sal_significantBits( blue_mask ); 2782 2783 if( GetDepth() == 24 ) 2784 if( red_mask == 0xFF0000 ) 2785 if( green_mask == 0xFF00 ) 2786 if( blue_mask == 0xFF ) 2787 eRGBMode_ = RGB; 2788 else 2789 eRGBMode_ = otherSalRGB; 2790 else if( blue_mask == 0xFF00 ) 2791 if( green_mask == 0xFF ) 2792 eRGBMode_ = RBG; 2793 else 2794 eRGBMode_ = otherSalRGB; 2795 else 2796 eRGBMode_ = otherSalRGB; 2797 else if( green_mask == 0xFF0000 ) 2798 if( red_mask == 0xFF00 ) 2799 if( blue_mask == 0xFF ) 2800 eRGBMode_ = GRB; 2801 else 2802 eRGBMode_ = otherSalRGB; 2803 else if( blue_mask == 0xFF00 ) 2804 if( red_mask == 0xFF ) 2805 eRGBMode_ = GBR; 2806 else 2807 eRGBMode_ = otherSalRGB; 2808 else 2809 eRGBMode_ = otherSalRGB; 2810 else if( blue_mask == 0xFF0000 ) 2811 if( red_mask == 0xFF00 ) 2812 if( green_mask == 0xFF ) 2813 eRGBMode_ = BRG; 2814 else 2815 eRGBMode_ = otherSalRGB; 2816 else if( green_mask == 0xFF00 ) 2817 if( red_mask == 0xFF ) 2818 eRGBMode_ = BGR; 2819 else 2820 eRGBMode_ = otherSalRGB; 2821 else 2822 eRGBMode_ = otherSalRGB; 2823 else 2824 eRGBMode_ = otherSalRGB; 2825 else 2826 eRGBMode_ = otherSalRGB; 2827 } 2828 } 2829 2830 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2831 SalVisual::~SalVisual() 2832 { 2833 if( -1 == screen && VisualID(-1) == visualid ) delete visual; 2834 } 2835 2836 // Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors 2837 // fuer die 6 XXXA ist das nicht reversibel 2838 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2839 // SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF 2840 2841 #define SALCOLOR RGB 2842 #define SALCOLORREVERSE BGR 2843 2844 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 ) 2845 { 2846 int n; 2847 2848 switch( GetMode() ) 2849 { 2850 case otherSalRGB: 2851 return sal_False; 2852 case SALCOLOR: 2853 break; 2854 case SALCOLORREVERSE: 2855 case RBG: 2856 case BRG: 2857 case GBR: 2858 case GRB: 2859 return Convert( n0, n1, n2 ); 2860 case RGBA: 2861 n = n0; 2862 n0 = n1; 2863 n1 = n2; 2864 n2 = n3; 2865 n3 = n; 2866 break; 2867 case BGRA: 2868 case RBGA: 2869 case BRGA: 2870 case GBRA: 2871 case GRBA: 2872 default: 2873 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); 2874 abort(); 2875 } 2876 return sal_True; 2877 } 2878 2879 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2 ) 2880 { 2881 int n; 2882 2883 switch( GetMode() ) 2884 { 2885 case otherSalRGB: 2886 return sal_False; 2887 case SALCOLOR: 2888 break; 2889 case RBG: 2890 n = n0; 2891 n0 = n1; 2892 n1 = n; 2893 break; 2894 case GRB: 2895 n = n1; 2896 n1 = n2; 2897 n2 = n; 2898 break; 2899 case SALCOLORREVERSE: 2900 n = n0; 2901 n0 = n2; 2902 n2 = n; 2903 break; 2904 case BRG: 2905 n = n0; 2906 n0 = n1; 2907 n1 = n2; 2908 n2 = n; 2909 break; 2910 case GBR: 2911 n = n2; 2912 n2 = n1; 2913 n1 = n0; 2914 n0 = n; 2915 break; 2916 default: 2917 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); 2918 abort(); 2919 } 2920 return sal_True; 2921 } 2922 2923 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2924 SalColor SalVisual::GetTCColor( Pixel nPixel ) const 2925 { 2926 if( SALCOLOR == eRGBMode_ ) 2927 return (SalColor)nPixel; 2928 2929 if( SALCOLORREVERSE == eRGBMode_ ) 2930 return MAKE_SALCOLOR( (nPixel & 0x0000FF), 2931 (nPixel & 0x00FF00) >> 8, 2932 (nPixel & 0xFF0000) >> 16); 2933 2934 Pixel r = nPixel & red_mask; 2935 Pixel g = nPixel & green_mask; 2936 Pixel b = nPixel & blue_mask; 2937 2938 if( otherSalRGB != eRGBMode_ ) // 8+8+8=24 2939 return MAKE_SALCOLOR( r >> nRedShift_, 2940 g >> nGreenShift_, 2941 b >> nBlueShift_ ); 2942 2943 if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_; 2944 if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_; 2945 if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_; 2946 2947 if( nRedBits_ != 8 ) 2948 r |= (r & 0xff) >> (8-nRedBits_); 2949 if( nGreenBits_ != 8 ) 2950 g |= (g & 0xff) >> (8-nGreenBits_); 2951 if( nBlueBits_ != 8 ) 2952 b |= (b & 0xff) >> (8-nBlueBits_); 2953 2954 return MAKE_SALCOLOR( r, g, b ); 2955 } 2956 2957 Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const 2958 { 2959 if( SALCOLOR == eRGBMode_ ) 2960 return (Pixel)nSalColor; 2961 2962 Pixel r = (Pixel)SALCOLOR_RED( nSalColor ); 2963 Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor ); 2964 Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor ); 2965 2966 if( SALCOLORREVERSE == eRGBMode_ ) 2967 return (b << 16) | (g << 8) | (r); 2968 2969 if( otherSalRGB != eRGBMode_ ) // 8+8+8=24 2970 return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_); 2971 2972 if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_; 2973 if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_; 2974 if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_; 2975 2976 return (r&red_mask) | (g&green_mask) | (b&blue_mask); 2977 } 2978 2979 // -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2980 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2981 SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap, int nScreen ) 2982 : m_pDisplay( pDisplay ), 2983 m_hColormap( hColormap ), 2984 m_nScreen( nScreen ) 2985 { 2986 m_aVisual = m_pDisplay->GetVisual( m_nScreen ); 2987 2988 XColor aColor; 2989 2990 GetXPixel( aColor, 0x00, 0x00, 0x00 ); 2991 m_nBlackPixel = aColor.pixel; 2992 2993 GetXPixel( aColor, 0xFF, 0xFF, 0xFF ); 2994 m_nWhitePixel = aColor.pixel; 2995 2996 m_nUsed = 1 << m_aVisual.GetDepth(); 2997 2998 if( m_aVisual.GetClass() == PseudoColor ) 2999 { 3000 int r, g, b; 3001 3002 // black, white, gray, ~gray = 4 3003 GetXPixels( aColor, 0xC0, 0xC0, 0xC0 ); 3004 3005 // light colors: 3 * 2 = 6 3006 // GetXPixels( aColor, 0x00, 0x00, 0x00 ); 3007 GetXPixels( aColor, 0x00, 0x00, 0xFF ); 3008 GetXPixels( aColor, 0x00, 0xFF, 0x00 ); 3009 GetXPixels( aColor, 0x00, 0xFF, 0xFF ); 3010 // GetXPixels( aColor, 0xFF, 0x00, 0x00 ); 3011 // GetXPixels( aColor, 0xFF, 0x00, 0xFF ); 3012 // GetXPixels( aColor, 0xFF, 0xFF, 0x00 ); 3013 // GetXPixels( aColor, 0xFF, 0xFF, 0xFF ); 3014 3015 // standard colors: 7 * 2 = 14 3016 // GetXPixels( aColor, 0x00, 0x00, 0x00 ); 3017 GetXPixels( aColor, 0x00, 0x00, 0x80 ); 3018 GetXPixels( aColor, 0x00, 0x80, 0x00 ); 3019 GetXPixels( aColor, 0x00, 0x80, 0x80 ); 3020 GetXPixels( aColor, 0x80, 0x00, 0x00 ); 3021 GetXPixels( aColor, 0x80, 0x00, 0x80 ); 3022 GetXPixels( aColor, 0x80, 0x80, 0x00 ); 3023 GetXPixels( aColor, 0x80, 0x80, 0x80 ); 3024 GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7 3025 3026 // cube: 6*6*6 - 8 = 208 3027 for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF 3028 for( g = 0; g < 0x100; g += 0x33 ) 3029 for( b = 0; b < 0x100; b += 0x33 ) 3030 GetXPixels( aColor, r, g, b ); 3031 3032 // gray: 16 - 6 = 10 3033 for( g = 0x11; g < 0xFF; g += 0x11 ) 3034 GetXPixels( aColor, g, g, g ); 3035 3036 // green: 16 - 6 = 10 3037 for( g = 0x11; g < 0xFF; g += 0x11 ) 3038 GetXPixels( aColor, 0, g, 0 ); 3039 3040 // red: 16 - 6 = 10 3041 for( r = 0x11; r < 0xFF; r += 0x11 ) 3042 GetXPixels( aColor, r, 0, 0 ); 3043 3044 // blue: 16 - 6 = 10 3045 for( b = 0x11; b < 0xFF; b += 0x11 ) 3046 GetXPixels( aColor, 0, 0, b ); 3047 } 3048 } 3049 3050 // PseudoColor 3051 SalColormap::SalColormap( const BitmapPalette &rPalette ) 3052 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3053 m_hColormap( None ), 3054 m_nWhitePixel( SALCOLOR_NONE ), 3055 m_nBlackPixel( SALCOLOR_NONE ), 3056 m_nUsed( rPalette.GetEntryCount() ), 3057 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ) 3058 { 3059 m_aPalette = std::vector<SalColor>(m_nUsed); 3060 3061 for( unsigned int i = 0; i < m_nUsed; i++ ) 3062 { 3063 const BitmapColor &rColor = rPalette[i]; 3064 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(), 3065 rColor.GetGreen(), 3066 rColor.GetBlue() ); 3067 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) ) 3068 m_nBlackPixel = i; 3069 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) ) 3070 m_nWhitePixel = i; 3071 } 3072 } 3073 3074 // MonoChrome 3075 SalColormap::SalColormap() 3076 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3077 m_hColormap( None ), 3078 m_nWhitePixel( 1 ), 3079 m_nBlackPixel( 0 ), 3080 m_nUsed( 2 ), 3081 m_nScreen( 0 ) 3082 { 3083 if( m_pDisplay ) 3084 m_nScreen = m_pDisplay->GetDefaultScreenNumber(); 3085 m_aPalette = std::vector<SalColor>(m_nUsed); 3086 3087 m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK; 3088 m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE; 3089 } 3090 3091 // TrueColor 3092 SalColormap::SalColormap( sal_uInt16 nDepth ) 3093 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3094 m_hColormap( None ), 3095 m_nWhitePixel( (1 << nDepth) - 1 ), 3096 m_nBlackPixel( 0x00000000 ), 3097 m_nUsed( 1 << nDepth ), 3098 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ) 3099 { 3100 const SalVisual *pVisual = &m_pDisplay->GetVisual( m_nScreen ); 3101 3102 if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth ) 3103 m_aVisual = *pVisual; 3104 else 3105 { 3106 XVisualInfo aVI; 3107 3108 if( !XMatchVisualInfo( m_pDisplay->GetDisplay(), 3109 m_pDisplay->GetDefaultScreenNumber(), 3110 nDepth, 3111 TrueColor, 3112 &aVI ) ) 3113 { 3114 aVI.visual = new Visual(); 3115 aVI.visualid = (VisualID)0; // beware of temporary destructor below 3116 aVI.screen = 0; 3117 aVI.depth = nDepth; 3118 aVI.c_class = TrueColor; 3119 if( 24 == nDepth ) // 888 3120 { 3121 aVI.red_mask = 0xFF0000; 3122 aVI.green_mask = 0x00FF00; 3123 aVI.blue_mask = 0x0000FF; 3124 } 3125 else if( 16 == nDepth ) // 565 3126 { 3127 aVI.red_mask = 0x00F800; 3128 aVI.green_mask = 0x0007E0; 3129 aVI.blue_mask = 0x00001F; 3130 } 3131 else if( 15 == nDepth ) // 555 3132 { 3133 aVI.red_mask = 0x007C00; 3134 aVI.green_mask = 0x0003E0; 3135 aVI.blue_mask = 0x00001F; 3136 } 3137 else if( 12 == nDepth ) // 444 3138 { 3139 aVI.red_mask = 0x000F00; 3140 aVI.green_mask = 0x0000F0; 3141 aVI.blue_mask = 0x00000F; 3142 } 3143 else if( 8 == nDepth ) // 332 3144 { 3145 aVI.red_mask = 0x0000E0; 3146 aVI.green_mask = 0x00001C; 3147 aVI.blue_mask = 0x000003; 3148 } 3149 else 3150 { 3151 aVI.red_mask = 0x000000; 3152 aVI.green_mask = 0x000000; 3153 aVI.blue_mask = 0x000000; 3154 } 3155 aVI.colormap_size = 0; 3156 aVI.bits_per_rgb = 8; 3157 3158 aVI.visual->ext_data = NULL; 3159 aVI.visual->visualid = aVI.visualid; 3160 aVI.visual->c_class = aVI.c_class; 3161 aVI.visual->red_mask = aVI.red_mask; 3162 aVI.visual->green_mask = aVI.green_mask; 3163 aVI.visual->blue_mask = aVI.blue_mask; 3164 aVI.visual->bits_per_rgb = aVI.bits_per_rgb; 3165 aVI.visual->map_entries = aVI.colormap_size; 3166 3167 m_aVisual = SalVisual( &aVI ); 3168 // give ownership of constructed Visual() to m_aVisual 3169 // see SalVisual destructor 3170 m_aVisual.visualid = (VisualID)-1; 3171 m_aVisual.screen = -1; 3172 } 3173 else 3174 m_aVisual = SalVisual( &aVI ); 3175 } 3176 } 3177 3178 SalColormap::~SalColormap() 3179 { 3180 #ifdef DBG_UTIL 3181 m_hColormap = (Colormap)ILLEGAL_POINTER; 3182 m_pDisplay = (SalDisplay*)ILLEGAL_POINTER; 3183 #endif 3184 } 3185 3186 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3187 void SalColormap::SetPalette( const BitmapPalette &rPalette ) 3188 { 3189 if( this != &GetX11SalData()->GetDisplay()->GetColormap(m_nScreen) ) 3190 { 3191 m_nBlackPixel = SALCOLOR_NONE; 3192 m_nWhitePixel = SALCOLOR_NONE; 3193 } 3194 3195 if( rPalette.GetEntryCount() > m_nUsed ) 3196 { 3197 m_nBlackPixel = SALCOLOR_NONE; 3198 m_nWhitePixel = SALCOLOR_NONE; 3199 m_nUsed = rPalette.GetEntryCount(); 3200 m_aPalette = std::vector<SalColor>(m_nUsed); 3201 } 3202 3203 for( int i = 0; i < rPalette.GetEntryCount(); i++ ) 3204 { 3205 const BitmapColor &rColor = rPalette[i]; 3206 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(), 3207 rColor.GetGreen(), 3208 rColor.GetBlue() ); 3209 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) ) 3210 m_nBlackPixel = i; 3211 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) ) 3212 m_nWhitePixel = i; 3213 } 3214 } 3215 3216 void SalColormap::GetPalette() 3217 { 3218 Pixel i; 3219 m_aPalette = std::vector<SalColor>(m_nUsed); 3220 3221 XColor *aColor = new XColor[m_nUsed]; 3222 3223 for( i = 0; i < m_nUsed; i++ ) 3224 { 3225 aColor[i].red = aColor[i].green = aColor[i].blue = 0; 3226 aColor[i].pixel = i; 3227 } 3228 3229 XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed ); 3230 3231 for( i = 0; i < m_nUsed; i++ ) 3232 { 3233 m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red >> 8, 3234 aColor[i].green >> 8, 3235 aColor[i].blue >> 8 ); 3236 } 3237 3238 delete [] aColor; 3239 } 3240 3241 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3242 static sal_uInt16 sal_Lookup( const std::vector<SalColor>& rPalette, 3243 int r, int g, int b, 3244 Pixel nUsed ) 3245 { 3246 sal_uInt16 nPixel = 0; 3247 int nBest = ColorDiff( rPalette[0], r, g, b ); 3248 3249 for( sal_uInt16 i = 1; i < nUsed; i++ ) 3250 { 3251 int n = ColorDiff( rPalette[i], r, g, b ); 3252 3253 if( n < nBest ) 3254 { 3255 if( !n ) 3256 return i; 3257 3258 nPixel = i; 3259 nBest = n; 3260 } 3261 } 3262 return nPixel; 3263 } 3264 3265 void SalColormap::GetLookupTable() 3266 { 3267 m_aLookupTable = std::vector<sal_uInt16>(16*16*16); 3268 3269 int i = 0; 3270 for( int r = 0; r < 256; r += 17 ) 3271 for( int g = 0; g < 256; g += 17 ) 3272 for( int b = 0; b < 256; b += 17 ) 3273 m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed ); 3274 } 3275 3276 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3277 SalColor SalColormap::GetColor( Pixel nPixel ) const 3278 { 3279 if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK; 3280 if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE; 3281 3282 if( m_aVisual.GetVisual() ) 3283 { 3284 if( m_aVisual.GetClass() == TrueColor ) 3285 return m_aVisual.GetTCColor( nPixel ); 3286 3287 if( m_aPalette.empty() 3288 && m_hColormap 3289 #ifdef PSEUDOCOLOR12 3290 && m_aVisual.GetDepth() <= 12 3291 #else 3292 && m_aVisual.GetDepth() <= 8 3293 #endif 3294 && m_aVisual.GetClass() == PseudoColor ) 3295 ((SalColormap*)this)->GetPalette(); 3296 } 3297 3298 if( !m_aPalette.empty() && nPixel < m_nUsed ) 3299 return m_aPalette[nPixel]; 3300 3301 if( m_hColormap ) 3302 { 3303 DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" ); 3304 return nPixel; 3305 } 3306 3307 // DirectColor, StaticColor, StaticGray, GrayScale 3308 XColor aColor; 3309 3310 aColor.pixel = nPixel; 3311 3312 XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor ); 3313 3314 return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 ); 3315 } 3316 3317 inline sal_Bool SalColormap::GetXPixel( XColor &rColor, 3318 int r, 3319 int g, 3320 int b ) const 3321 { 3322 rColor.red = r * 257; 3323 rColor.green = g * 257; 3324 rColor.blue = b * 257; 3325 return XAllocColor( GetXDisplay(), m_hColormap, &rColor ); 3326 } 3327 3328 sal_Bool SalColormap::GetXPixels( XColor &rColor, 3329 int r, 3330 int g, 3331 int b ) const 3332 { 3333 if( !GetXPixel( rColor, r, g, b ) ) 3334 return sal_False; 3335 if( rColor.pixel & 1 ) 3336 return sal_True; 3337 return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF ); 3338 } 3339 3340 Pixel SalColormap::GetPixel( SalColor nSalColor ) const 3341 { 3342 if( SALCOLOR_NONE == nSalColor ) return 0; 3343 if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel; 3344 if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel; 3345 3346 if( m_aVisual.GetClass() == TrueColor ) 3347 return m_aVisual.GetTCPixel( nSalColor ); 3348 3349 if( m_aLookupTable.empty() ) 3350 { 3351 if( m_aPalette.empty() 3352 && m_hColormap 3353 #ifdef PSEUDOCOLOR12 3354 && m_aVisual.GetDepth() <= 12 3355 #else 3356 && m_aVisual.GetDepth() <= 8 3357 #endif 3358 && m_aVisual.GetClass() == PseudoColor ) // what else ??? 3359 ((SalColormap*)this)->GetPalette(); 3360 3361 if( !m_aPalette.empty() ) 3362 for( Pixel i = 0; i < m_nUsed; i++ ) 3363 if( m_aPalette[i] == nSalColor ) 3364 return i; 3365 3366 if( m_hColormap ) 3367 { 3368 // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor) 3369 XColor aColor; 3370 3371 if( GetXPixel( aColor, 3372 SALCOLOR_RED ( nSalColor ), 3373 SALCOLOR_GREEN( nSalColor ), 3374 SALCOLOR_BLUE ( nSalColor ) ) ) 3375 { 3376 if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] ) 3377 { 3378 const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor; 3379 3380 if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] ) 3381 { 3382 XColor aInversColor; 3383 3384 SalColor nInversColor = nSalColor ^ 0xFFFFFF; 3385 3386 GetXPixel( aInversColor, 3387 SALCOLOR_RED ( nInversColor ), 3388 SALCOLOR_GREEN( nInversColor ), 3389 SALCOLOR_BLUE ( nInversColor ) ); 3390 3391 if( !m_aPalette[aInversColor.pixel] ) 3392 const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor; 3393 #ifdef DBG_UTIL 3394 else 3395 fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n", 3396 static_cast< unsigned long >(nSalColor), aColor.pixel, 3397 static_cast< unsigned long >(nInversColor), aInversColor.pixel); 3398 #endif 3399 } 3400 } 3401 3402 return aColor.pixel; 3403 } 3404 3405 #ifdef DBG_UTIL 3406 fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n", 3407 static_cast< unsigned long >(nSalColor) ); 3408 #endif 3409 } 3410 3411 if( m_aPalette.empty() ) 3412 { 3413 #ifdef DBG_UTIL 3414 fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n", 3415 static_cast< unsigned long >(nSalColor)); 3416 #endif 3417 return nSalColor; 3418 } 3419 3420 ((SalColormap*)this)->GetLookupTable(); 3421 } 3422 3423 // Colormatching ueber Palette 3424 sal_uInt16 r = SALCOLOR_RED ( nSalColor ); 3425 sal_uInt16 g = SALCOLOR_GREEN( nSalColor ); 3426 sal_uInt16 b = SALCOLOR_BLUE ( nSalColor ); 3427 return m_aLookupTable[ (((r+8)/17) << 8) 3428 + (((g+8)/17) << 4) 3429 + ((b+8)/17) ]; 3430 } 3431 3432