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_AUTOSCROLL_N: 2013 MAKE_CURSOR(asn_ ); 2014 break; 2015 case POINTER_AUTOSCROLL_S: 2016 MAKE_CURSOR( ass_ ); 2017 break; 2018 case POINTER_AUTOSCROLL_W: 2019 MAKE_CURSOR( asw_ ); 2020 break; 2021 case POINTER_AUTOSCROLL_E: 2022 MAKE_CURSOR( ase_ ); 2023 break; 2024 case POINTER_AUTOSCROLL_NW: 2025 MAKE_CURSOR( asnw_ ); 2026 break; 2027 case POINTER_AUTOSCROLL_NE: 2028 MAKE_CURSOR( asne_ ); 2029 break; 2030 case POINTER_AUTOSCROLL_SW: 2031 MAKE_CURSOR( assw_ ); 2032 break; 2033 case POINTER_AUTOSCROLL_SE: 2034 MAKE_CURSOR( asse_ ); 2035 break; 2036 case POINTER_AUTOSCROLL_NS: 2037 MAKE_CURSOR( asns_ ); 2038 break; 2039 case POINTER_AUTOSCROLL_WE: 2040 MAKE_CURSOR( aswe_ ); 2041 break; 2042 case POINTER_AUTOSCROLL_NSWE: 2043 MAKE_CURSOR( asnswe_ ); 2044 break; 2045 case POINTER_AIRBRUSH: 2046 MAKE_CURSOR( airbrush_ ); 2047 break; 2048 case POINTER_TEXT_VERTICAL: 2049 MAKE_CURSOR( vertcurs_ ); 2050 break; 2051 2052 // --> FME 2004-07-30 #i32329# Enhanced table selection 2053 case POINTER_TAB_SELECT_S: 2054 MAKE_CURSOR( tblsels_ ); 2055 break; 2056 case POINTER_TAB_SELECT_E: 2057 MAKE_CURSOR( tblsele_ ); 2058 break; 2059 case POINTER_TAB_SELECT_SE: 2060 MAKE_CURSOR( tblselse_ ); 2061 break; 2062 case POINTER_TAB_SELECT_W: 2063 MAKE_CURSOR( tblselw_ ); 2064 break; 2065 case POINTER_TAB_SELECT_SW: 2066 MAKE_CURSOR( tblselsw_ ); 2067 break; 2068 // <-- 2069 2070 // --> FME 2004-08-16 #i20119# Paintbrush tool 2071 case POINTER_PAINTBRUSH : 2072 MAKE_CURSOR( paintbrush_ ); 2073 break; 2074 // <-- 2075 2076 default: 2077 DBG_ERROR("pointer not implemented"); 2078 aCur = XCreateFontCursor( pDisp_, XC_arrow ); 2079 break; 2080 } 2081 2082 if( None == aCur ) 2083 { 2084 XColor aBlack, aWhite, aDummy; 2085 Colormap hColormap = GetColormap(m_nDefaultScreen).GetXColormap(); 2086 2087 XAllocNamedColor( pDisp_, hColormap, "black", &aBlack, &aDummy ); 2088 XAllocNamedColor( pDisp_, hColormap, "white", &aWhite, &aDummy ); 2089 2090 aCur = XCreatePixmapCursor( pDisp_, 2091 aCursBitmap, aMaskBitmap, 2092 &aBlack, &aWhite, 2093 nXHot, nYHot ); 2094 2095 XFreePixmap( pDisp_, aCursBitmap ); 2096 XFreePixmap( pDisp_, aMaskBitmap ); 2097 } 2098 2099 return aCur; 2100 } 2101 2102 int SalDisplay::CaptureMouse( SalFrame *pCapture ) 2103 { 2104 if( !pCapture ) 2105 { 2106 m_pCapture = NULL; 2107 XUngrabPointer( GetDisplay(), CurrentTime ); 2108 XFlush( GetDisplay() ); 2109 return 0; 2110 } 2111 2112 m_pCapture = NULL; 2113 2114 // FIXME: get rid of X11SalFrame 2115 const SystemEnvData* pEnvData = pCapture->GetSystemData(); 2116 int ret = XGrabPointer( GetDisplay(), 2117 (XLIB_Window)pEnvData->aWindow, 2118 False, 2119 PointerMotionMask| ButtonPressMask|ButtonReleaseMask, 2120 GrabModeAsync, 2121 GrabModeAsync, 2122 None, 2123 static_cast<X11SalFrame*>(pCapture)->GetCursor(), 2124 CurrentTime ); 2125 2126 if( ret != GrabSuccess ) 2127 { 2128 DBG_ASSERT( 1, "SalDisplay::CaptureMouse could not grab pointer\n"); 2129 return -1; 2130 } 2131 2132 m_pCapture = pCapture; 2133 return 1; 2134 } 2135 2136 // Events 2137 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2138 2139 void SalDisplay::SendInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 2140 { 2141 if( osl_acquireMutex( hEventGuard_ ) ) 2142 { 2143 m_aUserEvents.push_back( SalUserEvent( pFrame, pData, nEvent ) ); 2144 2145 // Notify SalXLib::Yield() of a pending event. 2146 pXLib_->PostUserEvent(); 2147 2148 osl_releaseMutex( hEventGuard_ ); 2149 } 2150 else { 2151 DBG_ASSERT( 1, "SalDisplay::SendInternalEvent !acquireMutex\n" ); 2152 } 2153 } 2154 2155 void SalDisplay::CancelInternalEvent( SalFrame* pFrame, void* pData, sal_uInt16 nEvent ) 2156 { 2157 if( osl_acquireMutex( hEventGuard_ ) ) 2158 { 2159 if( ! m_aUserEvents.empty() ) 2160 { 2161 std::list< SalUserEvent >::iterator it, next; 2162 next = m_aUserEvents.begin(); 2163 do 2164 { 2165 it = next++; 2166 if( it->m_pFrame == pFrame && 2167 it->m_pData == pData && 2168 it->m_nEvent == nEvent ) 2169 { 2170 m_aUserEvents.erase( it ); 2171 } 2172 } while( next != m_aUserEvents.end() ); 2173 } 2174 2175 osl_releaseMutex( hEventGuard_ ); 2176 } 2177 else { 2178 DBG_ASSERT( 1, "SalDisplay::CancelInternalEvent !acquireMutex\n" ); 2179 } 2180 } 2181 2182 sal_Bool SalX11Display::IsEvent() 2183 { 2184 sal_Bool bRet = sal_False; 2185 2186 if( osl_acquireMutex( hEventGuard_ ) ) 2187 { 2188 if( m_aUserEvents.begin() != m_aUserEvents.end() ) 2189 bRet = sal_True; 2190 osl_releaseMutex( hEventGuard_ ); 2191 } 2192 2193 if( bRet || XEventsQueued( pDisp_, QueuedAlready ) ) 2194 return sal_True; 2195 2196 XFlush( pDisp_ ); 2197 return sal_False; 2198 } 2199 2200 bool SalDisplay::DispatchInternalEvent() 2201 { 2202 SalFrame* pFrame = NULL; 2203 void* pData = NULL; 2204 sal_uInt16 nEvent = 0; 2205 2206 if( osl_acquireMutex( hEventGuard_ ) ) 2207 { 2208 if( m_aUserEvents.begin() != m_aUserEvents.end() ) 2209 { 2210 pFrame = m_aUserEvents.front().m_pFrame; 2211 pData = m_aUserEvents.front().m_pData; 2212 nEvent = m_aUserEvents.front().m_nEvent; 2213 2214 m_aUserEvents.pop_front(); 2215 } 2216 osl_releaseMutex( hEventGuard_ ); 2217 } 2218 else { 2219 DBG_ASSERT( 1, "SalDisplay::Yield !acquireMutex\n" ); 2220 } 2221 2222 if( pFrame ) 2223 pFrame->CallCallback( nEvent, pData ); 2224 2225 return pFrame != NULL; 2226 } 2227 2228 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2229 2230 void SalX11Display::Yield() 2231 { 2232 if( DispatchInternalEvent() ) 2233 return; 2234 2235 XEvent aEvent; 2236 DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() == 2237 vos::OThread::getCurrentIdentifier(), 2238 "will crash soon since solar mutex not locked in SalDisplay::Yield" ); 2239 2240 XNextEvent( pDisp_, &aEvent ); 2241 2242 Dispatch( &aEvent ); 2243 2244 #ifdef DBG_UTIL 2245 if( pXLib_->HasXErrorOccured() ) 2246 { 2247 XFlush( pDisp_ ); 2248 PrintEvent( "SalDisplay::Yield (WasXError)", &aEvent ); 2249 } 2250 #endif 2251 pXLib_->ResetXErrorOccured(); 2252 } 2253 2254 long SalX11Display::Dispatch( XEvent *pEvent ) 2255 { 2256 if( pEvent->type == XLIB_KeyPress || pEvent->type == KeyRelease ) 2257 { 2258 XLIB_Window aWindow = pEvent->xkey.window; 2259 2260 std::list< SalFrame* >::const_iterator it; 2261 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2262 { 2263 const X11SalFrame* pFrame = static_cast< const X11SalFrame* >(*it); 2264 if( pFrame->GetWindow() == aWindow || pFrame->GetShellWindow() == aWindow ) 2265 { 2266 aWindow = pFrame->GetWindow(); 2267 break; 2268 } 2269 } 2270 if( it != m_aFrames.end() ) 2271 { 2272 if ( mpInputMethod->FilterEvent( pEvent , aWindow ) ) 2273 return 0; 2274 } 2275 } 2276 else 2277 if ( mpInputMethod->FilterEvent( pEvent, None ) ) 2278 return 0; 2279 2280 SalInstance* pInstance = GetSalData()->m_pInstance; 2281 pInstance->CallEventCallback( pEvent, sizeof( XEvent ) ); 2282 2283 switch( pEvent->type ) 2284 { 2285 case MotionNotify: 2286 while( XCheckWindowEvent( pEvent->xany.display, 2287 pEvent->xany.window, 2288 ButtonMotionMask, 2289 pEvent ) ) 2290 ; 2291 m_nLastUserEventTime = pEvent->xmotion.time; 2292 break; 2293 case PropertyNotify: 2294 if( pEvent->xproperty.atom == getWMAdaptor()->getAtom( WMAdaptor::VCL_SYSTEM_SETTINGS ) ) 2295 { 2296 for( unsigned int i = 0; i < m_aScreens.size(); i++ ) 2297 { 2298 if( pEvent->xproperty.window == m_aScreens[i].m_aRefWindow ) 2299 { 2300 std::list< SalFrame* >::const_iterator it; 2301 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2302 (*it)->CallCallback( SALEVENT_SETTINGSCHANGED, NULL ); 2303 return 0; 2304 } 2305 } 2306 } 2307 break; 2308 case MappingNotify: 2309 if( MappingKeyboard == pEvent->xmapping.request || 2310 MappingModifier == pEvent->xmapping.request ) 2311 { 2312 XRefreshKeyboardMapping( &pEvent->xmapping ); 2313 if( MappingModifier == pEvent->xmapping.request ) 2314 ModifierMapping(); 2315 if( MappingKeyboard == pEvent->xmapping.request ) // refresh mapping 2316 GetKeyboardName( sal_True ); 2317 } 2318 break; 2319 case ButtonPress: 2320 case ButtonRelease: 2321 m_nLastUserEventTime = pEvent->xbutton.time; 2322 break; 2323 case XLIB_KeyPress: 2324 case KeyRelease: 2325 m_nLastUserEventTime = pEvent->xkey.time; 2326 break; 2327 default: 2328 2329 if ( GetKbdExtension()->UseExtension() 2330 && GetKbdExtension()->GetEventBase() == pEvent->type ) 2331 { 2332 GetKbdExtension()->Dispatch( pEvent ); 2333 return 1; 2334 } 2335 break; 2336 } 2337 2338 std::list< SalFrame* >::iterator it; 2339 for( it = m_aFrames.begin(); it != m_aFrames.end(); ++it ) 2340 { 2341 X11SalFrame* pFrame = static_cast< X11SalFrame* >(*it); 2342 XLIB_Window aDispatchWindow = pEvent->xany.window; 2343 if( pFrame->GetWindow() == aDispatchWindow 2344 || pFrame->GetShellWindow() == aDispatchWindow 2345 || pFrame->GetForeignParent() == aDispatchWindow 2346 ) 2347 { 2348 return pFrame->Dispatch( pEvent ); 2349 } 2350 if( pEvent->type == ConfigureNotify && pEvent->xconfigure.window == pFrame->GetStackingWindow() ) 2351 { 2352 return pFrame->Dispatch( pEvent ); 2353 } 2354 } 2355 2356 // dispatch to salobjects 2357 X11SalObject::Dispatch( pEvent ); 2358 2359 // is this perhaps a root window that changed size ? 2360 processRandREvent( pEvent ); 2361 2362 return 0; 2363 } 2364 2365 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2366 void SalDisplay::PrintEvent( const ByteString &rComment, 2367 XEvent *pEvent ) const 2368 { 2369 if( pEvent->type <= MappingNotify ) 2370 { 2371 fprintf( stderr, "[%s] %s s=%d w=%ld\n", 2372 rComment.GetBuffer(), 2373 EventNames[pEvent->type], 2374 pEvent->xany.send_event, 2375 pEvent->xany.window ); 2376 2377 switch( pEvent->type ) 2378 { 2379 case XLIB_KeyPress: 2380 case KeyRelease: 2381 fprintf( stderr, "\t\ts=%d c=%d\n", 2382 pEvent->xkey.state, 2383 pEvent->xkey.keycode ); 2384 break; 2385 2386 case ButtonPress: 2387 case ButtonRelease: 2388 fprintf( stderr, "\t\ts=%d b=%d x=%d y=%d rx=%d ry=%d\n", 2389 pEvent->xbutton.state, 2390 pEvent->xbutton.button, 2391 pEvent->xbutton.x, 2392 pEvent->xbutton.y, 2393 pEvent->xbutton.x_root, 2394 pEvent->xbutton.y_root ); 2395 break; 2396 2397 case MotionNotify: 2398 fprintf( stderr, "\t\ts=%d x=%d y=%d\n", 2399 pEvent->xmotion.state, 2400 pEvent->xmotion.x, 2401 pEvent->xmotion.y ); 2402 break; 2403 2404 case EnterNotify: 2405 case LeaveNotify: 2406 fprintf( stderr, "\t\tm=%d f=%d x=%d y=%d\n", 2407 pEvent->xcrossing.mode, 2408 pEvent->xcrossing.focus, 2409 pEvent->xcrossing.x, 2410 pEvent->xcrossing.y ); 2411 break; 2412 2413 case FocusIn: 2414 case FocusOut: 2415 fprintf( stderr, "\t\tm=%d d=%d\n", 2416 pEvent->xfocus.mode, 2417 pEvent->xfocus.detail ); 2418 break; 2419 2420 case Expose: 2421 case GraphicsExpose: 2422 fprintf( stderr, "\t\tc=%d %d*%d %d+%d\n", 2423 pEvent->xexpose.count, 2424 pEvent->xexpose.width, 2425 pEvent->xexpose.height, 2426 pEvent->xexpose.x, 2427 pEvent->xexpose.y ); 2428 break; 2429 2430 case VisibilityNotify: 2431 fprintf( stderr, "\t\ts=%d\n", 2432 pEvent->xvisibility.state ); 2433 break; 2434 2435 case CreateNotify: 2436 case DestroyNotify: 2437 break; 2438 2439 case MapNotify: 2440 case UnmapNotify: 2441 break; 2442 2443 case ReparentNotify: 2444 fprintf( stderr, "\t\tp=%d x=%d y=%d\n", 2445 sal::static_int_cast< int >(pEvent->xreparent.parent), 2446 pEvent->xreparent.x, 2447 pEvent->xreparent.y ); 2448 break; 2449 2450 case ConfigureNotify: 2451 fprintf( stderr, "\t\tb=%d %d*%d %d+%d\n", 2452 pEvent->xconfigure.border_width, 2453 pEvent->xconfigure.width, 2454 pEvent->xconfigure.height, 2455 pEvent->xconfigure.x, 2456 pEvent->xconfigure.y ); 2457 break; 2458 2459 case PropertyNotify: 2460 fprintf( stderr, "\t\ta=%s (0x%X)\n", 2461 GetAtomName( pDisp_, pEvent->xproperty.atom ), 2462 sal::static_int_cast< unsigned int >( 2463 pEvent->xproperty.atom) ); 2464 break; 2465 2466 case ColormapNotify: 2467 fprintf( stderr, "\t\tc=%ld n=%d s=%d\n", 2468 pEvent->xcolormap.colormap, 2469 pEvent->xcolormap.c_new, 2470 pEvent->xcolormap.state ); 2471 break; 2472 2473 case ClientMessage: 2474 fprintf( stderr, "\t\ta=%s (0x%X) f=%i [0x%lX,0x%lX,0x%lX,0x%lX,0x%lX])\n", 2475 GetAtomName( pDisp_, pEvent->xclient.message_type ), 2476 sal::static_int_cast< unsigned int >( 2477 pEvent->xclient.message_type), 2478 pEvent->xclient.format, 2479 pEvent->xclient.data.l[0], 2480 pEvent->xclient.data.l[1], 2481 pEvent->xclient.data.l[2], 2482 pEvent->xclient.data.l[3], 2483 pEvent->xclient.data.l[4] ); 2484 break; 2485 2486 case MappingNotify: 2487 fprintf( stderr, "\t\tr=%sd\n", 2488 MappingModifier == pEvent->xmapping.request 2489 ? "MappingModifier" 2490 : MappingKeyboard == pEvent->xmapping.request 2491 ? "MappingKeyboard" 2492 : "MappingPointer" ); 2493 2494 break; 2495 } 2496 } 2497 else 2498 fprintf( stderr, "[%s] %d s=%d w=%ld\n", 2499 rComment.GetBuffer(), 2500 pEvent->type, 2501 pEvent->xany.send_event, 2502 pEvent->xany.window ); 2503 } 2504 2505 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2506 void SalDisplay::PrintInfo() const 2507 { 2508 if( IsDisplay() ) 2509 { 2510 fprintf( stderr, "\n" ); 2511 fprintf( stderr, "Environment\n" ); 2512 fprintf( stderr, "\t$XENVIRONMENT \t\"%s\"\n", 2513 GetEnv( "XENVIRONMENT" ) ); 2514 fprintf( stderr, "\t$DISPLAY \t\"%s\"\n", 2515 GetEnv( "DISPLAY" ) ); 2516 fprintf( stderr, "\t$SAL_VISUAL \t\"%s\"\n", 2517 GetEnv( "SAL_VISUAL" ) ); 2518 fprintf( stderr, "\t$SAL_FONTPATH \t\"%s\"\n", 2519 GetEnv( "SAL_FONTPATH" ) ); 2520 fprintf( stderr, "\t$SAL_NOSEGV \t\"%s\"\n", 2521 GetEnv( "SAL_NOSEGV" ) ); 2522 fprintf( stderr, "\t$SAL_IGNOREXERRORS\t\"%s\"\n", 2523 GetEnv( "SAL_IGNOREXERRORS" ) ); 2524 fprintf( stderr, "\t$SAL_PROPERTIES \t\"%s\"\n", 2525 GetEnv( "SAL_PROPERTIES" ) ); 2526 fprintf( stderr, "\t$SAL_WM \t\"%s\"\n", 2527 GetEnv( "SAL_WM" ) ); 2528 fprintf( stderr, "\t$SAL_SYNCHRONIZE \t\"%s\"\n", 2529 GetEnv( "SAL_SYNCHRONIZE" ) ); 2530 2531 char sHostname[ 120 ]; 2532 gethostname (sHostname, 120 ); 2533 fprintf( stderr, "Client\n" ); 2534 fprintf( stderr, "\tHost \t\"%s\"\n", 2535 sHostname ); 2536 2537 fprintf( stderr, "Display\n" ); 2538 fprintf( stderr, "\tHost \t\"%s\"\n", 2539 DisplayString(pDisp_) ); 2540 fprintf( stderr, "\tVendor (Release) \t\"%s (%d)\"\n", 2541 ServerVendor(pDisp_), VendorRelease(pDisp_) ); 2542 fprintf( stderr, "\tProtocol \t%d.%d\n", 2543 ProtocolVersion(pDisp_), ProtocolRevision(pDisp_) ); 2544 fprintf( stderr, "\tScreen (count,def)\t%d (%d,%d)\n", 2545 m_nDefaultScreen, ScreenCount(pDisp_), DefaultScreen(pDisp_) ); 2546 fprintf( stderr, "\tshift ctrl alt \t%s (0x%X) %s (0x%X) %s (0x%X)\n", 2547 KeyStr( nShiftKeySym_ ), sal::static_int_cast< unsigned int >(nShiftKeySym_), 2548 KeyStr( nCtrlKeySym_ ), sal::static_int_cast< unsigned int >(nCtrlKeySym_), 2549 KeyStr( nMod1KeySym_ ), sal::static_int_cast< unsigned int >(nMod1KeySym_) ); 2550 if( XExtendedMaxRequestSize(pDisp_) * 4 ) 2551 fprintf( stderr, "\tXMaxRequestSize \t%ld %ld [bytes]\n", 2552 XMaxRequestSize(pDisp_) * 4, XExtendedMaxRequestSize(pDisp_) * 4 ); 2553 if( GetProperties() != PROPERTY_DEFAULT ) 2554 fprintf( stderr, "\tProperties \t0x%lX\n", GetProperties() ); 2555 if( eWindowManager_ != otherwm ) 2556 fprintf( stderr, "\tWindowmanager \t%d\n", eWindowManager_ ); 2557 fprintf( stderr, "\tWMName \t%s\n", rtl::OUStringToOString( getWMAdaptor()->getWindowManagerName(), osl_getThreadTextEncoding() ).getStr() ); 2558 } 2559 fprintf( stderr, "Screen\n" ); 2560 fprintf( stderr, "\tResolution/Size \t%ld*%ld %ld*%ld %.1lf\"\n", 2561 aResolution_.A(), aResolution_.B(), 2562 m_aScreens[m_nDefaultScreen].m_aSize.Width(), m_aScreens[m_nDefaultScreen].m_aSize.Height(), 2563 Hypothenuse( DisplayWidthMM ( pDisp_, m_nDefaultScreen ), 2564 DisplayHeightMM( pDisp_, m_nDefaultScreen ) ) / 25.4 ); 2565 fprintf( stderr, "\tBlack&White \t%lu %lu\n", 2566 GetColormap(m_nDefaultScreen).GetBlackPixel(), GetColormap(m_nDefaultScreen).GetWhitePixel() ); 2567 fprintf( stderr, "\tRGB \t0x%lx 0x%lx 0x%lx\n", 2568 GetVisual(m_nDefaultScreen).red_mask, GetVisual(m_nDefaultScreen).green_mask, GetVisual(m_nDefaultScreen).blue_mask ); 2569 fprintf( stderr, "\tVisual \t%d-bit %s ID=0x%x\n", 2570 GetVisual(m_nDefaultScreen).GetDepth(), 2571 VisualClassName[ GetVisual(m_nDefaultScreen).GetClass() ], 2572 sal::static_int_cast< unsigned int >(GetVisual(m_nDefaultScreen).GetVisualId()) ); 2573 } 2574 2575 int SalDisplay::addXineramaScreenUnique( long i_nX, long i_nY, long i_nWidth, long i_nHeight ) 2576 { 2577 // see if any frame buffers are at the same coordinates 2578 // this can happen with weird configuration e.g. on 2579 // XFree86 and Clone displays 2580 const size_t nScreens = m_aXineramaScreens.size(); 2581 for( size_t n = 0; n < nScreens; n++ ) 2582 { 2583 if( m_aXineramaScreens[n].Left() == i_nX && 2584 m_aXineramaScreens[n].Top() == i_nY ) 2585 { 2586 if( m_aXineramaScreens[n].GetWidth() < i_nWidth || 2587 m_aXineramaScreens[n].GetHeight() < i_nHeight ) 2588 { 2589 m_aXineramaScreens[n].SetSize( Size( i_nWidth, i_nHeight ) ); 2590 } 2591 return (int)n; 2592 } 2593 } 2594 m_aXineramaScreens.push_back( Rectangle( Point( i_nX, i_nY ), Size( i_nWidth, i_nHeight ) ) ); 2595 return (int)m_aXineramaScreens.size()-1; 2596 } 2597 2598 void SalDisplay::InitXinerama() 2599 { 2600 if( m_aScreens.size() > 1 ) 2601 { 2602 m_bXinerama = false; 2603 return; // multiple screens mean no xinerama 2604 } 2605 #ifdef USE_XINERAMA 2606 #if defined(USE_XINERAMA_XSUN) 2607 int nFramebuffers = 1; 2608 if( XineramaGetState( pDisp_, m_nDefaultScreen ) ) 2609 { 2610 XRectangle pFramebuffers[MAXFRAMEBUFFERS]; 2611 unsigned char hints[MAXFRAMEBUFFERS]; 2612 int result = XineramaGetInfo( pDisp_, 2613 m_nDefaultScreen, 2614 pFramebuffers, 2615 hints, 2616 &nFramebuffers ); 2617 if( result > 0 && nFramebuffers > 1 ) 2618 { 2619 m_bXinerama = true; 2620 m_aXineramaScreens = std::vector<Rectangle>(); 2621 for( int i = 0; i < nFramebuffers; i++ ) 2622 addXineramaScreenUnique( pFramebuffers[i].x, 2623 pFramebuffers[i].y, 2624 pFramebuffers[i].width, 2625 pFramebuffers[i].height ); 2626 } 2627 } 2628 #elif defined(USE_XINERAMA_XORG) 2629 if( XineramaIsActive( pDisp_ ) ) 2630 { 2631 int nFramebuffers = 1; 2632 XineramaScreenInfo* pScreens = XineramaQueryScreens( pDisp_, &nFramebuffers ); 2633 if( pScreens ) 2634 { 2635 if( nFramebuffers > 1 ) 2636 { 2637 m_aXineramaScreens = std::vector<Rectangle>(); 2638 for( int i = 0; i < nFramebuffers; i++ ) 2639 { 2640 addXineramaScreenUnique( pScreens[i].x_org, 2641 pScreens[i].y_org, 2642 pScreens[i].width, 2643 pScreens[i].height ); 2644 } 2645 m_bXinerama = m_aXineramaScreens.size() > 1; 2646 } 2647 XFree( pScreens ); 2648 } 2649 } 2650 #endif 2651 #if OSL_DEBUG_LEVEL > 1 2652 if( m_bXinerama ) 2653 { 2654 for( std::vector< Rectangle >::const_iterator it = m_aXineramaScreens.begin(); it != m_aXineramaScreens.end(); ++it ) 2655 fprintf( stderr, "Xinerama screen: %ldx%ld+%ld+%ld\n", it->GetWidth(), it->GetHeight(), it->Left(), it->Top() ); 2656 } 2657 #endif 2658 #endif // USE_XINERAMA 2659 } 2660 2661 void SalDisplay::registerFrame( SalFrame* pFrame ) 2662 { 2663 m_aFrames.push_front( pFrame ); 2664 } 2665 2666 void SalDisplay::deregisterFrame( SalFrame* pFrame ) 2667 { 2668 if( osl_acquireMutex( hEventGuard_ ) ) 2669 { 2670 std::list< SalUserEvent >::iterator it = m_aUserEvents.begin(); 2671 while ( it != m_aUserEvents.end() ) 2672 { 2673 if( it->m_pFrame == pFrame ) 2674 it = m_aUserEvents.erase( it ); 2675 else 2676 ++it; 2677 } 2678 osl_releaseMutex( hEventGuard_ ); 2679 } 2680 else { 2681 DBG_ERROR( "SalDisplay::deregisterFrame !acquireMutex\n" ); 2682 } 2683 2684 m_aFrames.remove( pFrame ); 2685 } 2686 2687 2688 extern "C" 2689 { 2690 static Bool timestamp_predicate( Display*, XEvent* i_pEvent, XPointer i_pArg ) 2691 { 2692 SalDisplay* pSalDisplay = reinterpret_cast<SalDisplay*>(i_pArg); 2693 if( i_pEvent->type == PropertyNotify && 2694 i_pEvent->xproperty.window == pSalDisplay->GetDrawable( pSalDisplay->GetDefaultScreenNumber() ) && 2695 i_pEvent->xproperty.atom == pSalDisplay->getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ) 2696 ) 2697 return True; 2698 2699 return False; 2700 } 2701 } 2702 2703 XLIB_Time SalDisplay::GetLastUserEventTime( bool i_bAlwaysReget ) const 2704 { 2705 if( m_nLastUserEventTime == CurrentTime || i_bAlwaysReget ) 2706 { 2707 // get current server time 2708 unsigned char c = 0; 2709 XEvent aEvent; 2710 Atom nAtom = getWMAdaptor()->getAtom( WMAdaptor::SAL_GETTIMEEVENT ); 2711 XChangeProperty( GetDisplay(), GetDrawable( GetDefaultScreenNumber() ), 2712 nAtom, nAtom, 8, PropModeReplace, &c, 1 ); 2713 XFlush( GetDisplay() ); 2714 2715 if( ! XIfEventWithTimeout( &aEvent, (XPointer)this, timestamp_predicate ) ) 2716 { 2717 // this should not happen at all; still sometimes it happens 2718 aEvent.xproperty.time = CurrentTime; 2719 } 2720 2721 m_nLastUserEventTime = aEvent.xproperty.time; 2722 } 2723 return m_nLastUserEventTime; 2724 } 2725 2726 bool SalDisplay::XIfEventWithTimeout( XEvent* o_pEvent, XPointer i_pPredicateData, 2727 X_if_predicate i_pPredicate, long i_nTimeout ) const 2728 { 2729 /* #i99360# ugly workaround an X11 library bug 2730 this replaces the following call: 2731 XIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ); 2732 */ 2733 bool bRet = true; 2734 2735 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2736 { 2737 // wait for some event to arrive 2738 struct pollfd aFD; 2739 aFD.fd = ConnectionNumber(GetDisplay()); 2740 aFD.events = POLLIN; 2741 aFD.revents = 0; 2742 poll( &aFD, 1, i_nTimeout ); 2743 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2744 { 2745 poll( &aFD, 1, i_nTimeout ); // try once more for a packet of events from the Xserver 2746 if( ! XCheckIfEvent( GetDisplay(), o_pEvent, i_pPredicate, i_pPredicateData ) ) 2747 { 2748 bRet = false; 2749 } 2750 } 2751 } 2752 return bRet; 2753 } 2754 2755 // -=-= SalVisual -=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2756 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2757 SalVisual::SalVisual() 2758 { 2759 rtl_zeroMemory( this, sizeof( SalVisual ) ); 2760 } 2761 2762 SalVisual::SalVisual( const XVisualInfo* pXVI ) 2763 { 2764 *(XVisualInfo*)this = *pXVI; 2765 if( GetClass() == TrueColor ) 2766 { 2767 nRedShift_ = sal_Shift( red_mask ); 2768 nGreenShift_ = sal_Shift( green_mask ); 2769 nBlueShift_ = sal_Shift( blue_mask ); 2770 2771 nRedBits_ = sal_significantBits( red_mask ); 2772 nGreenBits_ = sal_significantBits( green_mask ); 2773 nBlueBits_ = sal_significantBits( blue_mask ); 2774 2775 if( GetDepth() == 24 ) 2776 if( red_mask == 0xFF0000 ) 2777 if( green_mask == 0xFF00 ) 2778 if( blue_mask == 0xFF ) 2779 eRGBMode_ = RGB; 2780 else 2781 eRGBMode_ = otherSalRGB; 2782 else if( blue_mask == 0xFF00 ) 2783 if( green_mask == 0xFF ) 2784 eRGBMode_ = RBG; 2785 else 2786 eRGBMode_ = otherSalRGB; 2787 else 2788 eRGBMode_ = otherSalRGB; 2789 else if( green_mask == 0xFF0000 ) 2790 if( red_mask == 0xFF00 ) 2791 if( blue_mask == 0xFF ) 2792 eRGBMode_ = GRB; 2793 else 2794 eRGBMode_ = otherSalRGB; 2795 else if( blue_mask == 0xFF00 ) 2796 if( red_mask == 0xFF ) 2797 eRGBMode_ = GBR; 2798 else 2799 eRGBMode_ = otherSalRGB; 2800 else 2801 eRGBMode_ = otherSalRGB; 2802 else if( blue_mask == 0xFF0000 ) 2803 if( red_mask == 0xFF00 ) 2804 if( green_mask == 0xFF ) 2805 eRGBMode_ = BRG; 2806 else 2807 eRGBMode_ = otherSalRGB; 2808 else if( green_mask == 0xFF00 ) 2809 if( red_mask == 0xFF ) 2810 eRGBMode_ = BGR; 2811 else 2812 eRGBMode_ = otherSalRGB; 2813 else 2814 eRGBMode_ = otherSalRGB; 2815 else 2816 eRGBMode_ = otherSalRGB; 2817 else 2818 eRGBMode_ = otherSalRGB; 2819 } 2820 } 2821 2822 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2823 SalVisual::~SalVisual() 2824 { 2825 if( -1 == screen && VisualID(-1) == visualid ) delete visual; 2826 } 2827 2828 // Konvertiert die Reihenfolge der Bytes eines Pixel in Bytes eines SalColors 2829 // fuer die 6 XXXA ist das nicht reversibel 2830 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2831 // SalColor is RGB (ABGR) a=0xFF000000, r=0xFF0000, g=0xFF00, b=0xFF 2832 2833 #define SALCOLOR RGB 2834 #define SALCOLORREVERSE BGR 2835 2836 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2, int &n3 ) 2837 { 2838 int n; 2839 2840 switch( GetMode() ) 2841 { 2842 case otherSalRGB: 2843 return sal_False; 2844 case SALCOLOR: 2845 break; 2846 case SALCOLORREVERSE: 2847 case RBG: 2848 case BRG: 2849 case GBR: 2850 case GRB: 2851 return Convert( n0, n1, n2 ); 2852 case RGBA: 2853 n = n0; 2854 n0 = n1; 2855 n1 = n2; 2856 n2 = n3; 2857 n3 = n; 2858 break; 2859 case BGRA: 2860 case RBGA: 2861 case BRGA: 2862 case GBRA: 2863 case GRBA: 2864 default: 2865 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); 2866 abort(); 2867 } 2868 return sal_True; 2869 } 2870 2871 sal_Bool SalVisual::Convert( int &n0, int &n1, int &n2 ) 2872 { 2873 int n; 2874 2875 switch( GetMode() ) 2876 { 2877 case otherSalRGB: 2878 return sal_False; 2879 case SALCOLOR: 2880 break; 2881 case RBG: 2882 n = n0; 2883 n0 = n1; 2884 n1 = n; 2885 break; 2886 case GRB: 2887 n = n1; 2888 n1 = n2; 2889 n2 = n; 2890 break; 2891 case SALCOLORREVERSE: 2892 n = n0; 2893 n0 = n2; 2894 n2 = n; 2895 break; 2896 case BRG: 2897 n = n0; 2898 n0 = n1; 2899 n1 = n2; 2900 n2 = n; 2901 break; 2902 case GBR: 2903 n = n2; 2904 n2 = n1; 2905 n1 = n0; 2906 n0 = n; 2907 break; 2908 default: 2909 fprintf( stderr, "SalVisual::Convert %d\n", GetMode() ); 2910 abort(); 2911 } 2912 return sal_True; 2913 } 2914 2915 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2916 SalColor SalVisual::GetTCColor( Pixel nPixel ) const 2917 { 2918 if( SALCOLOR == eRGBMode_ ) 2919 return (SalColor)nPixel; 2920 2921 if( SALCOLORREVERSE == eRGBMode_ ) 2922 return MAKE_SALCOLOR( (nPixel & 0x0000FF), 2923 (nPixel & 0x00FF00) >> 8, 2924 (nPixel & 0xFF0000) >> 16); 2925 2926 Pixel r = nPixel & red_mask; 2927 Pixel g = nPixel & green_mask; 2928 Pixel b = nPixel & blue_mask; 2929 2930 if( otherSalRGB != eRGBMode_ ) // 8+8+8=24 2931 return MAKE_SALCOLOR( r >> nRedShift_, 2932 g >> nGreenShift_, 2933 b >> nBlueShift_ ); 2934 2935 if( nRedShift_ > 0 ) r >>= nRedShift_; else r <<= -nRedShift_; 2936 if( nGreenShift_ > 0 ) g >>= nGreenShift_; else g <<= -nGreenShift_; 2937 if( nBlueShift_ > 0 ) b >>= nBlueShift_; else b <<= -nBlueShift_; 2938 2939 if( nRedBits_ != 8 ) 2940 r |= (r & 0xff) >> (8-nRedBits_); 2941 if( nGreenBits_ != 8 ) 2942 g |= (g & 0xff) >> (8-nGreenBits_); 2943 if( nBlueBits_ != 8 ) 2944 b |= (b & 0xff) >> (8-nBlueBits_); 2945 2946 return MAKE_SALCOLOR( r, g, b ); 2947 } 2948 2949 Pixel SalVisual::GetTCPixel( SalColor nSalColor ) const 2950 { 2951 if( SALCOLOR == eRGBMode_ ) 2952 return (Pixel)nSalColor; 2953 2954 Pixel r = (Pixel)SALCOLOR_RED( nSalColor ); 2955 Pixel g = (Pixel)SALCOLOR_GREEN( nSalColor ); 2956 Pixel b = (Pixel)SALCOLOR_BLUE( nSalColor ); 2957 2958 if( SALCOLORREVERSE == eRGBMode_ ) 2959 return (b << 16) | (g << 8) | (r); 2960 2961 if( otherSalRGB != eRGBMode_ ) // 8+8+8=24 2962 return (r << nRedShift_) | (g << nGreenShift_) | (b << nBlueShift_); 2963 2964 if( nRedShift_ > 0 ) r <<= nRedShift_; else r >>= -nRedShift_; 2965 if( nGreenShift_ > 0 ) g <<= nGreenShift_; else g >>= -nGreenShift_; 2966 if( nBlueShift_ > 0 ) b <<= nBlueShift_; else b >>= -nBlueShift_; 2967 2968 return (r&red_mask) | (g&green_mask) | (b&blue_mask); 2969 } 2970 2971 // -=-= SalColormap -=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2972 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 2973 SalColormap::SalColormap( const SalDisplay *pDisplay, Colormap hColormap, int nScreen ) 2974 : m_pDisplay( pDisplay ), 2975 m_hColormap( hColormap ), 2976 m_nScreen( nScreen ) 2977 { 2978 m_aVisual = m_pDisplay->GetVisual( m_nScreen ); 2979 2980 XColor aColor; 2981 2982 GetXPixel( aColor, 0x00, 0x00, 0x00 ); 2983 m_nBlackPixel = aColor.pixel; 2984 2985 GetXPixel( aColor, 0xFF, 0xFF, 0xFF ); 2986 m_nWhitePixel = aColor.pixel; 2987 2988 m_nUsed = 1 << m_aVisual.GetDepth(); 2989 2990 if( m_aVisual.GetClass() == PseudoColor ) 2991 { 2992 int r, g, b; 2993 2994 // black, white, gray, ~gray = 4 2995 GetXPixels( aColor, 0xC0, 0xC0, 0xC0 ); 2996 2997 // light colors: 3 * 2 = 6 2998 // GetXPixels( aColor, 0x00, 0x00, 0x00 ); 2999 GetXPixels( aColor, 0x00, 0x00, 0xFF ); 3000 GetXPixels( aColor, 0x00, 0xFF, 0x00 ); 3001 GetXPixels( aColor, 0x00, 0xFF, 0xFF ); 3002 // GetXPixels( aColor, 0xFF, 0x00, 0x00 ); 3003 // GetXPixels( aColor, 0xFF, 0x00, 0xFF ); 3004 // GetXPixels( aColor, 0xFF, 0xFF, 0x00 ); 3005 // GetXPixels( aColor, 0xFF, 0xFF, 0xFF ); 3006 3007 // standard colors: 7 * 2 = 14 3008 // GetXPixels( aColor, 0x00, 0x00, 0x00 ); 3009 GetXPixels( aColor, 0x00, 0x00, 0x80 ); 3010 GetXPixels( aColor, 0x00, 0x80, 0x00 ); 3011 GetXPixels( aColor, 0x00, 0x80, 0x80 ); 3012 GetXPixels( aColor, 0x80, 0x00, 0x00 ); 3013 GetXPixels( aColor, 0x80, 0x00, 0x80 ); 3014 GetXPixels( aColor, 0x80, 0x80, 0x00 ); 3015 GetXPixels( aColor, 0x80, 0x80, 0x80 ); 3016 GetXPixels( aColor, 0x00, 0xB8, 0xFF ); // Blau 7 3017 3018 // cube: 6*6*6 - 8 = 208 3019 for( r = 0; r < 0x100; r += 0x33 ) // 0x33, 0x66, 0x99, 0xCC, 0xFF 3020 for( g = 0; g < 0x100; g += 0x33 ) 3021 for( b = 0; b < 0x100; b += 0x33 ) 3022 GetXPixels( aColor, r, g, b ); 3023 3024 // gray: 16 - 6 = 10 3025 for( g = 0x11; g < 0xFF; g += 0x11 ) 3026 GetXPixels( aColor, g, g, g ); 3027 3028 // green: 16 - 6 = 10 3029 for( g = 0x11; g < 0xFF; g += 0x11 ) 3030 GetXPixels( aColor, 0, g, 0 ); 3031 3032 // red: 16 - 6 = 10 3033 for( r = 0x11; r < 0xFF; r += 0x11 ) 3034 GetXPixels( aColor, r, 0, 0 ); 3035 3036 // blue: 16 - 6 = 10 3037 for( b = 0x11; b < 0xFF; b += 0x11 ) 3038 GetXPixels( aColor, 0, 0, b ); 3039 } 3040 } 3041 3042 // PseudoColor 3043 SalColormap::SalColormap( const BitmapPalette &rPalette ) 3044 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3045 m_hColormap( None ), 3046 m_nWhitePixel( SALCOLOR_NONE ), 3047 m_nBlackPixel( SALCOLOR_NONE ), 3048 m_nUsed( rPalette.GetEntryCount() ), 3049 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ) 3050 { 3051 m_aPalette = std::vector<SalColor>(m_nUsed); 3052 3053 for( unsigned int i = 0; i < m_nUsed; i++ ) 3054 { 3055 const BitmapColor &rColor = rPalette[i]; 3056 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(), 3057 rColor.GetGreen(), 3058 rColor.GetBlue() ); 3059 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) ) 3060 m_nBlackPixel = i; 3061 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) ) 3062 m_nWhitePixel = i; 3063 } 3064 } 3065 3066 // MonoChrome 3067 SalColormap::SalColormap() 3068 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3069 m_hColormap( None ), 3070 m_nWhitePixel( 1 ), 3071 m_nBlackPixel( 0 ), 3072 m_nUsed( 2 ), 3073 m_nScreen( 0 ) 3074 { 3075 if( m_pDisplay ) 3076 m_nScreen = m_pDisplay->GetDefaultScreenNumber(); 3077 m_aPalette = std::vector<SalColor>(m_nUsed); 3078 3079 m_aPalette[m_nBlackPixel] = SALCOLOR_BLACK; 3080 m_aPalette[m_nWhitePixel] = SALCOLOR_WHITE; 3081 } 3082 3083 // TrueColor 3084 SalColormap::SalColormap( sal_uInt16 nDepth ) 3085 : m_pDisplay( GetX11SalData()->GetDisplay() ), 3086 m_hColormap( None ), 3087 m_nWhitePixel( (1 << nDepth) - 1 ), 3088 m_nBlackPixel( 0x00000000 ), 3089 m_nUsed( 1 << nDepth ), 3090 m_nScreen( GetX11SalData()->GetDisplay()->GetDefaultScreenNumber() ) 3091 { 3092 const SalVisual *pVisual = &m_pDisplay->GetVisual( m_nScreen ); 3093 3094 if( pVisual->GetClass() == TrueColor && pVisual->GetDepth() == nDepth ) 3095 m_aVisual = *pVisual; 3096 else 3097 { 3098 XVisualInfo aVI; 3099 3100 if( !XMatchVisualInfo( m_pDisplay->GetDisplay(), 3101 m_pDisplay->GetDefaultScreenNumber(), 3102 nDepth, 3103 TrueColor, 3104 &aVI ) ) 3105 { 3106 aVI.visual = new Visual(); 3107 aVI.visualid = (VisualID)0; // beware of temporary destructor below 3108 aVI.screen = 0; 3109 aVI.depth = nDepth; 3110 aVI.c_class = TrueColor; 3111 if( 24 == nDepth ) // 888 3112 { 3113 aVI.red_mask = 0xFF0000; 3114 aVI.green_mask = 0x00FF00; 3115 aVI.blue_mask = 0x0000FF; 3116 } 3117 else if( 16 == nDepth ) // 565 3118 { 3119 aVI.red_mask = 0x00F800; 3120 aVI.green_mask = 0x0007E0; 3121 aVI.blue_mask = 0x00001F; 3122 } 3123 else if( 15 == nDepth ) // 555 3124 { 3125 aVI.red_mask = 0x007C00; 3126 aVI.green_mask = 0x0003E0; 3127 aVI.blue_mask = 0x00001F; 3128 } 3129 else if( 12 == nDepth ) // 444 3130 { 3131 aVI.red_mask = 0x000F00; 3132 aVI.green_mask = 0x0000F0; 3133 aVI.blue_mask = 0x00000F; 3134 } 3135 else if( 8 == nDepth ) // 332 3136 { 3137 aVI.red_mask = 0x0000E0; 3138 aVI.green_mask = 0x00001C; 3139 aVI.blue_mask = 0x000003; 3140 } 3141 else 3142 { 3143 aVI.red_mask = 0x000000; 3144 aVI.green_mask = 0x000000; 3145 aVI.blue_mask = 0x000000; 3146 } 3147 aVI.colormap_size = 0; 3148 aVI.bits_per_rgb = 8; 3149 3150 aVI.visual->ext_data = NULL; 3151 aVI.visual->visualid = aVI.visualid; 3152 aVI.visual->c_class = aVI.c_class; 3153 aVI.visual->red_mask = aVI.red_mask; 3154 aVI.visual->green_mask = aVI.green_mask; 3155 aVI.visual->blue_mask = aVI.blue_mask; 3156 aVI.visual->bits_per_rgb = aVI.bits_per_rgb; 3157 aVI.visual->map_entries = aVI.colormap_size; 3158 3159 m_aVisual = SalVisual( &aVI ); 3160 // give ownership of constructed Visual() to m_aVisual 3161 // see SalVisual destructor 3162 m_aVisual.visualid = (VisualID)-1; 3163 m_aVisual.screen = -1; 3164 } 3165 else 3166 m_aVisual = SalVisual( &aVI ); 3167 } 3168 } 3169 3170 SalColormap::~SalColormap() 3171 { 3172 #ifdef DBG_UTIL 3173 m_hColormap = (Colormap)ILLEGAL_POINTER; 3174 m_pDisplay = (SalDisplay*)ILLEGAL_POINTER; 3175 #endif 3176 } 3177 3178 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3179 void SalColormap::SetPalette( const BitmapPalette &rPalette ) 3180 { 3181 if( this != &GetX11SalData()->GetDisplay()->GetColormap(m_nScreen) ) 3182 { 3183 m_nBlackPixel = SALCOLOR_NONE; 3184 m_nWhitePixel = SALCOLOR_NONE; 3185 } 3186 3187 if( rPalette.GetEntryCount() > m_nUsed ) 3188 { 3189 m_nBlackPixel = SALCOLOR_NONE; 3190 m_nWhitePixel = SALCOLOR_NONE; 3191 m_nUsed = rPalette.GetEntryCount(); 3192 m_aPalette = std::vector<SalColor>(m_nUsed); 3193 } 3194 3195 for( int i = 0; i < rPalette.GetEntryCount(); i++ ) 3196 { 3197 const BitmapColor &rColor = rPalette[i]; 3198 m_aPalette[i] = MAKE_SALCOLOR( rColor.GetRed(), 3199 rColor.GetGreen(), 3200 rColor.GetBlue() ); 3201 if( (m_nBlackPixel == SALCOLOR_NONE) && (SALCOLOR_BLACK == m_aPalette[i]) ) 3202 m_nBlackPixel = i; 3203 else if( (m_nWhitePixel == SALCOLOR_NONE) && (SALCOLOR_WHITE == m_aPalette[i]) ) 3204 m_nWhitePixel = i; 3205 } 3206 } 3207 3208 void SalColormap::GetPalette() 3209 { 3210 Pixel i; 3211 m_aPalette = std::vector<SalColor>(m_nUsed); 3212 3213 XColor *aColor = new XColor[m_nUsed]; 3214 3215 for( i = 0; i < m_nUsed; i++ ) 3216 { 3217 aColor[i].red = aColor[i].green = aColor[i].blue = 0; 3218 aColor[i].pixel = i; 3219 } 3220 3221 XQueryColors( m_pDisplay->GetDisplay(), m_hColormap, aColor, m_nUsed ); 3222 3223 for( i = 0; i < m_nUsed; i++ ) 3224 { 3225 m_aPalette[i] = MAKE_SALCOLOR( aColor[i].red >> 8, 3226 aColor[i].green >> 8, 3227 aColor[i].blue >> 8 ); 3228 } 3229 3230 delete [] aColor; 3231 } 3232 3233 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3234 static sal_uInt16 sal_Lookup( const std::vector<SalColor>& rPalette, 3235 int r, int g, int b, 3236 Pixel nUsed ) 3237 { 3238 sal_uInt16 nPixel = 0; 3239 int nBest = ColorDiff( rPalette[0], r, g, b ); 3240 3241 for( sal_uInt16 i = 1; i < nUsed; i++ ) 3242 { 3243 int n = ColorDiff( rPalette[i], r, g, b ); 3244 3245 if( n < nBest ) 3246 { 3247 if( !n ) 3248 return i; 3249 3250 nPixel = i; 3251 nBest = n; 3252 } 3253 } 3254 return nPixel; 3255 } 3256 3257 void SalColormap::GetLookupTable() 3258 { 3259 m_aLookupTable = std::vector<sal_uInt16>(16*16*16); 3260 3261 int i = 0; 3262 for( int r = 0; r < 256; r += 17 ) 3263 for( int g = 0; g < 256; g += 17 ) 3264 for( int b = 0; b < 256; b += 17 ) 3265 m_aLookupTable[i++] = sal_Lookup( m_aPalette, r, g, b, m_nUsed ); 3266 } 3267 3268 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 3269 SalColor SalColormap::GetColor( Pixel nPixel ) const 3270 { 3271 if( m_nBlackPixel == nPixel ) return SALCOLOR_BLACK; 3272 if( m_nWhitePixel == nPixel ) return SALCOLOR_WHITE; 3273 3274 if( m_aVisual.GetVisual() ) 3275 { 3276 if( m_aVisual.GetClass() == TrueColor ) 3277 return m_aVisual.GetTCColor( nPixel ); 3278 3279 if( m_aPalette.empty() 3280 && m_hColormap 3281 #ifdef PSEUDOCOLOR12 3282 && m_aVisual.GetDepth() <= 12 3283 #else 3284 && m_aVisual.GetDepth() <= 8 3285 #endif 3286 && m_aVisual.GetClass() == PseudoColor ) 3287 ((SalColormap*)this)->GetPalette(); 3288 } 3289 3290 if( !m_aPalette.empty() && nPixel < m_nUsed ) 3291 return m_aPalette[nPixel]; 3292 3293 if( m_hColormap ) 3294 { 3295 DBG_ASSERT( 1, "SalColormap::GetColor() !hColormap_\n" ); 3296 return nPixel; 3297 } 3298 3299 // DirectColor, StaticColor, StaticGray, GrayScale 3300 XColor aColor; 3301 3302 aColor.pixel = nPixel; 3303 3304 XQueryColor( m_pDisplay->GetDisplay(), m_hColormap, &aColor ); 3305 3306 return MAKE_SALCOLOR( aColor.red>>8, aColor.green>>8, aColor.blue>>8 ); 3307 } 3308 3309 inline sal_Bool SalColormap::GetXPixel( XColor &rColor, 3310 int r, 3311 int g, 3312 int b ) const 3313 { 3314 rColor.red = r * 257; 3315 rColor.green = g * 257; 3316 rColor.blue = b * 257; 3317 return XAllocColor( GetXDisplay(), m_hColormap, &rColor ); 3318 } 3319 3320 sal_Bool SalColormap::GetXPixels( XColor &rColor, 3321 int r, 3322 int g, 3323 int b ) const 3324 { 3325 if( !GetXPixel( rColor, r, g, b ) ) 3326 return sal_False; 3327 if( rColor.pixel & 1 ) 3328 return sal_True; 3329 return GetXPixel( rColor, r^0xFF, g^0xFF, b^0xFF ); 3330 } 3331 3332 Pixel SalColormap::GetPixel( SalColor nSalColor ) const 3333 { 3334 if( SALCOLOR_NONE == nSalColor ) return 0; 3335 if( SALCOLOR_BLACK == nSalColor ) return m_nBlackPixel; 3336 if( SALCOLOR_WHITE == nSalColor ) return m_nWhitePixel; 3337 3338 if( m_aVisual.GetClass() == TrueColor ) 3339 return m_aVisual.GetTCPixel( nSalColor ); 3340 3341 if( m_aLookupTable.empty() ) 3342 { 3343 if( m_aPalette.empty() 3344 && m_hColormap 3345 #ifdef PSEUDOCOLOR12 3346 && m_aVisual.GetDepth() <= 12 3347 #else 3348 && m_aVisual.GetDepth() <= 8 3349 #endif 3350 && m_aVisual.GetClass() == PseudoColor ) // what else ??? 3351 ((SalColormap*)this)->GetPalette(); 3352 3353 if( !m_aPalette.empty() ) 3354 for( Pixel i = 0; i < m_nUsed; i++ ) 3355 if( m_aPalette[i] == nSalColor ) 3356 return i; 3357 3358 if( m_hColormap ) 3359 { 3360 // DirectColor, StaticColor, StaticGray, GrayScale (PseudoColor) 3361 XColor aColor; 3362 3363 if( GetXPixel( aColor, 3364 SALCOLOR_RED ( nSalColor ), 3365 SALCOLOR_GREEN( nSalColor ), 3366 SALCOLOR_BLUE ( nSalColor ) ) ) 3367 { 3368 if( !m_aPalette.empty() && !m_aPalette[aColor.pixel] ) 3369 { 3370 const_cast<SalColormap*>(this)->m_aPalette[aColor.pixel] = nSalColor; 3371 3372 if( !(aColor.pixel & 1) && !m_aPalette[aColor.pixel+1] ) 3373 { 3374 XColor aInversColor; 3375 3376 SalColor nInversColor = nSalColor ^ 0xFFFFFF; 3377 3378 GetXPixel( aInversColor, 3379 SALCOLOR_RED ( nInversColor ), 3380 SALCOLOR_GREEN( nInversColor ), 3381 SALCOLOR_BLUE ( nInversColor ) ); 3382 3383 if( !m_aPalette[aInversColor.pixel] ) 3384 const_cast<SalColormap*>(this)->m_aPalette[aInversColor.pixel] = nInversColor; 3385 #ifdef DBG_UTIL 3386 else 3387 fprintf( stderr, "SalColormap::GetPixel() 0x%06lx=%lu 0x%06lx=%lu\n", 3388 static_cast< unsigned long >(nSalColor), aColor.pixel, 3389 static_cast< unsigned long >(nInversColor), aInversColor.pixel); 3390 #endif 3391 } 3392 } 3393 3394 return aColor.pixel; 3395 } 3396 3397 #ifdef DBG_UTIL 3398 fprintf( stderr, "SalColormap::GetPixel() !XAllocColor %lx\n", 3399 static_cast< unsigned long >(nSalColor) ); 3400 #endif 3401 } 3402 3403 if( m_aPalette.empty() ) 3404 { 3405 #ifdef DBG_UTIL 3406 fprintf( stderr, "SalColormap::GetPixel() Palette empty %lx\n", 3407 static_cast< unsigned long >(nSalColor)); 3408 #endif 3409 return nSalColor; 3410 } 3411 3412 ((SalColormap*)this)->GetLookupTable(); 3413 } 3414 3415 // Colormatching über Palette 3416 sal_uInt16 r = SALCOLOR_RED ( nSalColor ); 3417 sal_uInt16 g = SALCOLOR_GREEN( nSalColor ); 3418 sal_uInt16 b = SALCOLOR_BLUE ( nSalColor ); 3419 return m_aLookupTable[ (((r+8)/17) << 8) 3420 + (((g+8)/17) << 4) 3421 + ((b+8)/17) ]; 3422 } 3423 3424 /* vim: set noet sw=4 ts=4: */ 3425