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