1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 31 #include "vcl/svapp.hxx" 32 33 #include "unx/gtk/gtkframe.hxx" 34 #include "unx/gtk/gtkdata.hxx" 35 #include "unx/gtk/gtkinst.hxx" 36 #include "unx/gtk/gtkgdi.hxx" 37 38 #include "unx/pspgraphics.h" 39 #include "unx/saldata.hxx" 40 #include "unx/saldisp.hxx" 41 42 #include <cstdio> 43 #include <cmath> 44 #include <vector> 45 #include <algorithm> 46 #include <hash_map> 47 48 typedef struct _cairo_font_options cairo_font_options_t; 49 50 // initialize statics 51 sal_Bool GtkSalGraphics::bThemeChanged = sal_True; 52 sal_Bool GtkSalGraphics::bNeedPixmapPaint = sal_False; 53 sal_Bool GtkSalGraphics::bGlobalNeedPixmapPaint = sal_False; 54 sal_Bool GtkSalGraphics::bToolbarGripWorkaround = sal_False; 55 sal_Bool GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround = sal_False; 56 57 GtkSalGraphics::~GtkSalGraphics() 58 { 59 } 60 61 62 using namespace rtl; 63 64 /************************************* 65 * Cached native widget objects 66 *************************************/ 67 class NWPixmapCacheList; 68 class NWPixmapCache; 69 struct NWFWidgetData 70 { 71 GtkWidget * gCacheWindow; 72 GtkWidget * gDumbContainer; 73 74 GtkWidget * gBtnWidget; 75 GtkWidget * gRadioWidget; 76 GtkWidget * gRadioWidgetSibling; 77 GtkWidget * gCheckWidget; 78 GtkWidget * gScrollHorizWidget; 79 GtkWidget * gScrollVertWidget; 80 GtkWidget * gArrowWidget; 81 GtkWidget * gDropdownWidget; 82 GtkWidget * gEditBoxWidget; 83 GtkWidget * gSpinButtonWidget; 84 GtkWidget * gNotebookWidget; 85 GtkWidget * gOptionMenuWidget; 86 GtkWidget * gComboWidget; 87 GtkWidget * gScrolledWindowWidget; 88 GtkWidget * gToolbarWidget; 89 GtkWidget * gToolbarButtonWidget; 90 GtkWidget * gToolbarToggleWidget; 91 GtkWidget * gHandleBoxWidget; 92 GtkWidget * gMenubarWidget; 93 GtkWidget * gMenuItemMenubarWidget; 94 GtkWidget * gMenuWidget; 95 GtkWidget * gMenuItemMenuWidget; 96 GtkWidget * gMenuItemCheckMenuWidget; 97 GtkWidget * gMenuItemRadioMenuWidget; 98 GtkWidget * gImageMenuItem; 99 GtkWidget * gTooltipPopup; 100 GtkWidget * gProgressBar; 101 GtkWidget * gTreeView; 102 GtkWidget * gHScale; 103 GtkWidget * gVScale; 104 105 NWPixmapCacheList* gNWPixmapCacheList; 106 NWPixmapCache* gCacheTabItems; 107 NWPixmapCache* gCacheTabPages; 108 109 NWFWidgetData() : 110 gCacheWindow( NULL ), 111 gDumbContainer( NULL ), 112 gBtnWidget( NULL ), 113 gRadioWidget( NULL ), 114 gRadioWidgetSibling( NULL ), 115 gCheckWidget( NULL ), 116 gScrollHorizWidget( NULL ), 117 gScrollVertWidget( NULL ), 118 gArrowWidget( NULL ), 119 gDropdownWidget( NULL ), 120 gEditBoxWidget( NULL ), 121 gSpinButtonWidget( NULL ), 122 gNotebookWidget( NULL ), 123 gOptionMenuWidget( NULL ), 124 gComboWidget( NULL ), 125 gScrolledWindowWidget( NULL ), 126 gToolbarWidget( NULL ), 127 gToolbarButtonWidget( NULL ), 128 gToolbarToggleWidget( NULL ), 129 gHandleBoxWidget( NULL ), 130 gMenubarWidget( NULL ), 131 gMenuItemMenubarWidget( NULL ), 132 gMenuWidget( NULL ), 133 gMenuItemMenuWidget( NULL ), 134 gMenuItemCheckMenuWidget( NULL ), 135 gMenuItemRadioMenuWidget( NULL ), 136 gImageMenuItem( NULL ), 137 gTooltipPopup( NULL ), 138 gProgressBar( NULL ), 139 gTreeView( NULL ), 140 gHScale( NULL ), 141 gVScale( NULL ), 142 gNWPixmapCacheList( NULL ), 143 gCacheTabItems( NULL ), 144 gCacheTabPages( NULL ) 145 {} 146 }; 147 148 // Keep a hash table of Widgets->default flags so that we can 149 // easily and quickly reset each to a default state before using 150 // them 151 static std::hash_map<long, guint> gWidgetDefaultFlags; 152 static std::vector<NWFWidgetData> gWidgetData; 153 154 static const GtkBorder aDefDefBorder = { 1, 1, 1, 1 }; 155 156 // Some GTK defaults 157 #define MIN_ARROW_SIZE 11 158 #define BTN_CHILD_SPACING 1 159 #define MIN_SPIN_ARROW_WIDTH 6 160 161 162 static void NWEnsureGTKRadio ( int nScreen ); 163 static void NWEnsureGTKButton ( int nScreen ); 164 static void NWEnsureGTKCheck ( int nScreen ); 165 static void NWEnsureGTKScrollbars ( int nScreen ); 166 static void NWEnsureGTKArrow ( int nScreen ); 167 static void NWEnsureGTKEditBox ( int nScreen ); 168 static void NWEnsureGTKSpinButton ( int nScreen ); 169 static void NWEnsureGTKNotebook ( int nScreen ); 170 static void NWEnsureGTKOptionMenu ( int nScreen ); 171 static void NWEnsureGTKCombo ( int nScreen ); 172 static void NWEnsureGTKScrolledWindow ( int nScreen ); 173 static void NWEnsureGTKToolbar ( int nScreen ); 174 static void NWEnsureGTKMenubar ( int nScreen ); 175 static void NWEnsureGTKMenu ( int nScreen ); 176 static void NWEnsureGTKTooltip ( int nScreen ); 177 static void NWEnsureGTKProgressBar ( int nScreen ); 178 static void NWEnsureGTKTreeView ( int nScreen ); 179 static void NWEnsureGTKSlider ( int nScreen ); 180 181 static void NWConvertVCLStateToGTKState( ControlState nVCLState, GtkStateType* nGTKState, GtkShadowType* nGTKShadow ); 182 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen ); 183 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState ); 184 185 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow ); 186 187 /* 188 * Individual helper functions 189 * 190 */ 191 192 //--- 193 static Rectangle NWGetButtonArea( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 194 const ImplControlValue& aValue, const OUString& rCaption ); 195 196 //--- 197 static Rectangle NWGetEditBoxPixmapRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 198 const ImplControlValue& aValue, const OUString& rCaption ); 199 200 static void NWPaintOneEditBox( int nScreen, GdkDrawable * gdkDrawable, GdkRectangle *gdkRect, 201 ControlType nType, ControlPart nPart, Rectangle aEditBoxRect, 202 ControlState nState, const ImplControlValue& aValue, 203 const OUString& rCaption ); 204 205 //--- 206 static Rectangle NWGetSpinButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 207 const ImplControlValue& aValue, const OUString& rCaption ); 208 209 static void NWPaintOneSpinButton( int nScreen, GdkPixmap * pixmap, ControlType nType, ControlPart nPart, Rectangle aAreaRect, 210 ControlState nState, const ImplControlValue& aValue, 211 const OUString& rCaption ); 212 //--- 213 static Rectangle NWGetComboBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 214 const ImplControlValue& aValue, const OUString& rCaption ); 215 216 //--- 217 static Rectangle NWGetListBoxButtonRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 218 const ImplControlValue& aValue, const OUString& rCaption ); 219 220 static Rectangle NWGetListBoxIndicatorRect( int nScreen, ControlType nType, ControlPart nPart, Rectangle aAreaRect, ControlState nState, 221 const ImplControlValue& aValue, const OUString& rCaption ); 222 223 static Rectangle NWGetToolbarRect( int nScreen, 224 ControlType nType, 225 ControlPart nPart, 226 Rectangle aAreaRect, 227 ControlState nState, 228 const ImplControlValue& aValue, 229 const OUString& rCaption ); 230 //--- 231 232 static Rectangle NWGetScrollButtonRect( int nScreen, ControlPart nPart, Rectangle aAreaRect ); 233 //--- 234 235 /********************************************************* 236 * PixmapCache 237 *********************************************************/ 238 239 // as some native widget drawing operations are pretty slow 240 // with certain themes (eg tabpages) 241 // this cache can be used to cache the corresponding pixmap 242 // see NWPaintGTKTabItem 243 244 class NWPixmapCacheData 245 { 246 public: 247 ControlType m_nType; 248 ControlState m_nState; 249 Rectangle m_pixmapRect; 250 GdkPixmap* m_pixmap; 251 252 NWPixmapCacheData() : m_nType(0), m_nState(0), m_pixmap(0) {} 253 ~NWPixmapCacheData() 254 { SetPixmap( NULL ); }; 255 void SetPixmap( GdkPixmap* pPixmap ); 256 }; 257 258 class NWPixmapCache 259 { 260 int m_size; 261 int m_idx; 262 int m_screen; 263 NWPixmapCacheData* pData; 264 public: 265 NWPixmapCache( int nScreen ); 266 ~NWPixmapCache(); 267 268 void SetSize( int n) 269 { delete [] pData; m_idx = 0; m_size = n; pData = new NWPixmapCacheData[m_size]; } 270 int GetSize() { return m_size; } 271 272 sal_Bool Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap ); 273 void Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap ); 274 275 void ThemeChanged(); 276 }; 277 278 class NWPixmapCacheList 279 { 280 public: 281 ::std::vector< NWPixmapCache* > mCaches; 282 283 void AddCache( NWPixmapCache *pCache ); 284 void RemoveCache( NWPixmapCache *pCache ); 285 void ThemeChanged(); 286 }; 287 288 // --- implementation --- 289 290 void NWPixmapCacheData::SetPixmap( GdkPixmap* pPixmap ) 291 { 292 if( m_pixmap ) 293 g_object_unref( m_pixmap ); 294 295 m_pixmap = pPixmap; 296 297 if( m_pixmap ) 298 g_object_ref( m_pixmap ); 299 } 300 301 302 NWPixmapCache::NWPixmapCache( int nScreen ) 303 { 304 m_idx = 0; 305 m_size = 0; 306 m_screen = nScreen; 307 pData = NULL; 308 if( gWidgetData[m_screen].gNWPixmapCacheList ) 309 gWidgetData[m_screen].gNWPixmapCacheList->AddCache(this); 310 } 311 NWPixmapCache::~NWPixmapCache() 312 { 313 if( gWidgetData[m_screen].gNWPixmapCacheList ) 314 gWidgetData[m_screen].gNWPixmapCacheList->RemoveCache(this); 315 delete[] pData; 316 } 317 void NWPixmapCache::ThemeChanged() 318 { 319 // throw away cached pixmaps 320 int i; 321 for(i=0; i<m_size; i++) 322 pData[i].SetPixmap( NULL ); 323 } 324 325 sal_Bool NWPixmapCache::Find( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap** pPixmap ) 326 { 327 aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag 328 int i; 329 for(i=0; i<m_size; i++) 330 { 331 if( pData[i].m_nType == aType && 332 pData[i].m_nState == aState && 333 pData[i].m_pixmapRect.GetWidth() == r_pixmapRect.GetWidth() && 334 pData[i].m_pixmapRect.GetHeight() == r_pixmapRect.GetHeight() && 335 pData[i].m_pixmap != NULL ) 336 { 337 *pPixmap = pData[i].m_pixmap; 338 return sal_True; 339 } 340 } 341 return sal_False; 342 } 343 344 void NWPixmapCache::Fill( ControlType aType, ControlState aState, const Rectangle& r_pixmapRect, GdkPixmap* pPixmap ) 345 { 346 if( !(aState & CTRL_CACHING_ALLOWED) ) 347 return; 348 349 aState &= ~CTRL_CACHING_ALLOWED; // mask clipping flag 350 m_idx = (m_idx+1) % m_size; // just wrap 351 pData[m_idx].m_nType = aType; 352 pData[m_idx].m_nState = aState; 353 pData[m_idx].m_pixmapRect = r_pixmapRect; 354 pData[m_idx].SetPixmap( pPixmap ); 355 } 356 357 358 void NWPixmapCacheList::AddCache( NWPixmapCache* pCache ) 359 { 360 mCaches.push_back( pCache ); 361 } 362 void NWPixmapCacheList::RemoveCache( NWPixmapCache* pCache ) 363 { 364 ::std::vector< NWPixmapCache* >::iterator p; 365 p = ::std::find( mCaches.begin(), mCaches.end(), pCache ); 366 if( p != mCaches.end() ) 367 mCaches.erase( p ); 368 } 369 void NWPixmapCacheList::ThemeChanged( ) 370 { 371 ::std::vector< NWPixmapCache* >::iterator p = mCaches.begin(); 372 while( p != mCaches.end() ) 373 { 374 (*p)->ThemeChanged(); 375 p++; 376 } 377 } 378 379 380 /********************************************************* 381 * Make border manipulation easier 382 *********************************************************/ 383 inline void NW_gtk_border_set_from_border( GtkBorder& aDst, const GtkBorder * pSrc ) 384 { 385 aDst.left = pSrc->left; 386 aDst.top = pSrc->top; 387 aDst.right = pSrc->right; 388 aDst.bottom = pSrc->bottom; 389 } 390 391 392 /********************************************************* 393 * Initialize GTK and local stuff 394 *********************************************************/ 395 void GtkData::initNWF( void ) 396 { 397 ImplSVData* pSVData = ImplGetSVData(); 398 399 // draw no border for popup menus (NWF draws its own) 400 pSVData->maNWFData.mbFlatMenu = true; 401 402 // draw separate buttons for toolbox dropdown items 403 pSVData->maNWFData.mbToolboxDropDownSeparate = true; 404 405 // small extra border around menu items 406 pSVData->maNWFData.mnMenuFormatExtraBorder = 1; 407 408 // draw toolbars in separate lines 409 pSVData->maNWFData.mbDockingAreaSeparateTB = true; 410 411 // open first menu on F10 412 pSVData->maNWFData.mbOpenMenuOnF10 = true; 413 414 // omit GetNativeControl while painting (see brdwin.cxx) 415 pSVData->maNWFData.mbCanDrawWidgetAnySize = true; 416 417 int nScreens = GetX11SalData()->GetDisplay()->GetScreenCount(); 418 gWidgetData = std::vector<NWFWidgetData>( nScreens ); 419 for( int i = 0; i < nScreens; i++ ) 420 gWidgetData[i].gNWPixmapCacheList = new NWPixmapCacheList; 421 422 423 if( SalGetDesktopEnvironment().equalsAscii( "KDE" ) ) 424 { 425 // #i97196# ensure a widget exists and the style engine was loaded 426 NWEnsureGTKButton( 0 ); 427 if( g_type_from_name( "QtEngineStyle" ) ) 428 { 429 // KDE 3.3 invented a bug in the qt<->gtk theme engine 430 // that makes direct rendering impossible: they totally 431 // ignore the clip rectangle passed to the paint methods 432 GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true; 433 } 434 } 435 static const char* pEnv = getenv( "SAL_GTK_USE_PIXMAPPAINT" ); 436 if( pEnv && *pEnv ) 437 GtkSalGraphics::bNeedPixmapPaint = GtkSalGraphics::bGlobalNeedPixmapPaint = true; 438 439 #if OSL_DEBUG_LEVEL > 1 440 std::fprintf( stderr, "GtkPlugin: using %s NWF\n", 441 GtkSalGraphics::bNeedPixmapPaint ? "offscreen" : "direct" ); 442 #endif 443 } 444 445 446 /********************************************************* 447 * Release GTK and local stuff 448 *********************************************************/ 449 void GtkData::deInitNWF( void ) 450 { 451 452 for( unsigned int i = 0; i < gWidgetData.size(); i++ ) 453 { 454 // free up global widgets 455 // gtk_widget_destroy will in turn destroy the child hierarchy 456 // so only destroy disjunct hierachies 457 if( gWidgetData[i].gCacheWindow ) 458 gtk_widget_destroy( gWidgetData[i].gCacheWindow ); 459 if( gWidgetData[i].gMenuWidget ) 460 gtk_widget_destroy( gWidgetData[i].gMenuWidget ); 461 if( gWidgetData[i].gTooltipPopup ) 462 gtk_widget_destroy( gWidgetData[i].gTooltipPopup ); 463 delete gWidgetData[i].gCacheTabPages; 464 gWidgetData[i].gCacheTabPages = NULL; 465 delete gWidgetData[i].gCacheTabItems; 466 gWidgetData[i].gCacheTabItems = NULL; 467 delete gWidgetData[i].gNWPixmapCacheList; 468 gWidgetData[i].gNWPixmapCacheList = NULL; 469 } 470 } 471 472 473 /********************************************************** 474 * track clip region 475 **********************************************************/ 476 void GtkSalGraphics::ResetClipRegion() 477 { 478 m_aClipRegion.SetNull(); 479 X11SalGraphics::ResetClipRegion(); 480 } 481 482 bool GtkSalGraphics::setClipRegion( const Region& i_rClip ) 483 { 484 m_aClipRegion = i_rClip; 485 bool bRet = X11SalGraphics::setClipRegion( m_aClipRegion ); 486 if( m_aClipRegion.IsEmpty() ) 487 m_aClipRegion.SetNull(); 488 return bRet; 489 } 490 491 void GtkSalGraphics::copyBits( const SalTwoRect* pPosAry, 492 SalGraphics* pSrcGraphics ) 493 { 494 GtkSalFrame* pFrame = GetGtkFrame(); 495 XLIB_Window aWin = None; 496 if( pFrame && m_pWindow ) 497 { 498 /* #i64117# some themes set the background pixmap VERY frequently */ 499 GdkWindow* pWin = GTK_WIDGET(m_pWindow)->window; 500 if( pWin ) 501 { 502 aWin = GDK_WINDOW_XWINDOW(pWin); 503 if( aWin != None ) 504 XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(), 505 aWin, 506 None ); 507 } 508 } 509 X11SalGraphics::copyBits( pPosAry, pSrcGraphics ); 510 if( pFrame && pFrame->getBackgroundPixmap() != None ) 511 XSetWindowBackgroundPixmap( pFrame->getDisplay()->GetDisplay(), 512 aWin, 513 pFrame->getBackgroundPixmap() ); 514 } 515 516 /* 517 * IsNativeControlSupported() 518 * 519 * Returns sal_True if the platform supports native 520 * drawing of the control defined by nPart 521 */ 522 sal_Bool GtkSalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) 523 { 524 if ( 525 ((nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL)) || 526 ((nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL)) || 527 ((nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL)) || 528 ((nType==CTRL_SCROLLBAR) && 529 ( (nPart==PART_DRAW_BACKGROUND_HORZ) 530 || (nPart==PART_DRAW_BACKGROUND_VERT) 531 || (nPart==PART_ENTIRE_CONTROL) 532 || (nPart==HAS_THREE_BUTTONS) ) ) || 533 ((nType==CTRL_EDITBOX) && 534 ( (nPart==PART_ENTIRE_CONTROL) 535 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) || 536 ((nType==CTRL_MULTILINE_EDITBOX) && 537 ( (nPart==PART_ENTIRE_CONTROL) 538 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) || 539 ((nType==CTRL_SPINBOX) && 540 ( (nPart==PART_ENTIRE_CONTROL) 541 || (nPart==PART_ALL_BUTTONS) 542 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) || 543 ((nType==CTRL_SPINBUTTONS) && 544 ( (nPart==PART_ENTIRE_CONTROL) 545 || (nPart==PART_ALL_BUTTONS) ) ) || 546 ((nType==CTRL_COMBOBOX) && 547 ( (nPart==PART_ENTIRE_CONTROL) 548 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) || 549 (((nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || 550 (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER)) && 551 ( (nPart==PART_ENTIRE_CONTROL) 552 || (nPart==PART_TABS_DRAW_RTL) ) ) || 553 ((nType==CTRL_LISTBOX) && 554 ( (nPart==PART_ENTIRE_CONTROL) 555 || (nPart==PART_WINDOW) 556 || (nPart==HAS_BACKGROUND_TEXTURE) ) ) || 557 ((nType == CTRL_TOOLBAR) && 558 ( (nPart==PART_ENTIRE_CONTROL) 559 || (nPart==PART_DRAW_BACKGROUND_HORZ) 560 || (nPart==PART_DRAW_BACKGROUND_VERT) 561 || (nPart==PART_THUMB_HORZ) 562 || (nPart==PART_THUMB_VERT) 563 || (nPart==PART_BUTTON) 564 ) 565 ) || 566 ((nType == CTRL_MENUBAR) && 567 ( (nPart==PART_ENTIRE_CONTROL) ) ) || 568 ((nType == CTRL_TOOLTIP) && 569 ( (nPart==PART_ENTIRE_CONTROL) ) ) || 570 ((nType == CTRL_MENU_POPUP) && 571 ( (nPart==PART_ENTIRE_CONTROL) 572 || (nPart==PART_MENU_ITEM) 573 || (nPart==PART_MENU_ITEM_CHECK_MARK) 574 || (nPart==PART_MENU_ITEM_RADIO_MARK) 575 ) 576 ) || 577 ((nType == CTRL_PROGRESS) && 578 ( (nPart == PART_ENTIRE_CONTROL) ) 579 ) || 580 ((nType == CTRL_LISTNODE || nType == CTRL_LISTNET) && 581 ( (nPart == PART_ENTIRE_CONTROL) ) 582 ) || 583 ((nType == CTRL_SLIDER) && 584 ( (nPart == PART_TRACK_HORZ_AREA) 585 || (nPart == PART_TRACK_VERT_AREA) 586 ) 587 ) 588 ) 589 return( sal_True ); 590 591 return( sal_False ); 592 } 593 594 595 /* 596 * HitTestNativeControl() 597 * 598 * bIsInside is set to sal_True if aPos is contained within the 599 * given part of the control, whose bounding region is 600 * given by rControlRegion (in VCL frame coordinates). 601 * 602 * returns whether bIsInside was really set. 603 */ 604 sal_Bool GtkSalGraphics::hitTestNativeControl( ControlType nType, 605 ControlPart nPart, 606 const Rectangle& rControlRegion, 607 const Point& aPos, 608 sal_Bool& rIsInside ) 609 { 610 if ( ( nType == CTRL_SCROLLBAR ) && 611 ( ( nPart == PART_BUTTON_UP ) || 612 ( nPart == PART_BUTTON_DOWN ) || 613 ( nPart == PART_BUTTON_LEFT ) || 614 ( nPart == PART_BUTTON_RIGHT ) ) ) 615 { 616 NWEnsureGTKScrollbars( m_nScreen ); 617 618 // Grab some button style attributes 619 gboolean has_forward; 620 gboolean has_forward2; 621 gboolean has_backward; 622 gboolean has_backward2; 623 624 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward, 625 "has-secondary-forward-stepper", &has_forward2, 626 "has-backward-stepper", &has_backward, 627 "has-secondary-backward-stepper", &has_backward2, (char *)NULL ); 628 Rectangle aForward; 629 Rectangle aBackward; 630 631 rIsInside = sal_False; 632 633 ControlPart nCounterPart = 0; 634 if ( nPart == PART_BUTTON_UP ) 635 nCounterPart = PART_BUTTON_DOWN; 636 else if ( nPart == PART_BUTTON_DOWN ) 637 nCounterPart = PART_BUTTON_UP; 638 else if ( nPart == PART_BUTTON_LEFT ) 639 nCounterPart = PART_BUTTON_RIGHT; 640 else if ( nPart == PART_BUTTON_RIGHT ) 641 nCounterPart = PART_BUTTON_LEFT; 642 643 aBackward = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion ); 644 aForward = NWGetScrollButtonRect( m_nScreen, nCounterPart, rControlRegion ); 645 646 if ( has_backward && has_forward2 ) 647 { 648 Size aSize( aBackward.GetSize() ); 649 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) ) 650 aSize.setHeight( aBackward.GetHeight() / 2 ); 651 else 652 aSize.setWidth( aBackward.GetWidth() / 2 ); 653 aBackward.SetSize( aSize ); 654 655 if ( nPart == PART_BUTTON_DOWN ) 656 aBackward.Move( 0, aBackward.GetHeight() / 2 ); 657 else if ( nPart == PART_BUTTON_RIGHT ) 658 aBackward.Move( aBackward.GetWidth() / 2, 0 ); 659 } 660 661 if ( has_backward2 && has_forward ) 662 { 663 Size aSize( aForward.GetSize() ); 664 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) ) 665 aSize.setHeight( aForward.GetHeight() / 2 ); 666 else 667 aSize.setWidth( aForward.GetWidth() / 2 ); 668 aForward.SetSize( aSize ); 669 670 if ( nPart == PART_BUTTON_DOWN ) 671 aForward.Move( 0, aForward.GetHeight() / 2 ); 672 else if ( nPart == PART_BUTTON_RIGHT ) 673 aForward.Move( aForward.GetWidth() / 2, 0 ); 674 } 675 676 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_LEFT ) ) 677 { 678 if ( has_backward ) 679 rIsInside |= aBackward.IsInside( aPos ); 680 if ( has_backward2 ) 681 rIsInside |= aForward.IsInside( aPos ); 682 } 683 else 684 { 685 if ( has_forward ) 686 rIsInside |= aBackward.IsInside( aPos ); 687 if ( has_forward2 ) 688 rIsInside |= aForward.IsInside( aPos ); 689 } 690 return ( sal_True ); 691 } 692 693 if( IsNativeControlSupported(nType, nPart) ) 694 { 695 rIsInside = rControlRegion.IsInside( aPos ); 696 return( sal_True ); 697 } 698 else 699 { 700 return( sal_False ); 701 } 702 } 703 704 705 /* 706 * DrawNativeControl() 707 * 708 * Draws the requested control described by nPart/nState. 709 * 710 * rControlRegion: The bounding region of the complete control in VCL frame coordinates. 711 * aValue: An optional value (tristate/numerical/string) 712 * rCaption: A caption or title string (like button text etc) 713 */ 714 sal_Bool GtkSalGraphics::drawNativeControl( ControlType nType, 715 ControlPart nPart, 716 const Rectangle& rControlRegion, 717 ControlState nState, 718 const ImplControlValue& aValue, 719 const OUString& rCaption ) 720 { 721 sal_Bool returnVal = sal_False; 722 // get a GC with current clipping region set 723 GetFontGC(); 724 725 726 // theme changed ? 727 if( GtkSalGraphics::bThemeChanged ) 728 { 729 // invalidate caches 730 for( unsigned int i = 0; i < gWidgetData.size(); i++ ) 731 if( gWidgetData[i].gNWPixmapCacheList ) 732 gWidgetData[i].gNWPixmapCacheList->ThemeChanged(); 733 GtkSalGraphics::bThemeChanged = sal_False; 734 } 735 736 Rectangle aCtrlRect( rControlRegion ); 737 Region aClipRegion( m_aClipRegion ); 738 if( aClipRegion.IsNull() ) 739 aClipRegion = aCtrlRect; 740 741 clipList aClip; 742 GdkDrawable* gdkDrawable = GDK_DRAWABLE( GetGdkWindow() ); 743 GdkPixmap* pixmap = NULL; 744 Rectangle aPixmapRect; 745 if( ( bNeedPixmapPaint ) 746 && nType != CTRL_SCROLLBAR 747 && nType != CTRL_SPINBOX 748 && nType != CTRL_TAB_ITEM 749 && nType != CTRL_TAB_PANE 750 && nType != CTRL_PROGRESS 751 && ! (bToolbarGripWorkaround && nType == CTRL_TOOLBAR && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) ) 752 ) 753 { 754 // make pixmap a little larger since some themes draw decoration 755 // outside the rectangle, see e.g. checkbox 756 aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ), 757 Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) ); 758 pixmap = NWGetPixmapFromScreen( aPixmapRect ); 759 if( ! pixmap ) 760 return sal_False; 761 gdkDrawable = GDK_DRAWABLE( pixmap ); 762 aCtrlRect = Rectangle( Point(1,1), aCtrlRect.GetSize() ); 763 aClip.push_back( aCtrlRect ); 764 } 765 else 766 { 767 RegionHandle aHdl = aClipRegion.BeginEnumRects(); 768 Rectangle aPaintRect; 769 while( aClipRegion.GetNextEnumRect( aHdl, aPaintRect ) ) 770 { 771 aPaintRect = aCtrlRect.GetIntersection( aPaintRect ); 772 if( aPaintRect.IsEmpty() ) 773 continue; 774 aClip.push_back( aPaintRect ); 775 } 776 aClipRegion.EndEnumRects( aHdl ); 777 } 778 779 if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) 780 { 781 returnVal = NWPaintGTKButton( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 782 } 783 else if ( (nType==CTRL_RADIOBUTTON) && (nPart==PART_ENTIRE_CONTROL) ) 784 { 785 returnVal = NWPaintGTKRadio( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 786 } 787 else if ( (nType==CTRL_CHECKBOX) && (nPart==PART_ENTIRE_CONTROL) ) 788 { 789 returnVal = NWPaintGTKCheck( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 790 } 791 else if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_DRAW_BACKGROUND_HORZ) || (nPart==PART_DRAW_BACKGROUND_VERT)) ) 792 { 793 returnVal = NWPaintGTKScrollbar( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 794 } 795 else if ( ((nType==CTRL_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) 796 || ((nType==CTRL_SPINBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) 797 || ((nType==CTRL_COMBOBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) 798 || ((nType==CTRL_LISTBOX) && (nPart==HAS_BACKGROUND_TEXTURE)) ) 799 { 800 returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 801 } 802 else if ( ((nType==CTRL_MULTILINE_EDITBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==HAS_BACKGROUND_TEXTURE)) ) ) 803 { 804 returnVal = NWPaintGTKEditBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 805 } 806 else if ( ((nType==CTRL_SPINBOX) || (nType==CTRL_SPINBUTTONS)) 807 && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_ALL_BUTTONS)) ) 808 { 809 returnVal = NWPaintGTKSpinBox( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 810 } 811 else if ( (nType == CTRL_COMBOBOX) && 812 ( (nPart==PART_ENTIRE_CONTROL) 813 ||(nPart==PART_BUTTON_DOWN) 814 ) ) 815 { 816 returnVal = NWPaintGTKComboBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 817 } 818 else if ( (nType==CTRL_TAB_ITEM) || (nType==CTRL_TAB_PANE) || (nType==CTRL_TAB_BODY) || (nType==CTRL_FIXEDBORDER) ) 819 { 820 if ( nType == CTRL_TAB_BODY ) 821 returnVal = sal_True; 822 else 823 returnVal = NWPaintGTKTabItem( nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption); 824 } 825 else if ( (nType==CTRL_LISTBOX) && ((nPart==PART_ENTIRE_CONTROL) || (nPart==PART_WINDOW)) ) 826 { 827 returnVal = NWPaintGTKListBox( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 828 } 829 else if ( (nType== CTRL_TOOLBAR) ) 830 { 831 returnVal = NWPaintGTKToolbar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 832 } 833 else if ( (nType== CTRL_MENUBAR) ) 834 { 835 returnVal = NWPaintGTKMenubar( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 836 } 837 else if( (nType == CTRL_MENU_POPUP) 838 && ( (nPart == PART_ENTIRE_CONTROL) 839 || (nPart == PART_MENU_ITEM) 840 || (nPart == PART_MENU_ITEM_CHECK_MARK) 841 || (nPart == PART_MENU_ITEM_RADIO_MARK) 842 ) 843 ) 844 { 845 returnVal = NWPaintGTKPopupMenu( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 846 } 847 else if( (nType == CTRL_TOOLTIP) && (nPart == PART_ENTIRE_CONTROL) ) 848 { 849 returnVal = NWPaintGTKTooltip( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 850 } 851 else if( (nType == CTRL_PROGRESS) && (nPart == PART_ENTIRE_CONTROL) ) 852 { 853 returnVal = NWPaintGTKProgress( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 854 } 855 else if( (nType == CTRL_LISTNODE) && (nPart == PART_ENTIRE_CONTROL) ) 856 { 857 returnVal = NWPaintGTKListNode( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 858 } 859 else if( (nType == CTRL_LISTNET) && (nPart == PART_ENTIRE_CONTROL) ) 860 { 861 // don't actually draw anything; gtk treeviews do not draw lines 862 returnVal = true; 863 } 864 else if( (nType == CTRL_SLIDER) ) 865 { 866 returnVal = NWPaintGTKSlider( gdkDrawable, nType, nPart, aCtrlRect, aClip, nState, aValue, rCaption ); 867 } 868 869 if( pixmap ) 870 { 871 returnVal = NWRenderPixmapToScreen( pixmap, aPixmapRect ) && returnVal; 872 g_object_unref( pixmap ); 873 } 874 875 return( returnVal ); 876 } 877 878 /* 879 * DrawNativeControlText() 880 * 881 * OPTIONAL. Draws the requested text for the control described by nPart/nState. 882 * Used if text not drawn by DrawNativeControl(). 883 * 884 * rControlRegion: The bounding region of the complete control in VCL frame coordinates. 885 * aValue: An optional value (tristate/numerical/string) 886 * rCaption: A caption or title string (like button text etc) 887 */ 888 sal_Bool GtkSalGraphics::drawNativeControlText( ControlType, 889 ControlPart, 890 const Rectangle&, 891 ControlState, 892 const ImplControlValue&, 893 const OUString& ) 894 { 895 return( sal_False ); 896 } 897 898 899 /* 900 * GetNativeControlRegion() 901 * 902 * If the return value is sal_True, rNativeBoundingRegion 903 * contains the true bounding region covered by the control 904 * including any adornment, while rNativeContentRegion contains the area 905 * within the control that can be safely drawn into without drawing over 906 * the borders of the control. 907 * 908 * rControlRegion: The bounding region of the control in VCL frame coordinates. 909 * aValue: An optional value (tristate/numerical/string) 910 * rCaption: A caption or title string (like button text etc) 911 */ 912 sal_Bool GtkSalGraphics::getNativeControlRegion( ControlType nType, 913 ControlPart nPart, 914 const Rectangle& rControlRegion, 915 ControlState nState, 916 const ImplControlValue& aValue, 917 const OUString& rCaption, 918 Rectangle &rNativeBoundingRegion, 919 Rectangle &rNativeContentRegion ) 920 { 921 sal_Bool returnVal = sal_False; 922 923 if ( (nType==CTRL_PUSHBUTTON) && (nPart==PART_ENTIRE_CONTROL) 924 && (rControlRegion.GetWidth() > 16) 925 && (rControlRegion.GetHeight() > 16) ) 926 { 927 rNativeBoundingRegion = NWGetButtonArea( m_nScreen, nType, nPart, rControlRegion, 928 nState, aValue, rCaption ); 929 rNativeContentRegion = rControlRegion; 930 931 returnVal = sal_True; 932 } 933 if ( (nType==CTRL_COMBOBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) ) 934 { 935 rNativeBoundingRegion = NWGetComboBoxButtonRect( m_nScreen, nType, nPart, rControlRegion, nState, 936 aValue, rCaption ); 937 rNativeContentRegion = rNativeBoundingRegion; 938 939 returnVal = sal_True; 940 } 941 if ( (nType==CTRL_SPINBOX) && ((nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) ) 942 { 943 944 rNativeBoundingRegion = NWGetSpinButtonRect( m_nScreen, nType, nPart, rControlRegion, nState, 945 aValue, rCaption ); 946 rNativeContentRegion = rNativeBoundingRegion; 947 948 returnVal = sal_True; 949 } 950 if ( (nType==CTRL_LISTBOX) && ((nPart==PART_BUTTON_DOWN) || (nPart==PART_SUB_EDIT)) ) 951 { 952 rNativeBoundingRegion = NWGetListBoxButtonRect( m_nScreen, nType, nPart, rControlRegion, nState, 953 aValue, rCaption ); 954 rNativeContentRegion = rNativeBoundingRegion; 955 956 returnVal = sal_True; 957 } 958 if ( (nType==CTRL_TOOLBAR) && 959 ((nPart==PART_DRAW_BACKGROUND_HORZ) || 960 (nPart==PART_DRAW_BACKGROUND_VERT) || 961 (nPart==PART_THUMB_HORZ) || 962 (nPart==PART_THUMB_VERT) || 963 (nPart==PART_BUTTON) 964 )) 965 { 966 rNativeBoundingRegion = NWGetToolbarRect( m_nScreen, nType, nPart, rControlRegion, nState, aValue, rCaption ); 967 rNativeContentRegion = rNativeBoundingRegion; 968 returnVal = sal_True; 969 } 970 if ( (nType==CTRL_SCROLLBAR) && ((nPart==PART_BUTTON_LEFT) || (nPart==PART_BUTTON_RIGHT) || 971 (nPart==PART_BUTTON_UP) || (nPart==PART_BUTTON_DOWN) ) ) 972 { 973 rNativeBoundingRegion = NWGetScrollButtonRect( m_nScreen, nPart, rControlRegion ); 974 rNativeContentRegion = rNativeBoundingRegion; 975 976 returnVal = sal_True; 977 } 978 if( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL) ) 979 { 980 NWEnsureGTKMenubar( m_nScreen ); 981 GtkRequisition aReq; 982 gtk_widget_size_request( gWidgetData[m_nScreen].gMenubarWidget, &aReq ); 983 Rectangle aMenuBarRect = rControlRegion; 984 aMenuBarRect = Rectangle( aMenuBarRect.TopLeft(), 985 Size( aMenuBarRect.GetWidth(), aReq.height+1 ) ); 986 rNativeBoundingRegion = aMenuBarRect; 987 rNativeContentRegion = rNativeBoundingRegion; 988 returnVal = sal_True; 989 } 990 if( (nType == CTRL_MENU_POPUP) ) 991 { 992 if( (nPart == PART_MENU_ITEM_CHECK_MARK) || 993 (nPart == PART_MENU_ITEM_RADIO_MARK) ) 994 { 995 NWEnsureGTKMenu( m_nScreen ); 996 997 gint indicator_size = 0; 998 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ? 999 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : gWidgetData[m_nScreen].gMenuItemRadioMenuWidget; 1000 gtk_widget_style_get( pWidget, 1001 "indicator_size", &indicator_size, 1002 (char *)NULL ); 1003 rNativeBoundingRegion = rControlRegion; 1004 Rectangle aIndicatorRect( Point( 0, 1005 (rControlRegion.GetHeight()-indicator_size)/2), 1006 Size( indicator_size, indicator_size ) ); 1007 rNativeContentRegion = aIndicatorRect; 1008 returnVal = sal_True; 1009 } 1010 } 1011 if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) ) 1012 { 1013 NWEnsureGTKRadio( m_nScreen ); 1014 NWEnsureGTKCheck( m_nScreen ); 1015 GtkWidget* widget = (nType == CTRL_RADIOBUTTON) ? gWidgetData[m_nScreen].gRadioWidget : gWidgetData[m_nScreen].gCheckWidget; 1016 gint indicator_size, indicator_spacing; 1017 gtk_widget_style_get( widget, 1018 "indicator_size", &indicator_size, 1019 "indicator_spacing", &indicator_spacing, 1020 (char *)NULL); 1021 indicator_size += 2*indicator_spacing; // guess overpaint of theme 1022 rNativeBoundingRegion = rControlRegion; 1023 Rectangle aIndicatorRect( Point( 0, 1024 (rControlRegion.GetHeight()-indicator_size)/2), 1025 Size( indicator_size, indicator_size ) ); 1026 rNativeContentRegion = aIndicatorRect; 1027 returnVal = sal_True; 1028 } 1029 if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL ) 1030 { 1031 NWEnsureGTKEditBox( m_nScreen ); 1032 GtkWidget* widget = gWidgetData[m_nScreen].gEditBoxWidget; 1033 GtkRequisition aReq; 1034 gtk_widget_size_request( widget, &aReq ); 1035 Rectangle aEditRect = rControlRegion; 1036 long nHeight = (aEditRect.GetHeight() > aReq.height+1) ? aEditRect.GetHeight() : aReq.height+1; 1037 aEditRect = Rectangle( aEditRect.TopLeft(), 1038 Size( aEditRect.GetWidth(), nHeight ) ); 1039 rNativeBoundingRegion = aEditRect; 1040 rNativeContentRegion = rNativeBoundingRegion; 1041 returnVal = sal_True; 1042 } 1043 if( (nType == CTRL_SLIDER) && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) ) 1044 { 1045 NWEnsureGTKSlider( m_nScreen ); 1046 GtkWidget* widget = (nPart == PART_THUMB_HORZ) ? gWidgetData[m_nScreen].gHScale : gWidgetData[m_nScreen].gVScale; 1047 gint slider_length = 10; 1048 gint slider_width = 10; 1049 gtk_widget_style_get( widget, 1050 "slider-width", &slider_width, 1051 "slider-length", &slider_length, 1052 (char *)NULL); 1053 Rectangle aRect( rControlRegion ); 1054 if( nPart == PART_THUMB_HORZ ) 1055 { 1056 aRect.Right() = aRect.Left() + slider_length - 1; 1057 aRect.Bottom() = aRect.Top() + slider_width - 1; 1058 } 1059 else 1060 { 1061 aRect.Bottom() = aRect.Top() + slider_length - 1; 1062 aRect.Right() = aRect.Left() + slider_width - 1; 1063 } 1064 rNativeBoundingRegion = rNativeContentRegion = aRect; 1065 returnVal = sal_True; 1066 } 1067 1068 return( returnVal ); 1069 } 1070 1071 1072 /************************************************************************ 1073 * Individual control drawing functions 1074 ************************************************************************/ 1075 sal_Bool GtkSalGraphics::NWPaintGTKButton( 1076 GdkDrawable* gdkDrawable, 1077 ControlType, ControlPart, 1078 const Rectangle& rControlRectangle, 1079 const clipList& rClipList, 1080 ControlState nState, const ImplControlValue&, 1081 const OUString& ) 1082 { 1083 GtkStateType stateType; 1084 GtkShadowType shadowType; 1085 gboolean interiorFocus; 1086 gint focusWidth; 1087 gint focusPad; 1088 sal_Bool bDrawFocus = sal_True; 1089 gint x, y, w, h; 1090 GtkBorder aDefBorder; 1091 GtkBorder* pBorder; 1092 GdkRectangle clipRect; 1093 1094 NWEnsureGTKButton( m_nScreen ); 1095 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1096 1097 x = rControlRectangle.Left(); 1098 y = rControlRectangle.Top(); 1099 w = rControlRectangle.GetWidth(); 1100 h = rControlRectangle.GetHeight(); 1101 1102 // Grab some button style attributes 1103 gtk_widget_style_get( gWidgetData[m_nScreen].gBtnWidget, "focus-line-width", &focusWidth, 1104 "focus-padding", &focusPad, 1105 "interior_focus", &interiorFocus, 1106 "default_border", &pBorder, 1107 (char *)NULL ); 1108 1109 // Make sure the border values exist, otherwise use some defaults 1110 if ( pBorder ) 1111 { 1112 NW_gtk_border_set_from_border( aDefBorder, pBorder ); 1113 gtk_border_free( pBorder ); 1114 } 1115 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder ); 1116 1117 // If the button is too small, don't ever draw focus or grab more space 1118 if ( (w < 16) || (h < 16) ) 1119 bDrawFocus = sal_False; 1120 1121 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 1122 1123 gint xi = x, yi = y, wi = w, hi = h; 1124 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus ) 1125 { 1126 xi += aDefBorder.left; 1127 yi += aDefBorder.top; 1128 wi -= aDefBorder.left + aDefBorder.right; 1129 hi -= aDefBorder.top + aDefBorder.bottom; 1130 } 1131 1132 if ( !interiorFocus && bDrawFocus ) 1133 { 1134 xi += focusWidth + focusPad; 1135 yi += focusWidth + focusPad; 1136 wi -= 2 * (focusWidth + focusPad); 1137 hi -= 2 * (focusWidth + focusPad); 1138 } 1139 1140 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it) 1141 { 1142 clipRect.x = it->Left(); 1143 clipRect.y = it->Top(); 1144 clipRect.width = it->GetWidth(); 1145 clipRect.height = it->GetHeight(); 1146 1147 // Buttons must paint opaque since some themes have alpha-channel enabled buttons 1148 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 1149 &clipRect, m_pWindow, "base", x, y, w, h ); 1150 1151 if ( (nState & CTRL_STATE_DEFAULT) && (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief == GTK_RELIEF_NORMAL) ) 1152 { 1153 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, 1154 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "buttondefault", x, y, w, h ); 1155 } 1156 1157 if ( (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief != GTK_RELIEF_NONE) 1158 || (nState & CTRL_STATE_PRESSED) 1159 || (nState & CTRL_STATE_ROLLOVER) ) 1160 { 1161 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, shadowType, 1162 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "button", xi, yi, wi, hi ); 1163 } 1164 } 1165 #if 0 // VCL draws focus rects 1166 // Draw focus rect 1167 if ( (nState & CTRL_STATE_FOCUSED) && (nState & CTRL_STATE_ENABLED) && bDrawFocus ) 1168 { 1169 if (interiorFocus) 1170 { 1171 x += gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad; 1172 y += gWidgetData[m_nScreen].gBtnWidget->style->ythickness + focusPad; 1173 w -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad); 1174 h -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad); 1175 } 1176 else 1177 { 1178 x -= focusWidth + focusPad; 1179 y -= focusWidth + focusPad; 1180 w += 2 * (focusWidth + focusPad); 1181 h += 2 * (focusWidth + focusPad); 1182 } 1183 if ( !interiorFocus ) 1184 gtk_paint_focus( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, &clipRect, 1185 gWidgetData[m_nScreen].gBtnWidget, "button", x, y, w, h ); 1186 } 1187 #endif 1188 1189 return( sal_True ); 1190 } 1191 1192 static Rectangle NWGetButtonArea( int nScreen, 1193 ControlType, ControlPart, Rectangle aAreaRect, ControlState nState, 1194 const ImplControlValue&, const OUString& ) 1195 { 1196 gboolean interiorFocus; 1197 gint focusWidth; 1198 gint focusPad; 1199 GtkBorder aDefBorder; 1200 GtkBorder * pBorder; 1201 sal_Bool bDrawFocus = sal_True; 1202 Rectangle aRect; 1203 gint x, y, w, h; 1204 1205 NWEnsureGTKButton( nScreen ); 1206 gtk_widget_style_get( gWidgetData[nScreen].gBtnWidget, 1207 "focus-line-width", &focusWidth, 1208 "focus-padding", &focusPad, 1209 "interior_focus", &interiorFocus, 1210 "default_border", &pBorder, 1211 (char *)NULL ); 1212 1213 // Make sure the border values exist, otherwise use some defaults 1214 if ( pBorder ) 1215 { 1216 NW_gtk_border_set_from_border( aDefBorder, pBorder ); 1217 gtk_border_free( pBorder ); 1218 } 1219 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder ); 1220 1221 x = aAreaRect.Left(); 1222 y = aAreaRect.Top(); 1223 w = aAreaRect.GetWidth(); 1224 h = aAreaRect.GetHeight(); 1225 1226 // If the button is too small, don't ever draw focus or grab more space 1227 if ( (w < 16) || (h < 16) ) 1228 bDrawFocus = sal_False; 1229 1230 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus ) 1231 { 1232 x -= aDefBorder.left; 1233 y -= aDefBorder.top; 1234 w += aDefBorder.left + aDefBorder.right; 1235 h += aDefBorder.top + aDefBorder.bottom; 1236 } 1237 1238 aRect = Rectangle( Point( x, y ), Size( w, h ) ); 1239 1240 return( aRect ); 1241 } 1242 1243 //------------------------------------- 1244 1245 sal_Bool GtkSalGraphics::NWPaintGTKRadio( GdkDrawable* gdkDrawable, 1246 ControlType, ControlPart, 1247 const Rectangle& rControlRectangle, 1248 const clipList& rClipList, 1249 ControlState nState, 1250 const ImplControlValue& aValue, 1251 const OUString& ) 1252 { 1253 GtkStateType stateType; 1254 GtkShadowType shadowType; 1255 sal_Bool isChecked = (aValue.getTristateVal()==BUTTONVALUE_ON); 1256 gint x, y; 1257 GdkRectangle clipRect; 1258 1259 NWEnsureGTKButton( m_nScreen ); 1260 NWEnsureGTKRadio( m_nScreen ); 1261 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1262 1263 gint indicator_size; 1264 gtk_widget_style_get( gWidgetData[m_nScreen].gRadioWidget, "indicator_size", &indicator_size, (char *)NULL); 1265 1266 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2; 1267 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2; 1268 1269 // Set the shadow based on if checked or not so we get a freakin checkmark. 1270 shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT; 1271 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidget, nState, stateType ); 1272 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidgetSibling, nState, stateType ); 1273 1274 // GTK enforces radio groups, so that if we don't have 2 buttons in the group, 1275 // the single button will always be active. So we have to have 2 buttons. 1276 1277 // #i59666# set the members directly where we should use 1278 // gtk_toggle_button_set_active. reason: there are animated themes 1279 // which are in active state only after a while leading to painting 1280 // intermediate states between active/inactive. Let's hope that 1281 // GtkToggleButtone stays binary compatible. 1282 if (!isChecked) 1283 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidgetSibling)->active = sal_True; 1284 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidget)->active = isChecked; 1285 1286 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1287 { 1288 clipRect.x = it->Left(); 1289 clipRect.y = it->Top(); 1290 clipRect.width = it->GetWidth(); 1291 clipRect.height = it->GetHeight(); 1292 1293 gtk_paint_option( gWidgetData[m_nScreen].gRadioWidget->style, gdkDrawable, stateType, shadowType, 1294 &clipRect, gWidgetData[m_nScreen].gRadioWidget, "radiobutton", 1295 x, y, indicator_size, indicator_size ); 1296 } 1297 1298 return( sal_True ); 1299 } 1300 1301 //------------------------------------- 1302 1303 sal_Bool GtkSalGraphics::NWPaintGTKCheck( GdkDrawable* gdkDrawable, 1304 ControlType, ControlPart, 1305 const Rectangle& rControlRectangle, 1306 const clipList& rClipList, 1307 ControlState nState, 1308 const ImplControlValue& aValue, 1309 const OUString& ) 1310 { 1311 GtkStateType stateType; 1312 GtkShadowType shadowType; 1313 bool isChecked = (aValue.getTristateVal() == BUTTONVALUE_ON); 1314 bool isInconsistent = (aValue.getTristateVal() == BUTTONVALUE_MIXED); 1315 GdkRectangle clipRect; 1316 gint x,y; 1317 1318 NWEnsureGTKButton( m_nScreen ); 1319 NWEnsureGTKCheck( m_nScreen ); 1320 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1321 1322 gint indicator_size; 1323 gtk_widget_style_get( gWidgetData[m_nScreen].gCheckWidget, "indicator_size", &indicator_size, (char *)NULL); 1324 1325 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2; 1326 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2; 1327 1328 // Set the shadow based on if checked or not so we get a checkmark. 1329 shadowType = isChecked ? GTK_SHADOW_IN : isInconsistent ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_OUT; 1330 NWSetWidgetState( gWidgetData[m_nScreen].gCheckWidget, nState, stateType ); 1331 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gCheckWidget)->active = isChecked; 1332 1333 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1334 { 1335 clipRect.x = it->Left(); 1336 clipRect.y = it->Top(); 1337 clipRect.width = it->GetWidth(); 1338 clipRect.height = it->GetHeight(); 1339 1340 gtk_paint_check( gWidgetData[m_nScreen].gCheckWidget->style, gdkDrawable, stateType, shadowType, 1341 &clipRect, gWidgetData[m_nScreen].gCheckWidget, "checkbutton", 1342 x, y, indicator_size, indicator_size ); 1343 } 1344 1345 return( sal_True ); 1346 } 1347 1348 //------------------------------------- 1349 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow ) 1350 { 1351 // Size the arrow appropriately 1352 Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 ); 1353 rArrow.SetSize( aSize ); 1354 1355 rArrow.SetPos( Point( 1356 rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2, 1357 rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2 1358 ) ); 1359 } 1360 1361 sal_Bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart, 1362 const Rectangle& rControlRectangle, 1363 const clipList&, 1364 ControlState nState, 1365 const ImplControlValue& aValue, 1366 const OUString& ) 1367 { 1368 OSL_ASSERT( aValue.getType() == CTRL_SCROLLBAR ); 1369 const ScrollbarValue* pScrollbarVal = static_cast<const ScrollbarValue *>(&aValue); 1370 GdkPixmap* pixmap = NULL; 1371 Rectangle pixmapRect, scrollbarRect; 1372 GtkStateType stateType; 1373 GtkShadowType shadowType; 1374 GtkScrollbar * scrollbarWidget; 1375 GtkStyle * style; 1376 GtkAdjustment* scrollbarValues = NULL; 1377 GtkOrientation scrollbarOrientation; 1378 Rectangle thumbRect = pScrollbarVal->maThumbRect; 1379 Rectangle button11BoundRect = pScrollbarVal->maButton1Rect; // backward 1380 Rectangle button22BoundRect = pScrollbarVal->maButton2Rect; // forward 1381 Rectangle button12BoundRect = pScrollbarVal->maButton1Rect; // secondary forward 1382 Rectangle button21BoundRect = pScrollbarVal->maButton2Rect; // secondary backward 1383 GtkArrowType button1Type; // backward 1384 GtkArrowType button2Type; // forward 1385 gchar * scrollbarTagH = (gchar *) "hscrollbar"; 1386 gchar * scrollbarTagV = (gchar *) "vscrollbar"; 1387 gchar * scrollbarTag = NULL; 1388 Rectangle arrowRect; 1389 gint slider_width = 0; 1390 gint stepper_size = 0; 1391 gint stepper_spacing = 0; 1392 gint trough_border = 0; 1393 gint min_slider_length = 0; 1394 gint vShim = 0; 1395 gint hShim = 0; 1396 gint x,y,w,h; 1397 1398 // make controlvalue rectangles relative to area 1399 thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1400 button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1401 button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1402 button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1403 button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1404 1405 NWEnsureGTKButton( m_nScreen ); 1406 NWEnsureGTKScrollbars( m_nScreen ); 1407 NWEnsureGTKArrow( m_nScreen ); 1408 1409 // Find the overall bounding rect of the control 1410 pixmapRect = rControlRectangle; 1411 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 1, 1412 pixmapRect.GetHeight() + 1 ) ); 1413 scrollbarRect = pixmapRect; 1414 1415 if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) ) 1416 return( sal_True ); 1417 1418 // Grab some button style attributes 1419 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, 1420 "slider_width", &slider_width, 1421 "stepper_size", &stepper_size, 1422 "trough_border", &trough_border, 1423 "stepper_spacing", &stepper_spacing, 1424 "min_slider_length", &min_slider_length, (char *)NULL ); 1425 gboolean has_forward; 1426 gboolean has_forward2; 1427 gboolean has_backward; 1428 gboolean has_backward2; 1429 1430 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward, 1431 "has-secondary-forward-stepper", &has_forward2, 1432 "has-backward-stepper", &has_backward, 1433 "has-secondary-backward-stepper", &has_backward2, (char *)NULL ); 1434 gint magic = trough_border ? 1 : 0; 1435 gint nFirst = 0; 1436 1437 if ( has_backward ) nFirst += 1; 1438 if ( has_forward2 ) nFirst += 1; 1439 1440 if ( nPart == PART_DRAW_BACKGROUND_HORZ ) 1441 { 1442 unsigned int sliderHeight = slider_width + (trough_border * 2); 1443 vShim = (pixmapRect.GetHeight() - sliderHeight) / 2; 1444 1445 scrollbarRect.Move( 0, vShim ); 1446 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), sliderHeight ) ); 1447 1448 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollHorizWidget ); 1449 scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL; 1450 scrollbarTag = scrollbarTagH; 1451 button1Type = GTK_ARROW_LEFT; 1452 button2Type = GTK_ARROW_RIGHT; 1453 1454 if ( has_backward ) 1455 { 1456 button12BoundRect.Move( stepper_size - trough_border, 1457 (scrollbarRect.GetHeight() - slider_width) / 2 ); 1458 } 1459 1460 button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1461 button11BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1462 button12BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1463 1464 if ( has_backward2 ) 1465 { 1466 button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1467 button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1468 } 1469 else 1470 { 1471 button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1472 } 1473 1474 button21BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1475 button22BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1476 1477 thumbRect.Bottom() = thumbRect.Top() + slider_width - 1; 1478 // Make sure the thumb is at least the default width (so we don't get tiny thumbs), 1479 // but if the VCL gives us a size smaller than the theme's default thumb size, 1480 // honor the VCL size 1481 #if 0 1482 if ( (thumbRect.GetWidth() < min_slider_length) 1483 && ((scrollbarRect.GetWidth()-button1BoundRect.GetWidth()-button2BoundRect.GetWidth()) > min_slider_length) ) 1484 thumbRect.SetSize( Size( min_slider_length, thumbRect.GetHeight() ) ); 1485 #endif 1486 1487 thumbRect.Right() += magic; 1488 // Center vertically in the track 1489 thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1490 } 1491 else 1492 { 1493 unsigned int sliderWidth = slider_width + (trough_border * 2); 1494 hShim = (pixmapRect.GetWidth() - sliderWidth) / 2; 1495 1496 scrollbarRect.Move( hShim, 0 ); 1497 scrollbarRect.SetSize( Size( sliderWidth, scrollbarRect.GetHeight() ) ); 1498 1499 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollVertWidget ); 1500 scrollbarOrientation = GTK_ORIENTATION_VERTICAL; 1501 scrollbarTag = scrollbarTagV; 1502 button1Type = GTK_ARROW_UP; 1503 button2Type = GTK_ARROW_DOWN; 1504 1505 if ( has_backward ) 1506 { 1507 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 1508 stepper_size + trough_border ); 1509 } 1510 button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border ); 1511 button11BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1512 button12BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1513 1514 if ( has_backward2 ) 1515 { 1516 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 ); 1517 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 ); 1518 } 1519 else 1520 { 1521 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 ); 1522 } 1523 1524 button21BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1525 button22BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1526 1527 thumbRect.Right() = thumbRect.Left() + slider_width - 1; 1528 #if 0 1529 // Make sure the thumb is at least the default width (so we don't get tiny thumbs), 1530 // but if the VCL gives us a size smaller than the theme's default thumb size, 1531 // honor the VCL size 1532 if ( (thumbRect.GetHeight() < min_slider_length) 1533 && ((scrollbarRect.GetHeight()-button1BoundRect.GetHeight()-button2BoundRect.GetHeight()) > min_slider_length) ) 1534 thumbRect.SetSize( Size( thumbRect.GetWidth(), min_slider_length ) ); 1535 #endif 1536 1537 thumbRect.Bottom() += magic; 1538 // Center horizontally in the track 1539 thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 ); 1540 } 1541 1542 sal_Bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 ); 1543 1544 scrollbarValues = gtk_range_get_adjustment( GTK_RANGE(scrollbarWidget) ); 1545 if ( scrollbarValues == NULL ) 1546 scrollbarValues = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 1547 if ( nPart == PART_DRAW_BACKGROUND_HORZ ) 1548 { 1549 scrollbarValues->lower = pScrollbarVal->mnMin; 1550 scrollbarValues->upper = pScrollbarVal->mnMax; 1551 scrollbarValues->value = pScrollbarVal->mnCur; 1552 scrollbarValues->page_size = scrollbarRect.GetWidth() / 2; 1553 } 1554 else 1555 { 1556 scrollbarValues->lower = pScrollbarVal->mnMin; 1557 scrollbarValues->upper = pScrollbarVal->mnMax; 1558 scrollbarValues->value = pScrollbarVal->mnCur; 1559 scrollbarValues->page_size = scrollbarRect.GetHeight() / 2; 1560 } 1561 gtk_adjustment_changed( scrollbarValues ); 1562 1563 // as multiple paints are required for the scrollbar 1564 // painting them directly to the window flickers 1565 pixmap = NWGetPixmapFromScreen( pixmapRect ); 1566 if( ! pixmap ) 1567 return sal_False; 1568 x = y = 0; 1569 1570 w = pixmapRect.GetWidth(); 1571 h = pixmapRect.GetHeight(); 1572 1573 GdkDrawable* const &gdkDrawable = GDK_DRAWABLE( pixmap ); 1574 GdkRectangle* gdkRect = NULL; 1575 1576 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1577 NWSetWidgetState( GTK_WIDGET(scrollbarWidget), nState, stateType ); 1578 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 1579 style = GTK_WIDGET( scrollbarWidget )->style; 1580 1581 // ----------------- TROUGH 1582 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, 1583 GTK_STATE_NORMAL, GTK_SHADOW_NONE, gdkRect, 1584 m_pWindow, "base", x, y, 1585 w, h ); 1586 gtk_paint_box( style, gdkDrawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, 1587 gdkRect, GTK_WIDGET(scrollbarWidget), "trough", 1588 x, y, 1589 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() ); 1590 1591 if ( nState & CTRL_STATE_FOCUSED ) 1592 { 1593 gtk_paint_focus( style, gdkDrawable, GTK_STATE_ACTIVE, 1594 gdkRect, GTK_WIDGET(scrollbarWidget), "trough", 1595 x, y, 1596 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() ); 1597 } 1598 1599 // ----------------- THUMB 1600 if ( has_slider ) 1601 { 1602 NWConvertVCLStateToGTKState( pScrollbarVal->mnThumbState, &stateType, &shadowType ); 1603 if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED ) stateType = GTK_STATE_PRELIGHT; 1604 gtk_paint_slider( style, gdkDrawable, stateType, GTK_SHADOW_OUT, 1605 gdkRect, GTK_WIDGET(scrollbarWidget), "slider", 1606 x+hShim+thumbRect.Left(), y+vShim+thumbRect.Top(), 1607 thumbRect.GetWidth(), thumbRect.GetHeight(), scrollbarOrientation ); 1608 } 1609 // ----------------- BUTTON 1 // 1610 if ( has_backward ) 1611 { 1612 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType ); 1613 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1614 gtk_paint_box( style, gdkDrawable, stateType, shadowType, 1615 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper", 1616 x+hShim+button11BoundRect.Left(), y+vShim+button11BoundRect.Top(), 1617 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() ); 1618 // ----------------- ARROW 1 1619 NWCalcArrowRect( button11BoundRect, arrowRect ); 1620 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1621 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True, 1622 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1623 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1624 } 1625 if ( has_forward2 ) 1626 { 1627 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType ); 1628 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1629 gtk_paint_box( style, gdkDrawable, stateType, shadowType, 1630 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper", 1631 x+hShim+button12BoundRect.Left(), y+vShim+button12BoundRect.Top(), 1632 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() ); 1633 // ----------------- ARROW 1 1634 NWCalcArrowRect( button12BoundRect, arrowRect ); 1635 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1636 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True, 1637 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1638 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1639 } 1640 // ----------------- BUTTON 2 1641 if ( has_backward2 ) 1642 { 1643 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType ); 1644 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1645 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect, 1646 GTK_WIDGET(scrollbarWidget), "stepper", 1647 x+hShim+button21BoundRect.Left(), y+vShim+button21BoundRect.Top(), 1648 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() ); 1649 // ----------------- ARROW 2 1650 NWCalcArrowRect( button21BoundRect, arrowRect ); 1651 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1652 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True, 1653 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1654 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1655 } 1656 if ( has_forward ) 1657 { 1658 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType ); 1659 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1660 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect, 1661 GTK_WIDGET(scrollbarWidget), "stepper", 1662 x+hShim+button22BoundRect.Left(), y+vShim+button22BoundRect.Top(), 1663 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() ); 1664 // ----------------- ARROW 2 1665 NWCalcArrowRect( button22BoundRect, arrowRect ); 1666 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1667 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True, 1668 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1669 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1670 } 1671 1672 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) ) 1673 { 1674 g_object_unref( pixmap ); 1675 return( sal_False ); 1676 } 1677 g_object_unref( pixmap ); 1678 1679 return( sal_True ); 1680 } 1681 1682 //--- 1683 1684 static Rectangle NWGetScrollButtonRect( int nScreen, ControlPart nPart, Rectangle aAreaRect ) 1685 { 1686 gint slider_width; 1687 gint stepper_size; 1688 gint stepper_spacing; 1689 gint trough_border; 1690 1691 NWEnsureGTKScrollbars( nScreen ); 1692 1693 // Grab some button style attributes 1694 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget, 1695 "slider-width", &slider_width, 1696 "stepper-size", &stepper_size, 1697 "trough-border", &trough_border, 1698 "stepper-spacing", &stepper_spacing, (char *)NULL ); 1699 1700 gboolean has_forward; 1701 gboolean has_forward2; 1702 gboolean has_backward; 1703 gboolean has_backward2; 1704 1705 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget, 1706 "has-forward-stepper", &has_forward, 1707 "has-secondary-forward-stepper", &has_forward2, 1708 "has-backward-stepper", &has_backward, 1709 "has-secondary-backward-stepper", &has_backward2, (char *)NULL ); 1710 gint buttonWidth; 1711 gint buttonHeight; 1712 Rectangle buttonRect; 1713 1714 gint nFirst = 0; 1715 gint nSecond = 0; 1716 1717 if ( has_forward ) nSecond += 1; 1718 if ( has_forward2 ) nFirst += 1; 1719 if ( has_backward ) nFirst += 1; 1720 if ( has_backward2 ) nSecond += 1; 1721 1722 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) ) 1723 { 1724 buttonWidth = slider_width + 2 * trough_border; 1725 buttonHeight = stepper_size + trough_border + stepper_spacing; 1726 } 1727 else 1728 { 1729 buttonWidth = stepper_size + trough_border + stepper_spacing; 1730 buttonHeight = slider_width + 2 * trough_border; 1731 } 1732 1733 if ( nPart == PART_BUTTON_UP ) 1734 { 1735 buttonHeight *= nFirst; 1736 buttonHeight -= 1; 1737 buttonRect.setX( aAreaRect.Left() ); 1738 buttonRect.setY( aAreaRect.Top() ); 1739 } 1740 else if ( nPart == PART_BUTTON_LEFT ) 1741 { 1742 buttonWidth *= nFirst; 1743 buttonWidth -= 1; 1744 buttonRect.setX( aAreaRect.Left() ); 1745 buttonRect.setY( aAreaRect.Top() ); 1746 } 1747 else if ( nPart == PART_BUTTON_DOWN ) 1748 { 1749 buttonHeight *= nSecond; 1750 buttonRect.setX( aAreaRect.Left() ); 1751 buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight ); 1752 } 1753 else if ( nPart == PART_BUTTON_RIGHT ) 1754 { 1755 buttonWidth *= nSecond; 1756 buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth ); 1757 buttonRect.setY( aAreaRect.Top() ); 1758 } 1759 1760 buttonRect.SetSize( Size( buttonWidth, buttonHeight ) ); 1761 1762 return( buttonRect ); 1763 } 1764 1765 //------------------------------------- 1766 1767 sal_Bool GtkSalGraphics::NWPaintGTKEditBox( GdkDrawable* gdkDrawable, 1768 ControlType nType, ControlPart nPart, 1769 const Rectangle& rControlRectangle, 1770 const clipList& rClipList, 1771 ControlState nState, 1772 const ImplControlValue& aValue, 1773 const OUString& rCaption ) 1774 { 1775 Rectangle pixmapRect; 1776 GdkRectangle clipRect; 1777 1778 // Find the overall bounding rect of the buttons's drawing area, 1779 // plus its actual draw rect excluding adornment 1780 pixmapRect = NWGetEditBoxPixmapRect( m_nScreen, nType, nPart, rControlRectangle, 1781 nState, aValue, rCaption ); 1782 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1783 { 1784 clipRect.x = it->Left(); 1785 clipRect.y = it->Top(); 1786 clipRect.width = it->GetWidth(); 1787 clipRect.height = it->GetHeight(); 1788 1789 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, pixmapRect, nState, aValue, rCaption ); 1790 } 1791 1792 return( sal_True ); 1793 } 1794 1795 1796 /* Take interior/exterior focus into account and return 1797 * the bounding rectangle of the edit box including 1798 * any focus requirements. 1799 */ 1800 static Rectangle NWGetEditBoxPixmapRect(int nScreen, 1801 ControlType, 1802 ControlPart, 1803 Rectangle aAreaRect, 1804 ControlState, 1805 const ImplControlValue&, 1806 const OUString& ) 1807 { 1808 Rectangle pixmapRect = aAreaRect; 1809 gboolean interiorFocus; 1810 gint focusWidth; 1811 1812 NWEnsureGTKEditBox( nScreen ); 1813 1814 // Grab some entry style attributes 1815 gtk_widget_style_get( gWidgetData[nScreen].gEditBoxWidget, 1816 "focus-line-width", &focusWidth, 1817 "interior-focus", &interiorFocus, (char *)NULL ); 1818 1819 if ( !interiorFocus ) 1820 { 1821 pixmapRect.Move( -(focusWidth), -(focusWidth) ); 1822 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + (2*(focusWidth)), 1823 pixmapRect.GetHeight() + (2*(focusWidth)) ) ); 1824 } 1825 1826 return( pixmapRect ); 1827 } 1828 1829 1830 /* Paint a GTK Entry widget into the specified GdkPixmap. 1831 * All coordinates should be local to the Pixmap, NOT 1832 * screen/window coordinates. 1833 */ 1834 static void NWPaintOneEditBox( int nScreen, 1835 GdkDrawable * gdkDrawable, 1836 GdkRectangle * gdkRect, 1837 ControlType nType, 1838 ControlPart, 1839 Rectangle aEditBoxRect, 1840 ControlState nState, 1841 const ImplControlValue&, 1842 const OUString& ) 1843 { 1844 GtkStateType stateType; 1845 GtkShadowType shadowType; 1846 GtkWidget *widget; 1847 1848 NWEnsureGTKButton( nScreen ); 1849 NWEnsureGTKEditBox( nScreen ); 1850 NWEnsureGTKSpinButton( nScreen ); 1851 NWEnsureGTKCombo( nScreen ); 1852 NWEnsureGTKScrolledWindow( nScreen ); 1853 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1854 1855 /* border's shadowType for gtk entries is always GTK_SHADOW_IN (see gtkentry.c) 1856 shadowType = GTK_SHADOW_IN; 1857 */ 1858 1859 switch ( nType ) 1860 { 1861 case CTRL_SPINBOX: 1862 widget = gWidgetData[nScreen].gSpinButtonWidget; 1863 break; 1864 1865 case CTRL_MULTILINE_EDITBOX: 1866 widget = gWidgetData[nScreen].gScrolledWindowWidget; 1867 break; 1868 case CTRL_COMBOBOX: 1869 widget = GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry; 1870 break; 1871 1872 default: 1873 widget = gWidgetData[nScreen].gEditBoxWidget; 1874 break; 1875 } 1876 1877 if ( stateType == GTK_STATE_PRELIGHT ) 1878 stateType = GTK_STATE_NORMAL; 1879 1880 // Blueprint needs to paint entry_bg with a Button widget, not an Entry widget to get 1881 // a nice white (or whatever default color) background 1882 GtkWidget* pBGWidget = widget; 1883 if( GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround ) 1884 { 1885 NWSetWidgetState( gWidgetData[nScreen].gBtnWidget, nState, stateType ); 1886 pBGWidget = gWidgetData[nScreen].gBtnWidget; 1887 } 1888 NWSetWidgetState( widget, nState, stateType ); 1889 1890 gtk_paint_flat_box( pBGWidget->style, gdkDrawable, stateType, GTK_SHADOW_NONE, 1891 gdkRect, pBGWidget, "entry_bg", 1892 aEditBoxRect.Left(), aEditBoxRect.Top(), 1893 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() ); 1894 gtk_paint_shadow( widget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, 1895 gdkRect, widget, "entry", 1896 aEditBoxRect.Left(), aEditBoxRect.Top(), 1897 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() ); 1898 1899 } 1900 1901 1902 1903 //------------------------------------- 1904 1905 sal_Bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, 1906 const Rectangle& rControlRectangle, 1907 const clipList&, 1908 ControlState nState, 1909 const ImplControlValue& aValue, 1910 const OUString& rCaption ) 1911 { 1912 GdkPixmap * pixmap; 1913 Rectangle pixmapRect; 1914 GtkStateType stateType; 1915 GtkShadowType shadowType; 1916 const SpinbuttonValue * pSpinVal = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue *>(&aValue) : NULL; 1917 Rectangle upBtnRect; 1918 ControlPart upBtnPart = PART_BUTTON_UP; 1919 ControlState upBtnState = CTRL_STATE_ENABLED; 1920 Rectangle downBtnRect; 1921 ControlPart downBtnPart = PART_BUTTON_DOWN; 1922 ControlState downBtnState = CTRL_STATE_ENABLED; 1923 1924 NWEnsureGTKButton( m_nScreen ); 1925 NWEnsureGTKSpinButton( m_nScreen ); 1926 NWEnsureGTKArrow( m_nScreen ); 1927 1928 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1929 1930 if ( pSpinVal ) 1931 { 1932 upBtnPart = pSpinVal->mnUpperPart; 1933 upBtnState = pSpinVal->mnUpperState; 1934 1935 downBtnPart = pSpinVal->mnLowerPart; 1936 downBtnState = pSpinVal->mnLowerState; 1937 } 1938 1939 // CTRL_SPINBUTTONS pass their area in pSpinVal, not in rControlRectangle 1940 if ( nType == CTRL_SPINBUTTONS ) 1941 { 1942 if ( !pSpinVal ) 1943 { 1944 std::fprintf( stderr, "Tried to draw CTRL_SPINBUTTONS, but the SpinButtons data structure didn't exist!\n" ); 1945 return( false ); 1946 } 1947 pixmapRect = pSpinVal->maUpperRect; 1948 pixmapRect.Union( pSpinVal->maLowerRect ); 1949 } 1950 else 1951 pixmapRect = rControlRectangle; 1952 1953 1954 pixmap = NWGetPixmapFromScreen( pixmapRect ); 1955 if ( !pixmap ) 1956 return( sal_False ); 1957 1958 upBtnRect = NWGetSpinButtonRect( m_nScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); 1959 downBtnRect = NWGetSpinButtonRect( m_nScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); 1960 1961 if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) 1962 { 1963 // Draw an edit field for SpinBoxes and ComboBoxes 1964 Rectangle aEditBoxRect( pixmapRect ); 1965 aEditBoxRect.SetSize( Size( upBtnRect.Left() - pixmapRect.Left(), aEditBoxRect.GetHeight() ) ); 1966 aEditBoxRect.setX( 0 ); 1967 aEditBoxRect.setY( 0 ); 1968 1969 NWPaintOneEditBox( m_nScreen, pixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); 1970 } 1971 1972 NWSetWidgetState( gWidgetData[m_nScreen].gSpinButtonWidget, nState, stateType ); 1973 gtk_widget_style_get( gWidgetData[m_nScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); 1974 1975 if ( shadowType != GTK_SHADOW_NONE ) 1976 { 1977 Rectangle shadowRect( upBtnRect ); 1978 1979 shadowRect.Union( downBtnRect ); 1980 gtk_paint_box( gWidgetData[m_nScreen].gSpinButtonWidget->style, pixmap, GTK_STATE_NORMAL, shadowType, NULL, 1981 gWidgetData[m_nScreen].gSpinButtonWidget, "spinbutton", 1982 (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), 1983 shadowRect.GetWidth(), shadowRect.GetHeight() ); 1984 } 1985 1986 NWPaintOneSpinButton( m_nScreen, pixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); 1987 NWPaintOneSpinButton( m_nScreen, pixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); 1988 1989 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) ) 1990 { 1991 g_object_unref( pixmap ); 1992 return( sal_False ); 1993 } 1994 1995 g_object_unref( pixmap ); 1996 return( sal_True ); 1997 } 1998 1999 //--- 2000 2001 static Rectangle NWGetSpinButtonRect( int nScreen, 2002 ControlType, 2003 ControlPart nPart, 2004 Rectangle aAreaRect, 2005 ControlState, 2006 const ImplControlValue&, 2007 const OUString& ) 2008 { 2009 gint buttonSize; 2010 Rectangle buttonRect; 2011 2012 NWEnsureGTKSpinButton( nScreen ); 2013 2014 buttonSize = MAX( PANGO_PIXELS( pango_font_description_get_size(GTK_WIDGET(gWidgetData[nScreen].gSpinButtonWidget)->style->font_desc) ), 2015 MIN_SPIN_ARROW_WIDTH ); 2016 buttonSize -= buttonSize % 2 - 1; /* force odd */ 2017 buttonRect.SetSize( Size( buttonSize + 2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness, 2018 buttonRect.GetHeight() ) ); 2019 buttonRect.setX( aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()) ); 2020 if ( nPart == PART_BUTTON_UP ) 2021 { 2022 buttonRect.setY( aAreaRect.Top() ); 2023 buttonRect.Bottom() = buttonRect.Top() + (aAreaRect.GetHeight() / 2); 2024 } 2025 else if( nPart == PART_BUTTON_DOWN ) 2026 { 2027 buttonRect.setY( aAreaRect.Top() + (aAreaRect.GetHeight() / 2) ); 2028 buttonRect.Bottom() = aAreaRect.Bottom(); // cover area completely 2029 } 2030 else 2031 { 2032 buttonRect.Right() = buttonRect.Left()-1; 2033 buttonRect.Left() = aAreaRect.Left(); 2034 buttonRect.Top() = aAreaRect.Top(); 2035 buttonRect.Bottom() = aAreaRect.Bottom(); 2036 } 2037 2038 return( buttonRect ); 2039 } 2040 2041 //--- 2042 2043 static void NWPaintOneSpinButton( int nScreen, 2044 GdkPixmap* pixmap, 2045 ControlType nType, 2046 ControlPart nPart, 2047 Rectangle aAreaRect, 2048 ControlState nState, 2049 const ImplControlValue& aValue, 2050 const OUString& rCaption ) 2051 { 2052 Rectangle buttonRect; 2053 GtkStateType stateType; 2054 GtkShadowType shadowType; 2055 Rectangle arrowRect; 2056 gint arrowSize; 2057 2058 NWEnsureGTKSpinButton( nScreen ); 2059 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2060 2061 buttonRect = NWGetSpinButtonRect( nScreen, nType, nPart, aAreaRect, nState, aValue, rCaption ); 2062 2063 NWSetWidgetState( gWidgetData[nScreen].gSpinButtonWidget, nState, stateType ); 2064 gtk_paint_box( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, shadowType, NULL, gWidgetData[nScreen].gSpinButtonWidget, 2065 (nPart == PART_BUTTON_UP) ? "spinbutton_up" : "spinbutton_down", 2066 (buttonRect.Left() - aAreaRect.Left()), (buttonRect.Top() - aAreaRect.Top()), 2067 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2068 2069 arrowSize = (buttonRect.GetWidth() - (2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness)) - 4; 2070 arrowSize -= arrowSize % 2 - 1; /* force odd */ 2071 arrowRect.SetSize( Size( arrowSize, arrowSize ) ); 2072 arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 ); 2073 if ( nPart == PART_BUTTON_UP ) 2074 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 + 1); 2075 else 2076 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 - 1); 2077 2078 gtk_paint_arrow( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[nScreen].gSpinButtonWidget, 2079 "spinbutton", (nPart == PART_BUTTON_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, sal_True, 2080 (arrowRect.Left() - aAreaRect.Left()), (arrowRect.Top() - aAreaRect.Top()), 2081 arrowRect.GetWidth(), arrowRect.GetHeight() ); 2082 } 2083 2084 2085 //------------------------------------- 2086 2087 sal_Bool GtkSalGraphics::NWPaintGTKComboBox( GdkDrawable* gdkDrawable, 2088 ControlType nType, ControlPart nPart, 2089 const Rectangle& rControlRectangle, 2090 const clipList& rClipList, 2091 ControlState nState, 2092 const ImplControlValue& aValue, 2093 const OUString& rCaption ) 2094 { 2095 Rectangle pixmapRect; 2096 Rectangle buttonRect; 2097 GtkStateType stateType; 2098 GtkShadowType shadowType; 2099 Rectangle arrowRect; 2100 gint x,y; 2101 GdkRectangle clipRect; 2102 2103 NWEnsureGTKButton( m_nScreen ); 2104 NWEnsureGTKArrow( m_nScreen ); 2105 NWEnsureGTKCombo( m_nScreen ); 2106 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2107 2108 // Find the overall bounding rect of the buttons's drawing area, 2109 // plus its actual draw rect excluding adornment 2110 pixmapRect = rControlRectangle; 2111 x = rControlRectangle.Left(); 2112 y = rControlRectangle.Top(); 2113 2114 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 2115 NWSetWidgetState( gWidgetData[m_nScreen].gComboWidget, nState, stateType ); 2116 NWSetWidgetState( gWidgetData[m_nScreen].gArrowWidget, nState, stateType ); 2117 2118 buttonRect = NWGetComboBoxButtonRect( m_nScreen, nType, PART_BUTTON_DOWN, pixmapRect, nState, aValue, rCaption ); 2119 if( nPart == PART_BUTTON_DOWN ) 2120 buttonRect.Left() += 1; 2121 2122 Rectangle aEditBoxRect( pixmapRect ); 2123 aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) ); 2124 2125 #define ARROW_EXTENT 0.7 2126 arrowRect.SetSize( Size( (gint)(MIN_ARROW_SIZE * ARROW_EXTENT), 2127 (gint)(MIN_ARROW_SIZE * ARROW_EXTENT) ) ); 2128 arrowRect.SetPos( Point( buttonRect.Left() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2), 2129 buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) ); 2130 2131 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2132 { 2133 clipRect.x = it->Left(); 2134 clipRect.y = it->Top(); 2135 clipRect.width = it->GetWidth(); 2136 clipRect.height = it->GetHeight(); 2137 2138 if( nPart == PART_ENTIRE_CONTROL ) 2139 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, aEditBoxRect, 2140 nState, aValue, rCaption ); 2141 2142 // Buttons must paint opaque since some themes have alpha-channel enabled buttons 2143 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 2144 &clipRect, m_pWindow, "base", 2145 x+(buttonRect.Left() - pixmapRect.Left()), 2146 y+(buttonRect.Top() - pixmapRect.Top()), 2147 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2148 gtk_paint_box( GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button->style, gdkDrawable, stateType, shadowType, 2149 &clipRect, GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button, "button", 2150 x+(buttonRect.Left() - pixmapRect.Left()), 2151 y+(buttonRect.Top() - pixmapRect.Top()), 2152 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2153 2154 gtk_paint_arrow( gWidgetData[m_nScreen].gArrowWidget->style, gdkDrawable, stateType, shadowType, 2155 &clipRect, gWidgetData[m_nScreen].gArrowWidget, "arrow", GTK_ARROW_DOWN, sal_True, 2156 x+(arrowRect.Left() - pixmapRect.Left()), y+(arrowRect.Top() - pixmapRect.Top()), 2157 arrowRect.GetWidth(), arrowRect.GetHeight() ); 2158 } 2159 2160 return( sal_True ); 2161 } 2162 2163 //---- 2164 2165 static Rectangle NWGetComboBoxButtonRect( int nScreen, 2166 ControlType, 2167 ControlPart nPart, 2168 Rectangle aAreaRect, 2169 ControlState, 2170 const ImplControlValue&, 2171 const OUString& ) 2172 { 2173 Rectangle aButtonRect; 2174 gint nArrowWidth; 2175 gint nButtonWidth; 2176 gint nFocusWidth; 2177 gint nFocusPad; 2178 2179 NWEnsureGTKArrow( nScreen ); 2180 2181 // Grab some button style attributes 2182 gtk_widget_style_get( gWidgetData[nScreen].gDropdownWidget, 2183 "focus-line-width", &nFocusWidth, 2184 "focus-padding", &nFocusPad, (char *)NULL ); 2185 2186 nArrowWidth = MIN_ARROW_SIZE + (GTK_MISC(gWidgetData[nScreen].gArrowWidget)->xpad * 2); 2187 nButtonWidth = nArrowWidth + 2188 ((BTN_CHILD_SPACING + gWidgetData[nScreen].gDropdownWidget->style->xthickness) * 2) 2189 + (2 * (nFocusWidth+nFocusPad)); 2190 if( nPart == PART_BUTTON_DOWN ) 2191 { 2192 aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) ); 2193 aButtonRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, 2194 aAreaRect.Top() ) ); 2195 } 2196 else if( nPart == PART_SUB_EDIT ) 2197 { 2198 NWEnsureGTKCombo( nScreen ); 2199 2200 gint adjust_x = GTK_CONTAINER(gWidgetData[nScreen].gComboWidget)->border_width + 2201 nFocusWidth + 2202 nFocusPad; 2203 gint adjust_y = adjust_x + gWidgetData[nScreen].gComboWidget->style->ythickness; 2204 adjust_x += gWidgetData[nScreen].gComboWidget->style->xthickness; 2205 aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - 2 * adjust_x, 2206 aAreaRect.GetHeight() - 2 * adjust_y ) ); 2207 Point aEditPos = aAreaRect.TopLeft(); 2208 aEditPos.X() += adjust_x; 2209 aEditPos.Y() += adjust_y; 2210 aButtonRect.SetPos( aEditPos ); 2211 } 2212 2213 return( aButtonRect ); 2214 } 2215 2216 //------------------------------------- 2217 2218 2219 2220 sal_Bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, 2221 const Rectangle& rControlRectangle, 2222 const clipList&, 2223 ControlState nState, 2224 const ImplControlValue& aValue, 2225 const OUString& ) 2226 { 2227 OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM ); 2228 GdkPixmap * pixmap; 2229 Rectangle pixmapRect; 2230 Rectangle tabRect; 2231 GtkStateType stateType; 2232 GtkShadowType shadowType; 2233 if( ! gWidgetData[ m_nScreen ].gCacheTabItems ) 2234 { 2235 gWidgetData[ m_nScreen ].gCacheTabItems = new NWPixmapCache( m_nScreen ); 2236 gWidgetData[ m_nScreen ].gCacheTabPages = new NWPixmapCache( m_nScreen ); 2237 } 2238 NWPixmapCache& aCacheItems = *gWidgetData[ m_nScreen ].gCacheTabItems; 2239 NWPixmapCache& aCachePage = *gWidgetData[ m_nScreen ].gCacheTabPages; 2240 2241 if( !aCacheItems.GetSize() ) 2242 aCacheItems.SetSize( 20 ); 2243 if( !aCachePage.GetSize() ) 2244 aCachePage.SetSize( 1 ); 2245 2246 if ( (nType == CTRL_TAB_ITEM) && (aValue.getType() != CTRL_TAB_ITEM) ) 2247 { 2248 return( false ); 2249 } 2250 2251 NWEnsureGTKButton( m_nScreen ); 2252 NWEnsureGTKNotebook( m_nScreen ); 2253 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2254 2255 // Find the overall bounding rect of the buttons's drawing area, 2256 // plus its actual draw rect excluding adornment 2257 pixmapRect = rControlRectangle; 2258 if ( nType == CTRL_TAB_ITEM ) 2259 { 2260 const TabitemValue * pTabitemValue = static_cast<const TabitemValue *>(&aValue); 2261 if ( !pTabitemValue->isFirst() ) 2262 { 2263 // GTK+ tabs overlap on the right edge (the top tab obscures the 2264 // left edge of the tab right "below" it, so adjust the rectangle 2265 // to draw tabs slightly large so the overlap happens 2266 pixmapRect.Move( -2, 0 ); 2267 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, pixmapRect.GetHeight() ) ); 2268 } 2269 if ( nState & CTRL_STATE_SELECTED ) 2270 { 2271 // In GTK+, the selected tab is 2px taller than all other tabs 2272 pixmapRect.Move( 0, -2 ); 2273 pixmapRect.Bottom() += 2; 2274 tabRect = pixmapRect; 2275 // Only draw over 1 pixel of the tab pane that this tab is drawn on top of. 2276 tabRect.Bottom() -= 1; 2277 } 2278 else 2279 tabRect = pixmapRect; 2280 2281 // Allow the tab to draw a right border if needed 2282 tabRect.Right() -= 1; 2283 2284 // #129732# avoid degenerate cases which might lead to crashes 2285 if( tabRect.GetWidth() <= 1 || tabRect.GetHeight() <= 1 ) 2286 return false; 2287 } 2288 2289 if( nType == CTRL_TAB_ITEM ) 2290 { 2291 if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) ) 2292 return NWRenderPixmapToScreen( pixmap, pixmapRect ); 2293 } 2294 else 2295 { 2296 if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) ) 2297 return NWRenderPixmapToScreen( pixmap, pixmapRect ); 2298 } 2299 2300 2301 // gtk_widget_set_state( gWidgetData[m_nScreen].gNotebookWidget, stateType ); 2302 2303 pixmap = gdk_pixmap_new( NULL, pixmapRect.GetWidth(), pixmapRect.GetHeight(), 2304 GetX11SalData()->GetDisplay()->GetVisual( m_nScreen ).GetDepth() ); 2305 GdkRectangle paintRect; 2306 paintRect.x = paintRect.y = 0; 2307 paintRect.width = pixmapRect.GetWidth(); 2308 paintRect.height = pixmapRect.GetHeight(); 2309 2310 gtk_paint_flat_box( m_pWindow->style, pixmap, GTK_STATE_NORMAL, 2311 GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", 0, 0, -1, -1); 2312 2313 NWSetWidgetState( gWidgetData[m_nScreen].gNotebookWidget, nState, stateType ); 2314 2315 switch( nType ) 2316 { 2317 case CTRL_TAB_BODY: 2318 break; 2319 2320 case CTRL_FIXEDBORDER: 2321 case CTRL_TAB_PANE: 2322 gtk_paint_box_gap( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget, 2323 (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); 2324 break; 2325 2326 case CTRL_TAB_ITEM: 2327 stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; 2328 2329 gtk_paint_extension( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget, 2330 (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), 2331 tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); 2332 2333 if ( nState & CTRL_STATE_SELECTED ) 2334 { 2335 gtk_paint_flat_box( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, 2336 (char *)"base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); 2337 } 2338 break; 2339 2340 default: 2341 break; 2342 } 2343 2344 // Crux seems to think it can make the pane without a left edge 2345 if ( nType == CTRL_FIXEDBORDER ) 2346 pixmapRect.Move( 1, 0 ); 2347 2348 // cache data 2349 if( nType == CTRL_TAB_ITEM ) 2350 aCacheItems.Fill( nType, nState, pixmapRect, pixmap ); 2351 else 2352 aCachePage.Fill( nType, nState, pixmapRect, pixmap ); 2353 2354 sal_Bool bSuccess = NWRenderPixmapToScreen(pixmap, pixmapRect); 2355 g_object_unref( pixmap ); 2356 return bSuccess; 2357 } 2358 2359 //------------------------------------- 2360 2361 sal_Bool GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable, 2362 ControlType nType, ControlPart nPart, 2363 const Rectangle& rControlRectangle, 2364 const clipList& rClipList, 2365 ControlState nState, 2366 const ImplControlValue& aValue, 2367 const OUString& rCaption ) 2368 { 2369 Rectangle pixmapRect; 2370 Rectangle widgetRect; 2371 Rectangle aIndicatorRect; 2372 GtkStateType stateType; 2373 GtkShadowType shadowType; 2374 gint bInteriorFocus; 2375 gint nFocusLineWidth; 2376 gint nFocusPadding; 2377 gint x,y; 2378 GdkRectangle clipRect; 2379 2380 NWEnsureGTKButton( m_nScreen ); 2381 NWEnsureGTKOptionMenu( m_nScreen ); 2382 NWEnsureGTKScrolledWindow( m_nScreen ); 2383 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2384 2385 // Find the overall bounding rect of the buttons's drawing area, 2386 // plus its actual draw rect excluding adornment 2387 pixmapRect = rControlRectangle; 2388 if ( nPart == PART_WINDOW ) 2389 { 2390 // Make the widget a _bit_ bigger 2391 pixmapRect.SetPos( Point( pixmapRect.Left() - 1, 2392 pixmapRect.Top() - 1 ) ); 2393 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, 2394 pixmapRect.GetHeight() + 2 ) ); 2395 } 2396 2397 widgetRect = pixmapRect; 2398 x = pixmapRect.Left(); 2399 y = pixmapRect.Top(); 2400 2401 // set up references to correct drawable and cliprect 2402 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 2403 NWSetWidgetState( gWidgetData[m_nScreen].gOptionMenuWidget, nState, stateType ); 2404 NWSetWidgetState( gWidgetData[m_nScreen].gScrolledWindowWidget, nState, stateType ); 2405 2406 if ( nPart != PART_WINDOW ) 2407 { 2408 gtk_widget_style_get( gWidgetData[m_nScreen].gOptionMenuWidget, 2409 "interior_focus", &bInteriorFocus, 2410 "focus_line_width", &nFocusLineWidth, 2411 "focus_padding", &nFocusPadding, 2412 (char *)NULL); 2413 } 2414 2415 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2416 { 2417 clipRect.x = it->Left(); 2418 clipRect.y = it->Top(); 2419 clipRect.width = it->GetWidth(); 2420 clipRect.height = it->GetHeight(); 2421 2422 if ( nPart != PART_WINDOW ) 2423 { 2424 // Listboxes must paint opaque since some themes have alpha-channel enabled bodies 2425 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 2426 &clipRect, m_pWindow, "base", x, y, 2427 pixmapRect.GetWidth(), pixmapRect.GetHeight() ); 2428 gtk_paint_box( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect, 2429 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenu", 2430 x+(widgetRect.Left() - pixmapRect.Left()), 2431 y+(widgetRect.Top() - pixmapRect.Top()), 2432 widgetRect.GetWidth(), widgetRect.GetHeight() ); 2433 aIndicatorRect = NWGetListBoxIndicatorRect( m_nScreen, nType, nPart, widgetRect, nState, 2434 aValue, rCaption ); 2435 gtk_paint_tab( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect, 2436 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenutab", 2437 x+(aIndicatorRect.Left() - pixmapRect.Left()), 2438 y+(aIndicatorRect.Top() - pixmapRect.Top()), 2439 aIndicatorRect.GetWidth(), aIndicatorRect.GetHeight() ); 2440 } 2441 else 2442 { 2443 shadowType = GTK_SHADOW_IN; 2444 2445 gtk_paint_shadow( gWidgetData[m_nScreen].gScrolledWindowWidget->style, gdkDrawable, GTK_STATE_NORMAL, shadowType, 2446 &clipRect, gWidgetData[m_nScreen].gScrolledWindowWidget, "scrolled_window", 2447 x+(widgetRect.Left() - pixmapRect.Left()), y+(widgetRect.Top() - pixmapRect.Top()), 2448 widgetRect.GetWidth(), widgetRect.GetHeight() ); 2449 } 2450 } 2451 2452 return( sal_True ); 2453 } 2454 2455 sal_Bool GtkSalGraphics::NWPaintGTKToolbar( 2456 GdkDrawable* gdkDrawable, 2457 ControlType, ControlPart nPart, 2458 const Rectangle& rControlRectangle, 2459 const clipList& rClipList, 2460 ControlState nState, const ImplControlValue& aValue, 2461 const OUString& ) 2462 { 2463 GtkStateType stateType; 2464 GtkShadowType shadowType; 2465 gint x, y, w, h; 2466 gint g_x=0, g_y=0, g_w=10, g_h=10; 2467 bool bPaintButton = true; 2468 GtkWidget* pButtonWidget = gWidgetData[m_nScreen].gToolbarButtonWidget; 2469 GdkRectangle clipRect; 2470 2471 NWEnsureGTKToolbar( m_nScreen ); 2472 if( nPart == PART_BUTTON ) // toolbar buttons cannot focus in gtk 2473 nState &= ~CTRL_STATE_FOCUSED; 2474 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2475 2476 x = rControlRectangle.Left(); 2477 y = rControlRectangle.Top(); 2478 w = rControlRectangle.GetWidth(); 2479 h = rControlRectangle.GetHeight(); 2480 2481 // handle toolbar 2482 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 2483 { 2484 NWSetWidgetState( gWidgetData[m_nScreen].gToolbarWidget, nState, stateType ); 2485 2486 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE ); 2487 if ( nState & CTRL_STATE_ENABLED ) 2488 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE ); 2489 2490 if( nPart == PART_DRAW_BACKGROUND_HORZ ) 2491 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_HORIZONTAL ); 2492 else 2493 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_VERTICAL ); 2494 } 2495 // handle grip 2496 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 2497 { 2498 NWSetWidgetState( gWidgetData[m_nScreen].gHandleBoxWidget, nState, stateType ); 2499 2500 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE ); 2501 if ( nState & CTRL_STATE_ENABLED ) 2502 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE ); 2503 2504 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(gWidgetData[m_nScreen].gHandleBoxWidget), shadowType ); 2505 2506 // evaluate grip rect 2507 if( aValue.getType() == CTRL_TOOLBAR ) 2508 { 2509 const ToolbarValue* pVal = static_cast<const ToolbarValue*>(&aValue); 2510 g_x = pVal->maGripRect.Left(); 2511 g_y = pVal->maGripRect.Top(); 2512 g_w = pVal->maGripRect.GetWidth(); 2513 g_h = pVal->maGripRect.GetHeight(); 2514 } 2515 } 2516 // handle button 2517 else if( nPart == PART_BUTTON ) 2518 { 2519 bPaintButton = 2520 (GTK_BUTTON(pButtonWidget)->relief != GTK_RELIEF_NONE) 2521 || (nState & CTRL_STATE_PRESSED) 2522 || (nState & CTRL_STATE_ROLLOVER); 2523 if( aValue.getTristateVal() == BUTTONVALUE_ON ) 2524 { 2525 pButtonWidget = gWidgetData[m_nScreen].gToolbarToggleWidget; 2526 shadowType = GTK_SHADOW_IN; 2527 stateType = GTK_STATE_ACTIVE; 2528 // special case stateType value for depressed toggle buttons 2529 // cf. gtk+/gtk/gtktogglebutton.c (gtk_toggle_button_update_state) 2530 if( (nState & (CTRL_STATE_ROLLOVER|CTRL_STATE_PRESSED)) ) 2531 { 2532 stateType = GTK_STATE_PRELIGHT; 2533 shadowType = GTK_SHADOW_OUT; 2534 } 2535 bPaintButton = true; 2536 } 2537 else 2538 stateType = GTK_STATE_PRELIGHT; // only for bPaintButton = true, in which case always rollver is meant 2539 2540 NWSetWidgetState( pButtonWidget, nState, stateType ); 2541 gtk_widget_ensure_style( pButtonWidget ); 2542 } 2543 2544 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2545 { 2546 clipRect.x = it->Left(); 2547 clipRect.y = it->Top(); 2548 clipRect.width = it->GetWidth(); 2549 clipRect.height = it->GetHeight(); 2550 2551 // draw toolbar 2552 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 2553 { 2554 gtk_paint_flat_box( gWidgetData[m_nScreen].gToolbarWidget->style, 2555 gdkDrawable, 2556 (GtkStateType)GTK_STATE_NORMAL, 2557 GTK_SHADOW_NONE, 2558 &clipRect, 2559 gWidgetData[m_nScreen].gToolbarWidget, 2560 "base", 2561 x, y, w, h ); 2562 gtk_paint_box( gWidgetData[m_nScreen].gToolbarWidget->style, 2563 gdkDrawable, 2564 stateType, 2565 shadowType, 2566 &clipRect, 2567 gWidgetData[m_nScreen].gToolbarWidget, 2568 "toolbar", 2569 x, y, w, h ); 2570 } 2571 // draw grip 2572 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 2573 { 2574 gtk_paint_handle( gWidgetData[m_nScreen].gHandleBoxWidget->style, 2575 gdkDrawable, 2576 GTK_STATE_NORMAL, 2577 GTK_SHADOW_OUT, 2578 &clipRect, 2579 gWidgetData[m_nScreen].gHandleBoxWidget, 2580 "handlebox", 2581 g_x, g_y, g_w, g_h, 2582 nPart == PART_THUMB_HORZ ? 2583 GTK_ORIENTATION_HORIZONTAL : 2584 GTK_ORIENTATION_VERTICAL 2585 ); 2586 } 2587 // draw button 2588 else if( nPart == PART_BUTTON ) 2589 { 2590 if( bPaintButton ) 2591 { 2592 gtk_paint_box( pButtonWidget->style, gdkDrawable, 2593 stateType, 2594 shadowType, 2595 &clipRect, 2596 pButtonWidget, "button", x, y, w, h ); 2597 } 2598 } 2599 } 2600 2601 return( sal_True ); 2602 } 2603 2604 //---- 2605 2606 sal_Bool GtkSalGraphics::NWPaintGTKMenubar( 2607 GdkDrawable* gdkDrawable, 2608 ControlType, ControlPart nPart, 2609 const Rectangle& rControlRectangle, 2610 const clipList& rClipList, 2611 ControlState nState, const ImplControlValue&, 2612 const OUString& ) 2613 { 2614 GtkStateType stateType; 2615 GtkShadowType shadowType; 2616 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT; 2617 gint x, y, w, h; 2618 GdkRectangle clipRect; 2619 2620 NWEnsureGTKMenubar( m_nScreen ); 2621 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2622 2623 x = rControlRectangle.Left(); 2624 y = rControlRectangle.Top(); 2625 w = rControlRectangle.GetWidth(); 2626 h = rControlRectangle.GetHeight(); 2627 2628 if( nPart == PART_MENU_ITEM ) 2629 { 2630 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2631 { 2632 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenubarWidget, 2633 "selected_shadow_type", &selected_shadow_type, 2634 (char *)NULL); 2635 } 2636 } 2637 2638 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2639 { 2640 clipRect.x = it->Left(); 2641 clipRect.y = it->Top(); 2642 clipRect.width = it->GetWidth(); 2643 clipRect.height = it->GetHeight(); 2644 2645 // handle Menubar 2646 if( nPart == PART_ENTIRE_CONTROL ) 2647 { 2648 NWSetWidgetState( gWidgetData[m_nScreen].gMenubarWidget, nState, stateType ); 2649 2650 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE ); 2651 if ( nState & CTRL_STATE_ENABLED ) 2652 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE ); 2653 2654 // #118704# for translucent menubar styles paint background first 2655 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenubarWidget->style, 2656 gdkDrawable, 2657 GTK_STATE_NORMAL, 2658 GTK_SHADOW_NONE, 2659 &clipRect, 2660 GTK_WIDGET(m_pWindow), 2661 "base", 2662 x, y, w, h ); 2663 gtk_paint_box( gWidgetData[m_nScreen].gMenubarWidget->style, 2664 gdkDrawable, 2665 stateType, 2666 shadowType, 2667 &clipRect, 2668 gWidgetData[m_nScreen].gMenubarWidget, 2669 "menubar", 2670 x, y, w, h ); 2671 } 2672 else if( nPart == PART_MENU_ITEM ) 2673 { 2674 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2675 { 2676 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenubarWidget->style, 2677 gdkDrawable, 2678 GTK_STATE_PRELIGHT, 2679 selected_shadow_type, 2680 &clipRect, 2681 gWidgetData[m_nScreen].gMenuItemMenubarWidget, 2682 "menuitem", 2683 x, y, w, h); 2684 } 2685 } 2686 } 2687 2688 return( sal_True ); 2689 } 2690 2691 sal_Bool GtkSalGraphics::NWPaintGTKPopupMenu( 2692 GdkDrawable* gdkDrawable, 2693 ControlType, ControlPart nPart, 2694 const Rectangle& rControlRectangle, 2695 const clipList& rClipList, 2696 ControlState nState, const ImplControlValue&, 2697 const OUString& ) 2698 { 2699 // #i50745# gtk does not draw disabled menu entries (and crux theme 2700 // even crashes), draw them using vcl functionality. 2701 if( nPart == PART_MENU_ITEM && ! (nState & CTRL_STATE_ENABLED) ) 2702 return sal_False; 2703 2704 GtkStateType stateType; 2705 GtkShadowType shadowType; 2706 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT; 2707 gint x, y, w, h; 2708 GdkRectangle clipRect; 2709 2710 NWEnsureGTKMenu( m_nScreen ); 2711 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2712 2713 x = rControlRectangle.Left(); 2714 y = rControlRectangle.Top(); 2715 w = rControlRectangle.GetWidth(); 2716 h = rControlRectangle.GetHeight(); 2717 2718 if( nPart == PART_MENU_ITEM && 2719 ( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) ) 2720 { 2721 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenuWidget, 2722 "selected_shadow_type", &selected_shadow_type, 2723 (char *)NULL); 2724 } 2725 2726 NWSetWidgetState( gWidgetData[m_nScreen].gMenuWidget, nState, stateType ); 2727 2728 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE ); 2729 if ( nState & CTRL_STATE_ENABLED ) 2730 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE ); 2731 2732 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2733 { 2734 clipRect.x = it->Left(); 2735 clipRect.y = it->Top(); 2736 clipRect.width = it->GetWidth(); 2737 clipRect.height = it->GetHeight(); 2738 2739 if( nPart == PART_ENTIRE_CONTROL ) 2740 { 2741 // #118704# for translucent menubar styles paint background first 2742 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenuWidget->style, 2743 gdkDrawable, 2744 GTK_STATE_NORMAL, 2745 GTK_SHADOW_NONE, 2746 &clipRect, 2747 GTK_WIDGET(m_pWindow), 2748 "base", 2749 x, y, w, h ); 2750 gtk_paint_box( gWidgetData[m_nScreen].gMenuWidget->style, 2751 gdkDrawable, 2752 GTK_STATE_NORMAL, 2753 GTK_SHADOW_OUT, 2754 &clipRect, 2755 gWidgetData[m_nScreen].gMenuWidget, 2756 "menu", 2757 x, y, w, h ); 2758 } 2759 else if( nPart == PART_MENU_ITEM ) 2760 { 2761 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2762 { 2763 if( nState & CTRL_STATE_ENABLED ) 2764 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenuWidget->style, 2765 gdkDrawable, 2766 GTK_STATE_PRELIGHT, 2767 selected_shadow_type, 2768 &clipRect, 2769 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2770 "menuitem", 2771 x, y, w, h); 2772 } 2773 } 2774 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ) 2775 { 2776 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ? 2777 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : 2778 gWidgetData[m_nScreen].gMenuItemRadioMenuWidget; 2779 2780 GtkStateType nStateType = GTK_STATE_NORMAL; 2781 GtkShadowType nShadowType; 2782 2783 if ( nState & CTRL_STATE_SELECTED ) 2784 nStateType = GTK_STATE_PRELIGHT; 2785 2786 NWSetWidgetState( pWidget, nState, nStateType ); 2787 2788 if ( nState & CTRL_STATE_PRESSED ) 2789 nShadowType = GTK_SHADOW_IN; 2790 else 2791 nShadowType = GTK_SHADOW_OUT; 2792 2793 if ( nPart == PART_MENU_ITEM_CHECK_MARK ) 2794 { 2795 gtk_paint_check( pWidget->style, 2796 gdkDrawable, 2797 nStateType, 2798 nShadowType, 2799 &clipRect, 2800 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2801 "check", 2802 x, y, w, h ); 2803 } 2804 else 2805 { 2806 gtk_paint_option( pWidget->style, 2807 gdkDrawable, 2808 nStateType, 2809 nShadowType, 2810 &clipRect, 2811 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2812 "option", 2813 x, y, w, h ); 2814 } 2815 } 2816 } 2817 2818 return( sal_True ); 2819 } 2820 2821 sal_Bool GtkSalGraphics::NWPaintGTKTooltip( 2822 GdkDrawable* gdkDrawable, 2823 ControlType, ControlPart, 2824 const Rectangle& rControlRectangle, 2825 const clipList& rClipList, 2826 ControlState, const ImplControlValue&, 2827 const OUString& ) 2828 { 2829 NWEnsureGTKTooltip( m_nScreen ); 2830 2831 gint x, y, w, h; 2832 GdkRectangle clipRect; 2833 2834 x = rControlRectangle.Left(); 2835 y = rControlRectangle.Top(); 2836 w = rControlRectangle.GetWidth(); 2837 h = rControlRectangle.GetHeight(); 2838 2839 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2840 { 2841 clipRect.x = it->Left(); 2842 clipRect.y = it->Top(); 2843 clipRect.width = it->GetWidth(); 2844 clipRect.height = it->GetHeight(); 2845 2846 gtk_paint_flat_box( gWidgetData[m_nScreen].gTooltipPopup->style, 2847 gdkDrawable, 2848 GTK_STATE_NORMAL, 2849 GTK_SHADOW_OUT, 2850 &clipRect, 2851 gWidgetData[m_nScreen].gTooltipPopup, 2852 "tooltip", 2853 x, y, w, h ); 2854 } 2855 2856 return( sal_True ); 2857 } 2858 2859 sal_Bool GtkSalGraphics::NWPaintGTKListNode( 2860 GdkDrawable*, 2861 ControlType, ControlPart, 2862 const Rectangle& rControlRectangle, 2863 const clipList&, 2864 ControlState nState, const ImplControlValue& rValue, 2865 const OUString& ) 2866 { 2867 NWEnsureGTKTreeView( m_nScreen ); 2868 2869 Rectangle aRect( rControlRectangle ); 2870 aRect.Left() -= 2; 2871 aRect.Right() += 2; 2872 aRect.Top() -= 2; 2873 aRect.Bottom() += 2; 2874 gint w, h; 2875 w = aRect.GetWidth(); 2876 h = aRect.GetHeight(); 2877 2878 GtkStateType stateType; 2879 GtkShadowType shadowType; 2880 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2881 2882 ButtonValue aButtonValue = rValue.getTristateVal(); 2883 GtkExpanderStyle eStyle = GTK_EXPANDER_EXPANDED; 2884 2885 switch( aButtonValue ) 2886 { 2887 case BUTTONVALUE_ON: eStyle = GTK_EXPANDER_EXPANDED;break; 2888 case BUTTONVALUE_OFF: eStyle = GTK_EXPANDER_COLLAPSED; break; 2889 default: 2890 break; 2891 } 2892 2893 GdkPixmap* pixmap = NWGetPixmapFromScreen( aRect ); 2894 if( ! pixmap ) 2895 return sal_False; 2896 2897 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 2898 gtk_paint_expander( gWidgetData[m_nScreen].gTreeView->style, 2899 pixDrawable, 2900 stateType, 2901 NULL, 2902 gWidgetData[m_nScreen].gTreeView, 2903 "treeview", 2904 w/2, h/2, 2905 eStyle ); 2906 2907 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, aRect ); 2908 g_object_unref( pixmap ); 2909 2910 return bRet; 2911 } 2912 2913 sal_Bool GtkSalGraphics::NWPaintGTKProgress( 2914 GdkDrawable*, 2915 ControlType, ControlPart, 2916 const Rectangle& rControlRectangle, 2917 const clipList&, 2918 ControlState, const ImplControlValue& rValue, 2919 const OUString& ) 2920 { 2921 NWEnsureGTKProgressBar( m_nScreen ); 2922 2923 gint w, h; 2924 w = rControlRectangle.GetWidth(); 2925 h = rControlRectangle.GetHeight(); 2926 2927 long nProgressWidth = rValue.getNumericVal(); 2928 2929 GdkPixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) ); 2930 if( ! pixmap ) 2931 return sal_False; 2932 2933 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 2934 2935 // paint background 2936 gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style, 2937 pixDrawable, 2938 GTK_STATE_NORMAL, 2939 GTK_SHADOW_NONE, 2940 NULL, 2941 gWidgetData[m_nScreen].gProgressBar, 2942 "trough", 2943 0, 0, w, h ); 2944 if( nProgressWidth > 0 ) 2945 { 2946 // paint progress 2947 if( Application::GetSettings().GetLayoutRTL() ) 2948 { 2949 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 2950 pixDrawable, 2951 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 2952 NULL, 2953 gWidgetData[m_nScreen].gProgressBar, 2954 "bar", 2955 w-nProgressWidth, 0, nProgressWidth, h 2956 ); 2957 } 2958 else 2959 { 2960 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 2961 pixDrawable, 2962 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 2963 NULL, 2964 gWidgetData[m_nScreen].gProgressBar, 2965 "bar", 2966 0, 0, nProgressWidth, h 2967 ); 2968 } 2969 } 2970 2971 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); 2972 g_object_unref( pixmap ); 2973 2974 return bRet; 2975 } 2976 2977 sal_Bool GtkSalGraphics::NWPaintGTKSlider( 2978 GdkDrawable*, 2979 ControlType, ControlPart nPart, 2980 const Rectangle& rControlRectangle, 2981 const clipList&, 2982 ControlState nState, const ImplControlValue& rValue, 2983 const OUString& ) 2984 { 2985 OSL_ASSERT( rValue.getType() == CTRL_SLIDER ); 2986 NWEnsureGTKSlider( m_nScreen ); 2987 2988 gint w, h; 2989 w = rControlRectangle.GetWidth(); 2990 h = rControlRectangle.GetHeight(); 2991 2992 const SliderValue* pVal = static_cast<const SliderValue*>(&rValue); 2993 2994 GdkPixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle ); 2995 if( ! pixmap ) 2996 return sal_False; 2997 2998 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 2999 GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) 3000 ? GTK_WIDGET(gWidgetData[m_nScreen].gHScale) 3001 : GTK_WIDGET(gWidgetData[m_nScreen].gVScale); 3002 const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; 3003 GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; 3004 GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE; 3005 gint slider_width = 10; 3006 gint slider_length = 10; 3007 gint trough_border = 0; 3008 gtk_widget_style_get( pWidget, 3009 "slider-width", &slider_width, 3010 "slider-length", &slider_length, 3011 "trough-border", &trough_border, 3012 NULL); 3013 3014 eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; 3015 if( nPart == PART_TRACK_HORZ_AREA ) 3016 { 3017 gtk_paint_box( pWidget->style, 3018 pixDrawable, 3019 eState, 3020 GTK_SHADOW_IN, 3021 NULL, 3022 pWidget, 3023 "trough", 3024 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); 3025 gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); 3026 gtk_paint_slider( pWidget->style, 3027 pixDrawable, 3028 eState, 3029 GTK_SHADOW_OUT, 3030 NULL, 3031 pWidget, 3032 pDetail, 3033 x, (h-slider_width)/2, 3034 slider_length, slider_width, 3035 eOri ); 3036 } 3037 else 3038 { 3039 gtk_paint_box( pWidget->style, 3040 pixDrawable, 3041 eState, 3042 GTK_SHADOW_IN, 3043 NULL, 3044 pWidget, 3045 "trough", 3046 (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); 3047 gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); 3048 gtk_paint_slider( pWidget->style, 3049 pixDrawable, 3050 eState, 3051 GTK_SHADOW_OUT, 3052 NULL, 3053 pWidget, 3054 pDetail, 3055 (w-slider_width)/2, y, 3056 slider_width, slider_length, 3057 eOri ); 3058 } 3059 #if 0 3060 // paint background 3061 gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style, 3062 pixDrawable, 3063 GTK_STATE_NORMAL, 3064 GTK_SHADOW_NONE, 3065 NULL, 3066 gWidgetData[m_nScreen].gProgressBar, 3067 "trough", 3068 0, 0, w, h ); 3069 if( nProgressWidth > 0 ) 3070 { 3071 // paint progress 3072 if( Application::GetSettings().GetLayoutRTL() ) 3073 { 3074 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 3075 pixDrawable, 3076 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 3077 NULL, 3078 gWidgetData[m_nScreen].gProgressBar, 3079 "bar", 3080 w-nProgressWidth, 0, nProgressWidth, h 3081 ); 3082 } 3083 else 3084 { 3085 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 3086 pixDrawable, 3087 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 3088 NULL, 3089 gWidgetData[m_nScreen].gProgressBar, 3090 "bar", 3091 0, 0, nProgressWidth, h 3092 ); 3093 } 3094 } 3095 #endif 3096 3097 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); 3098 g_object_unref( pixmap ); 3099 3100 return bRet; 3101 } 3102 3103 //---- 3104 3105 static Rectangle NWGetListBoxButtonRect( int nScreen, 3106 ControlType, 3107 ControlPart nPart, 3108 Rectangle aAreaRect, 3109 ControlState, 3110 const ImplControlValue&, 3111 const OUString& ) 3112 { 3113 Rectangle aPartRect; 3114 GtkRequisition *pIndicatorSize = NULL; 3115 GtkBorder *pIndicatorSpacing = NULL; 3116 gint width = 13; // GTK+ default 3117 gint right = 5; // GTK+ default 3118 gint nButtonAreaWidth = 0; 3119 gint xthickness = 0; 3120 3121 NWEnsureGTKOptionMenu( nScreen ); 3122 3123 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget, 3124 "indicator_size", &pIndicatorSize, 3125 "indicator_spacing",&pIndicatorSpacing, (char *)NULL); 3126 3127 if ( pIndicatorSize ) 3128 width = pIndicatorSize->width; 3129 3130 if ( pIndicatorSpacing ) 3131 right = pIndicatorSpacing->right; 3132 3133 Size aPartSize( 0, aAreaRect.GetHeight() ); 3134 Point aPartPos ( 0, aAreaRect.Top() ); 3135 3136 xthickness = gWidgetData[nScreen].gOptionMenuWidget->style->xthickness; 3137 nButtonAreaWidth = width + right + (xthickness * 2); 3138 switch( nPart ) 3139 { 3140 case PART_BUTTON_DOWN: 3141 aPartSize.Width() = nButtonAreaWidth; 3142 aPartPos.X() = aAreaRect.Left() + aAreaRect.GetWidth() - aPartSize.Width(); 3143 break; 3144 3145 case PART_SUB_EDIT: 3146 aPartSize.Width() = aAreaRect.GetWidth() - nButtonAreaWidth - xthickness; 3147 aPartPos.X() = aAreaRect.Left() + xthickness; 3148 break; 3149 3150 default: 3151 aPartSize.Width() = aAreaRect.GetWidth(); 3152 aPartPos.X() = aAreaRect.Left(); 3153 break; 3154 } 3155 aPartRect = Rectangle( aPartPos, aPartSize ); 3156 3157 if ( pIndicatorSize ) 3158 gtk_requisition_free( pIndicatorSize ); 3159 if ( pIndicatorSpacing ) 3160 gtk_border_free( pIndicatorSpacing ); 3161 3162 return( aPartRect ); 3163 } 3164 3165 //---- 3166 3167 static Rectangle NWGetListBoxIndicatorRect( int nScreen, 3168 ControlType, 3169 ControlPart, 3170 Rectangle aAreaRect, 3171 ControlState, 3172 const ImplControlValue&, 3173 const OUString& ) 3174 { 3175 Rectangle aIndicatorRect; 3176 GtkRequisition *pIndicatorSize = NULL; 3177 GtkBorder *pIndicatorSpacing = NULL; 3178 gint width = 13; // GTK+ default 3179 gint height = 13; // GTK+ default 3180 gint right = 5; // GTK+ default 3181 3182 NWEnsureGTKOptionMenu( nScreen ); 3183 3184 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget, 3185 "indicator_size", &pIndicatorSize, 3186 "indicator_spacing",&pIndicatorSpacing, (char *)NULL); 3187 3188 if ( pIndicatorSize ) 3189 { 3190 width = pIndicatorSize->width; 3191 height = pIndicatorSize->height; 3192 } 3193 3194 if ( pIndicatorSpacing ) 3195 right = pIndicatorSpacing->right; 3196 3197 aIndicatorRect.SetSize( Size( width, height ) ); 3198 aIndicatorRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - width - right - gWidgetData[nScreen].gOptionMenuWidget->style->xthickness, 3199 aAreaRect.Top() + ((aAreaRect.GetHeight() - height) / 2) ) ); 3200 3201 // If height is odd, move the indicator down 1 pixel 3202 if ( aIndicatorRect.GetHeight() % 2 ) 3203 aIndicatorRect.Move( 0, 1 ); 3204 3205 if ( pIndicatorSize ) 3206 gtk_requisition_free( pIndicatorSize ); 3207 if ( pIndicatorSpacing ) 3208 gtk_border_free( pIndicatorSpacing ); 3209 3210 return( aIndicatorRect ); 3211 } 3212 3213 static Rectangle NWGetToolbarRect( int nScreen, 3214 ControlType, 3215 ControlPart nPart, 3216 Rectangle aAreaRect, 3217 ControlState, 3218 const ImplControlValue&, 3219 const OUString& ) 3220 { 3221 Rectangle aRet; 3222 3223 if( nPart == PART_DRAW_BACKGROUND_HORZ || 3224 nPart == PART_DRAW_BACKGROUND_VERT ) 3225 aRet = aAreaRect; 3226 else if( nPart == PART_THUMB_HORZ ) 3227 aRet = Rectangle( Point( 0, 0 ), Size( aAreaRect.GetWidth(), 10 ) ); 3228 else if( nPart == PART_THUMB_VERT ) 3229 aRet = Rectangle( Point( 0, 0 ), Size( 10, aAreaRect.GetHeight() ) ); 3230 else if( nPart == PART_BUTTON ) 3231 { 3232 aRet = aAreaRect; 3233 3234 NWEnsureGTKToolbar( nScreen ); 3235 3236 gint nMinWidth = 3237 2*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness 3238 + 1 // CHILD_SPACING constant, found in gtk_button.c 3239 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness; // Murphy factor 3240 gint nMinHeight = 3241 2*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness 3242 + 1 // CHILD_SPACING constant, found in gtk_button.c 3243 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness; // Murphy factor 3244 3245 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarButtonWidget ); 3246 if( aAreaRect.GetWidth() < nMinWidth ) 3247 aRet.Right() = aRet.Left() + nMinWidth; 3248 if( aAreaRect.GetHeight() < nMinHeight ) 3249 aRet.Bottom() = aRet.Top() + nMinHeight; 3250 } 3251 3252 return aRet; 3253 } 3254 3255 /************************************************************************ 3256 * helper for GtkSalFrame 3257 ************************************************************************/ 3258 static inline Color getColor( const GdkColor& rCol ) 3259 { 3260 return Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 ); 3261 } 3262 3263 #if OSL_DEBUG_LEVEL > 1 3264 3265 void printColor( const char* name, const GdkColor& rCol ) 3266 { 3267 std::fprintf( stderr, " %s = 0x%2x 0x%2x 0x%2x\n", 3268 name, 3269 rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 ); 3270 } 3271 3272 void printStyleColors( GtkStyle* pStyle ) 3273 { 3274 static const char* pStates[] = { "NORMAL", "ACTIVE", "PRELIGHT", "SELECTED", "INSENSITIVE" }; 3275 3276 for( int i = 0; i < 5; i++ ) 3277 { 3278 std::fprintf( stderr, "state %s colors:\n", pStates[i] ); 3279 printColor( "bg ", pStyle->bg[i] ); 3280 printColor( "fg ", pStyle->fg[i] ); 3281 printColor( "light ", pStyle->light[i] ); 3282 printColor( "dark ", pStyle->dark[i] ); 3283 printColor( "mid ", pStyle->mid[i] ); 3284 printColor( "text ", pStyle->text[i] ); 3285 printColor( "base ", pStyle->base[i] ); 3286 printColor( "text_aa", pStyle->text_aa[i] ); 3287 } 3288 } 3289 #endif 3290 3291 void GtkSalGraphics::updateSettings( AllSettings& rSettings ) 3292 { 3293 // get the widgets in place 3294 NWEnsureGTKMenu( m_nScreen ); 3295 NWEnsureGTKMenubar( m_nScreen ); 3296 NWEnsureGTKScrollbars( m_nScreen ); 3297 NWEnsureGTKEditBox( m_nScreen ); 3298 NWEnsureGTKTooltip( m_nScreen ); 3299 3300 gtk_widget_ensure_style( m_pWindow ); 3301 GtkStyle* pStyle = gtk_widget_get_style( m_pWindow ); 3302 3303 StyleSettings aStyleSet = rSettings.GetStyleSettings(); 3304 3305 #if OSL_DEBUG_LEVEL > 2 3306 printStyleColors( pStyle ); 3307 #endif 3308 3309 // text colors 3310 Color aTextColor = getColor( pStyle->text[GTK_STATE_NORMAL] ); 3311 aStyleSet.SetDialogTextColor( aTextColor ); 3312 aStyleSet.SetButtonTextColor( aTextColor ); 3313 aStyleSet.SetRadioCheckTextColor( aTextColor ); 3314 aStyleSet.SetGroupTextColor( aTextColor ); 3315 aStyleSet.SetLabelTextColor( aTextColor ); 3316 aStyleSet.SetInfoTextColor( aTextColor ); 3317 aStyleSet.SetWindowTextColor( aTextColor ); 3318 aStyleSet.SetFieldTextColor( aTextColor ); 3319 3320 // Tooltip colors 3321 GtkStyle* pTooltipStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gTooltipPopup ); 3322 aTextColor = getColor( pTooltipStyle->fg[ GTK_STATE_NORMAL ] ); 3323 aStyleSet.SetHelpTextColor( aTextColor ); 3324 3325 // mouse over text colors 3326 aTextColor = getColor( pStyle->fg[ GTK_STATE_PRELIGHT ] ); 3327 aStyleSet.SetButtonRolloverTextColor( aTextColor ); 3328 aStyleSet.SetFieldRolloverTextColor( aTextColor ); 3329 3330 // background colors 3331 Color aBackColor = getColor( pStyle->bg[GTK_STATE_NORMAL] ); 3332 Color aBackFieldColor = getColor( pStyle->base[ GTK_STATE_NORMAL ] ); 3333 aStyleSet.Set3DColors( aBackColor ); 3334 aStyleSet.SetFaceColor( aBackColor ); 3335 aStyleSet.SetDialogColor( aBackColor ); 3336 aStyleSet.SetWorkspaceColor( aBackColor ); 3337 aStyleSet.SetFieldColor( aBackFieldColor ); 3338 aStyleSet.SetWindowColor( aBackFieldColor ); 3339 // aStyleSet.SetHelpColor( aBackColor ); 3340 // ancient wisdom tells us a mystic algorithm how to set checked color 3341 if( aBackColor == COL_LIGHTGRAY ) 3342 aStyleSet.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) ); 3343 else 3344 { 3345 Color aColor2 = aStyleSet.GetLightColor(); 3346 Color aCheck( (sal_uInt8)(((sal_uInt16)aBackColor.GetRed()+(sal_uInt16)aColor2.GetRed())/2), 3347 (sal_uInt8)(((sal_uInt16)aBackColor.GetGreen()+(sal_uInt16)aColor2.GetGreen())/2), 3348 (sal_uInt8)(((sal_uInt16)aBackColor.GetBlue()+(sal_uInt16)aColor2.GetBlue())/2) 3349 ); 3350 aStyleSet.SetCheckedColor( aCheck ); 3351 } 3352 3353 // highlighting colors 3354 Color aHighlightColor = getColor( pStyle->base[GTK_STATE_SELECTED] ); 3355 Color aHighlightTextColor = getColor( pStyle->text[GTK_STATE_SELECTED] ); 3356 aStyleSet.SetHighlightColor( aHighlightColor ); 3357 aStyleSet.SetHighlightTextColor( aHighlightTextColor ); 3358 3359 if( ! gtk_check_version( 2, 10, 0 ) ) // link colors came in with 2.10, avoid an assertion 3360 { 3361 // hyperlink colors 3362 GdkColor *link_color = NULL; 3363 gtk_widget_style_get (m_pWindow, "link-color", &link_color, NULL); 3364 if (link_color) 3365 { 3366 aStyleSet.SetLinkColor(getColor(*link_color)); 3367 gdk_color_free (link_color); 3368 link_color = NULL; 3369 } 3370 gtk_widget_style_get (m_pWindow, "visited-link-color", &link_color, NULL); 3371 if (link_color) 3372 { 3373 aStyleSet.SetVisitedLinkColor(getColor(*link_color)); 3374 gdk_color_free (link_color); 3375 } 3376 } 3377 3378 // Tab colors 3379 aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color. 3380 Color aSelectedBackColor = getColor( pStyle->bg[GTK_STATE_ACTIVE] ); 3381 aStyleSet.SetInactiveTabColor( aSelectedBackColor ); 3382 3383 // menu disabled entries handling 3384 aStyleSet.SetSkipDisabledInMenus( sal_True ); 3385 // menu colors 3386 GtkStyle* pMenuStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gMenuWidget ); 3387 GtkStyle* pMenuItemStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenuItemMenuWidget ); 3388 GtkStyle* pMenubarStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenubarWidget ); 3389 GtkStyle* pMenuTextStyle = gtk_rc_get_style( gtk_bin_get_child( GTK_BIN(gWidgetData[m_nScreen].gMenuItemMenuWidget) ) ); 3390 3391 aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] ); 3392 aStyleSet.SetMenuBarColor( aBackColor ); 3393 aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] ); 3394 aTextColor = getColor( pMenuTextStyle->fg[GTK_STATE_NORMAL] ); 3395 aStyleSet.SetMenuColor( aBackColor ); 3396 aStyleSet.SetMenuTextColor( aTextColor ); 3397 3398 aTextColor = getColor( pMenubarStyle->fg[GTK_STATE_NORMAL] ); 3399 aStyleSet.SetMenuBarTextColor( aTextColor ); 3400 3401 #if OSL_DEBUG_LEVEL > 1 3402 std::fprintf( stderr, "==\n" ); 3403 std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor().GetColor(), aStyleSet.GetMenuColor().GetLuminance() ); 3404 std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor().GetColor(), aStyleSet.GetMenuTextColor().GetLuminance() ); 3405 std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor().GetColor(), aStyleSet.GetMenuBarColor().GetLuminance() ); 3406 std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor().GetColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() ); 3407 std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor().GetColor(), aStyleSet.GetLightColor().GetLuminance() ); 3408 std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor().GetColor(), aStyleSet.GetShadowColor().GetLuminance() ); 3409 #endif 3410 3411 // Awful hack for menu separators in the Sonar and similar themes. 3412 // If the menu color is not too dark, and the menu text color is lighter, 3413 // make the "light" color lighter than the menu color and the "shadow" 3414 // color darker than it. 3415 if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 && 3416 aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() ) 3417 { 3418 Color temp = aStyleSet.GetMenuColor(); 3419 temp.IncreaseLuminance( 8 ); 3420 aStyleSet.SetLightColor( temp ); 3421 temp = aStyleSet.GetMenuColor(); 3422 temp.DecreaseLuminance( 16 ); 3423 aStyleSet.SetShadowColor( temp ); 3424 } 3425 3426 aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] ); 3427 aHighlightTextColor = getColor( pMenuTextStyle->fg[ GTK_STATE_PRELIGHT ] ); 3428 if( aHighlightColor == aHighlightTextColor ) 3429 aHighlightTextColor = (aHighlightColor.GetLuminance() < 128) ? Color( COL_WHITE ) : Color( COL_BLACK ); 3430 aStyleSet.SetMenuHighlightColor( aHighlightColor ); 3431 aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor ); 3432 3433 // UI font 3434 OString aFamily = pango_font_description_get_family( pStyle->font_desc ); 3435 int nPangoHeight = pango_font_description_get_size( pStyle->font_desc ); 3436 PangoStyle eStyle = pango_font_description_get_style( pStyle->font_desc ); 3437 PangoWeight eWeight = pango_font_description_get_weight( pStyle->font_desc ); 3438 PangoStretch eStretch = pango_font_description_get_stretch( pStyle->font_desc ); 3439 3440 psp::FastPrintFontInfo aInfo; 3441 // set family name 3442 aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 ); 3443 // set italic 3444 switch( eStyle ) 3445 { 3446 case PANGO_STYLE_NORMAL: aInfo.m_eItalic = psp::italic::Upright;break; 3447 case PANGO_STYLE_ITALIC: aInfo.m_eItalic = psp::italic::Italic;break; 3448 case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = psp::italic::Oblique;break; 3449 } 3450 // set weight 3451 if( eWeight <= PANGO_WEIGHT_ULTRALIGHT ) 3452 aInfo.m_eWeight = psp::weight::UltraLight; 3453 else if( eWeight <= PANGO_WEIGHT_LIGHT ) 3454 aInfo.m_eWeight = psp::weight::Light; 3455 else if( eWeight <= PANGO_WEIGHT_NORMAL ) 3456 aInfo.m_eWeight = psp::weight::Normal; 3457 else if( eWeight <= PANGO_WEIGHT_BOLD ) 3458 aInfo.m_eWeight = psp::weight::Bold; 3459 else 3460 aInfo.m_eWeight = psp::weight::UltraBold; 3461 // set width 3462 switch( eStretch ) 3463 { 3464 case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = psp::width::UltraCondensed;break; 3465 case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = psp::width::ExtraCondensed;break; 3466 case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = psp::width::Condensed;break; 3467 case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = psp::width::SemiCondensed;break; 3468 case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = psp::width::Normal;break; 3469 case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = psp::width::SemiExpanded;break; 3470 case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = psp::width::Expanded;break; 3471 case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = psp::width::ExtraExpanded;break; 3472 case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = psp::width::UltraExpanded;break; 3473 } 3474 3475 #if OSL_DEBUG_LEVEL > 1 3476 std::fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() ); 3477 #endif 3478 3479 // match font to e.g. resolve "Sans" 3480 psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILocale() ); 3481 3482 #if OSL_DEBUG_LEVEL > 1 3483 std::fprintf( stderr, "font match %s, name AFTER: \"%s\"\n", 3484 aInfo.m_nID != 0 ? "succeeded" : "failed", 3485 OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() ); 3486 #endif 3487 3488 sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B(); 3489 int nPointHeight = 0; 3490 static gboolean(*pAbso)(const PangoFontDescription*) = 3491 (gboolean(*)(const PangoFontDescription*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "pango_font_description_get_size_is_absolute" ); 3492 3493 if( pAbso && pAbso( pStyle->font_desc ) ) 3494 nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE); 3495 else 3496 nPointHeight = nPangoHeight/PANGO_SCALE; 3497 3498 Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) ); 3499 if( aInfo.m_eWeight != psp::weight::Unknown ) 3500 aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) ); 3501 if( aInfo.m_eWidth != psp::width::Unknown ) 3502 aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) ); 3503 if( aInfo.m_eItalic != psp::italic::Unknown ) 3504 aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) ); 3505 if( aInfo.m_ePitch != psp::pitch::Unknown ) 3506 aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) ); 3507 3508 aStyleSet.SetAppFont( aFont ); 3509 aStyleSet.SetHelpFont( aFont ); 3510 aStyleSet.SetTitleFont( aFont ); 3511 aStyleSet.SetFloatTitleFont( aFont ); 3512 aStyleSet.SetMenuFont( aFont ); 3513 aStyleSet.SetToolFont( aFont ); 3514 aStyleSet.SetLabelFont( aFont ); 3515 aStyleSet.SetInfoFont( aFont ); 3516 aStyleSet.SetRadioCheckFont( aFont ); 3517 aStyleSet.SetPushButtonFont( aFont ); 3518 aStyleSet.SetFieldFont( aFont ); 3519 aStyleSet.SetIconFont( aFont ); 3520 aStyleSet.SetGroupFont( aFont ); 3521 3522 // get cursor blink time 3523 GtkSettings *pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gEditBoxWidget ); 3524 gboolean blink = false; 3525 3526 g_object_get( pSettings, "gtk-cursor-blink", &blink, (char *)NULL ); 3527 if( blink ) 3528 { 3529 gint blink_time = STYLE_CURSOR_NOBLINKTIME; 3530 g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, (char *)NULL ); 3531 // set the blink_time if there is a setting and it is reasonable 3532 // else leave the default value 3533 if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) ) 3534 aStyleSet.SetCursorBlinkTime( blink_time/2 ); 3535 } 3536 else 3537 aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME ); 3538 3539 gboolean showmenuicons = true; 3540 pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gImageMenuItem ); 3541 g_object_get( pSettings, "gtk-menu-images", &showmenuicons, (char *)NULL ); 3542 aStyleSet.SetUseImagesInMenus( showmenuicons ); 3543 3544 // set scrollbar settings 3545 gint slider_width = 14; 3546 gint trough_border = 1; 3547 gint min_slider_length = 21; 3548 3549 // Grab some button style attributes 3550 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, 3551 "slider-width", &slider_width, 3552 "trough-border", &trough_border, 3553 "min-slider-length", &min_slider_length, 3554 (char *)NULL ); 3555 gint magic = trough_border ? 1 : 0; 3556 aStyleSet.SetScrollBarSize( slider_width + 2*trough_border ); 3557 aStyleSet.SetMinThumbSize( min_slider_length - magic ); 3558 3559 // preferred icon style 3560 gchar* pIconThemeName = NULL; 3561 g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &pIconThemeName, (char *)NULL ); 3562 aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii( pIconThemeName ) ); 3563 g_free( pIconThemeName ); 3564 3565 // FIXME: need some way of fetching toolbar icon size. 3566 // aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL ); 3567 3568 const cairo_font_options_t* pNewOptions = NULL; 3569 if( GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), m_nScreen ) ) 3570 { 3571 //#if !GTK_CHECK_VERSION(2,8,1) 3572 #if !GTK_CHECK_VERSION(2,9,0) 3573 static cairo_font_options_t* (*gdk_screen_get_font_options)(GdkScreen*) = 3574 (cairo_font_options_t*(*)(GdkScreen*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_screen_get_font_options" ); 3575 if( gdk_screen_get_font_options != NULL ) 3576 #endif 3577 pNewOptions = gdk_screen_get_font_options( pScreen ); 3578 } 3579 aStyleSet.SetCairoFontOptions( pNewOptions ); 3580 3581 // finally update the collected settings 3582 rSettings.SetStyleSettings( aStyleSet ); 3583 3584 #if OSL_DEBUG_LEVEL > 1 3585 { 3586 GtkSettings* pGtkSettings = gtk_settings_get_default(); 3587 GValue aValue; 3588 memset( &aValue, 0, sizeof(GValue) ); 3589 g_value_init( &aValue, G_TYPE_STRING ); 3590 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue ); 3591 const gchar* pThemeName = g_value_get_string( &aValue ); 3592 std::fprintf( stderr, "Theme name is \"%s\"\n", pThemeName ); 3593 g_value_unset( &aValue ); 3594 } 3595 #endif 3596 GtkSettings* pGtkSettings = gtk_settings_get_default(); 3597 GValue aValue; 3598 memset( &aValue, 0, sizeof(GValue) ); 3599 g_value_init( &aValue, G_TYPE_STRING ); 3600 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue ); 3601 const gchar* pThemeName = g_value_get_string( &aValue ); 3602 3603 // default behaviour 3604 bNeedPixmapPaint = bGlobalNeedPixmapPaint; 3605 bToolbarGripWorkaround = false; 3606 bNeedButtonStyleAsEditBackgroundWorkaround = false; 3607 3608 // setup some workarounds for "blueprint" theme 3609 if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 ) 3610 { 3611 bNeedButtonStyleAsEditBackgroundWorkaround = true; 3612 if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun ) 3613 { 3614 // #i52570#, #i61532# workaround a weird paint issue; 3615 // on a Sunray Xserver sometimes painting buttons and edits 3616 // won't work when using the blueprint theme 3617 // not reproducible with simpler programs or other themes 3618 if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 ) 3619 { 3620 bNeedPixmapPaint = true; 3621 bToolbarGripWorkaround = true; 3622 } 3623 } 3624 } 3625 // clean up 3626 g_value_unset( &aValue ); 3627 } 3628 3629 3630 /************************************************************************ 3631 * Create a GdkPixmap filled with the contents of an area of an Xlib window 3632 ************************************************************************/ 3633 3634 GdkPixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect ) 3635 { 3636 // Create a new pixmap to hold the composite of the window background and the control 3637 GdkPixmap * pPixmap = gdk_pixmap_new( GDK_DRAWABLE(GetGdkWindow()), srcRect.GetWidth(), srcRect.GetHeight(), -1 ); 3638 GdkGC * pPixmapGC = gdk_gc_new( pPixmap ); 3639 3640 if( !pPixmap || !pPixmapGC ) 3641 { 3642 if ( pPixmap ) 3643 g_object_unref( pPixmap ); 3644 if ( pPixmapGC ) 3645 g_object_unref( pPixmapGC ); 3646 std::fprintf( stderr, "salnativewidgets-gtk.cxx: could not get valid pixmap from screen\n" ); 3647 return( NULL ); 3648 } 3649 3650 // Copy the background of the screen into a composite pixmap 3651 CopyScreenArea( GetXDisplay(), 3652 GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(), 3653 gdk_x11_drawable_get_xid(pPixmap), 3654 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ), 3655 gdk_drawable_get_depth( GDK_DRAWABLE( pPixmap ) ), 3656 gdk_x11_gc_get_xgc(pPixmapGC), 3657 srcRect.Left(), srcRect.Top(), srcRect.GetWidth(), srcRect.GetHeight(), 0, 0 ); 3658 3659 g_object_unref( pPixmapGC ); 3660 return( pPixmap ); 3661 } 3662 3663 3664 3665 3666 /************************************************************************ 3667 * Copy an alpha pixmap to screen using a gc with clipping 3668 ************************************************************************/ 3669 3670 sal_Bool GtkSalGraphics::NWRenderPixmapToScreen( GdkPixmap* pPixmap, Rectangle dstRect ) 3671 { 3672 // The GC can't be null, otherwise we'd have no clip region 3673 GC aFontGC = GetFontGC(); 3674 if( aFontGC == NULL ) 3675 { 3676 std::fprintf(stderr, "salnativewidgets.cxx: no valid GC\n" ); 3677 return( sal_False ); 3678 } 3679 3680 if ( !pPixmap ) 3681 return( sal_False ); 3682 3683 // Copy the background of the screen into a composite pixmap 3684 CopyScreenArea( GetXDisplay(), 3685 GDK_DRAWABLE_XID(pPixmap), 3686 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ), 3687 gdk_drawable_get_depth( GDK_DRAWABLE(pPixmap) ), 3688 GetDrawable(), m_nScreen, GetVisual().GetDepth(), 3689 aFontGC, 3690 0, 0, dstRect.GetWidth(), dstRect.GetHeight(), dstRect.Left(), dstRect.Top() ); 3691 3692 return( sal_True ); 3693 } 3694 3695 3696 /************************************************************************ 3697 * State conversion 3698 ************************************************************************/ 3699 static void NWConvertVCLStateToGTKState( ControlState nVCLState, 3700 GtkStateType* nGTKState, GtkShadowType* nGTKShadow ) 3701 { 3702 *nGTKShadow = GTK_SHADOW_OUT; 3703 *nGTKState = GTK_STATE_INSENSITIVE; 3704 3705 if ( nVCLState & CTRL_STATE_ENABLED ) 3706 { 3707 if ( nVCLState & CTRL_STATE_PRESSED ) 3708 { 3709 *nGTKState = GTK_STATE_ACTIVE; 3710 *nGTKShadow = GTK_SHADOW_IN; 3711 } 3712 else if ( nVCLState & CTRL_STATE_ROLLOVER ) 3713 { 3714 *nGTKState = GTK_STATE_PRELIGHT; 3715 *nGTKShadow = GTK_SHADOW_OUT; 3716 } 3717 else 3718 { 3719 *nGTKState = GTK_STATE_NORMAL; 3720 *nGTKShadow = GTK_SHADOW_OUT; 3721 } 3722 } 3723 } 3724 3725 /************************************************************************ 3726 * Set widget flags 3727 ************************************************************************/ 3728 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState ) 3729 { 3730 // Set to default state, then build up from there 3731 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_DEFAULT ); 3732 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_FOCUS ); 3733 GTK_WIDGET_UNSET_FLAGS( widget, GTK_SENSITIVE ); 3734 GTK_WIDGET_SET_FLAGS( widget, gWidgetDefaultFlags[(long)widget] ); 3735 3736 if ( nState & CTRL_STATE_DEFAULT ) 3737 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_DEFAULT ); 3738 if ( !GTK_IS_TOGGLE_BUTTON(widget) && (nState & CTRL_STATE_FOCUSED) ) 3739 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_FOCUS ); 3740 if ( nState & CTRL_STATE_ENABLED ) 3741 GTK_WIDGET_SET_FLAGS( widget, GTK_SENSITIVE ); 3742 gtk_widget_set_state( widget, nGtkState ); 3743 } 3744 3745 /************************************************************************ 3746 * Widget ensure functions - make sure cached objects are valid 3747 ************************************************************************/ 3748 3749 //------------------------------------- 3750 3751 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen ) 3752 { 3753 NWFWidgetData& rData = gWidgetData[nScreen]; 3754 if ( !rData.gCacheWindow || !rData.gDumbContainer ) 3755 { 3756 if ( !rData.gCacheWindow ) 3757 { 3758 rData.gCacheWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL ); 3759 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen ); 3760 if( pScreen ) 3761 gtk_window_set_screen( GTK_WINDOW(rData.gCacheWindow), pScreen ); 3762 } 3763 if ( !rData.gDumbContainer ) 3764 rData.gDumbContainer = gtk_fixed_new(); 3765 gtk_container_add( GTK_CONTAINER(rData.gCacheWindow), rData.gDumbContainer ); 3766 gtk_widget_realize( rData.gDumbContainer ); 3767 gtk_widget_realize( rData.gCacheWindow ); 3768 } 3769 3770 gtk_container_add( GTK_CONTAINER(rData.gDumbContainer), widget ); 3771 gtk_widget_realize( widget ); 3772 gtk_widget_ensure_style( widget ); 3773 3774 // Store widget's default flags 3775 gWidgetDefaultFlags[ (long)widget ] = GTK_WIDGET_FLAGS( widget ); 3776 } 3777 3778 //------------------------------------- 3779 3780 static void NWEnsureGTKButton( int nScreen ) 3781 { 3782 if ( !gWidgetData[nScreen].gBtnWidget ) 3783 { 3784 gWidgetData[nScreen].gBtnWidget = gtk_button_new_with_label( "" ); 3785 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gBtnWidget, nScreen ); 3786 } 3787 } 3788 3789 //------------------------------------- 3790 3791 static void NWEnsureGTKRadio( int nScreen ) 3792 { 3793 if ( !gWidgetData[nScreen].gRadioWidget || !gWidgetData[nScreen].gRadioWidgetSibling ) 3794 { 3795 gWidgetData[nScreen].gRadioWidget = gtk_radio_button_new( NULL ); 3796 gWidgetData[nScreen].gRadioWidgetSibling = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(gWidgetData[nScreen].gRadioWidget) ); 3797 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidget, nScreen ); 3798 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidgetSibling, nScreen ); 3799 } 3800 } 3801 3802 //------------------------------------- 3803 3804 static void NWEnsureGTKCheck( int nScreen ) 3805 { 3806 if ( !gWidgetData[nScreen].gCheckWidget ) 3807 { 3808 gWidgetData[nScreen].gCheckWidget = gtk_check_button_new(); 3809 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gCheckWidget, nScreen ); 3810 } 3811 } 3812 3813 //------------------------------------- 3814 3815 static void NWEnsureGTKScrollbars( int nScreen ) 3816 { 3817 if ( !gWidgetData[nScreen].gScrollHorizWidget ) 3818 { 3819 gWidgetData[nScreen].gScrollHorizWidget = gtk_hscrollbar_new( NULL ); 3820 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollHorizWidget, nScreen ); 3821 } 3822 3823 if ( !gWidgetData[nScreen].gScrollVertWidget ) 3824 { 3825 gWidgetData[nScreen].gScrollVertWidget = gtk_vscrollbar_new( NULL ); 3826 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollVertWidget, nScreen ); 3827 } 3828 } 3829 3830 //------------------------------------- 3831 3832 static void NWEnsureGTKArrow( int nScreen ) 3833 { 3834 if ( !gWidgetData[nScreen].gArrowWidget || !gWidgetData[nScreen].gDropdownWidget ) 3835 { 3836 gWidgetData[nScreen].gDropdownWidget = gtk_toggle_button_new(); 3837 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gDropdownWidget, nScreen ); 3838 gWidgetData[nScreen].gArrowWidget = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT ); 3839 gtk_container_add( GTK_CONTAINER(gWidgetData[nScreen].gDropdownWidget), gWidgetData[nScreen].gArrowWidget ); 3840 gtk_widget_set_rc_style( gWidgetData[nScreen].gArrowWidget ); 3841 gtk_widget_realize( gWidgetData[nScreen].gArrowWidget ); 3842 } 3843 } 3844 3845 //------------------------------------- 3846 3847 static void NWEnsureGTKEditBox( int nScreen ) 3848 { 3849 if ( !gWidgetData[nScreen].gEditBoxWidget ) 3850 { 3851 gWidgetData[nScreen].gEditBoxWidget = gtk_entry_new(); 3852 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gEditBoxWidget, nScreen ); 3853 } 3854 } 3855 3856 //------------------------------------- 3857 3858 static void NWEnsureGTKSpinButton( int nScreen ) 3859 { 3860 if ( !gWidgetData[nScreen].gSpinButtonWidget ) 3861 { 3862 GtkAdjustment *adj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 1, 1, 1, 0) ); 3863 gWidgetData[nScreen].gSpinButtonWidget = gtk_spin_button_new( adj, 1, 2 ); 3864 3865 //Setting non-editable means it doesn't blink, so there's no timeouts 3866 //running around to nobble us 3867 gtk_editable_set_editable(GTK_EDITABLE(gWidgetData[nScreen].gSpinButtonWidget), false); 3868 3869 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSpinButtonWidget, nScreen ); 3870 } 3871 } 3872 3873 //------------------------------------- 3874 3875 static void NWEnsureGTKNotebook( int nScreen ) 3876 { 3877 if ( !gWidgetData[nScreen].gNotebookWidget ) 3878 { 3879 gWidgetData[nScreen].gNotebookWidget = gtk_notebook_new(); 3880 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gNotebookWidget, nScreen ); 3881 } 3882 } 3883 3884 //------------------------------------- 3885 3886 static void NWEnsureGTKOptionMenu( int nScreen ) 3887 { 3888 if ( !gWidgetData[nScreen].gOptionMenuWidget ) 3889 { 3890 gWidgetData[nScreen].gOptionMenuWidget = gtk_option_menu_new(); 3891 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gOptionMenuWidget, nScreen ); 3892 } 3893 } 3894 3895 //------------------------------------- 3896 3897 static void NWEnsureGTKCombo( int nScreen ) 3898 { 3899 if ( !gWidgetData[nScreen].gComboWidget ) 3900 { 3901 gWidgetData[nScreen].gComboWidget = gtk_combo_new(); 3902 3903 // #i59129# Setting non-editable means it doesn't blink, so 3904 // there are no timeouts running around to nobble us 3905 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry), false); 3906 3907 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gComboWidget, nScreen ); 3908 // Must realize the ComboBox's children, since GTK 3909 // does not do this for us in GtkCombo::gtk_widget_realize() 3910 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->button ); 3911 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry ); 3912 } 3913 } 3914 3915 //------------------------------------- 3916 3917 static void NWEnsureGTKScrolledWindow( int nScreen ) 3918 { 3919 if ( !gWidgetData[nScreen].gScrolledWindowWidget ) 3920 { 3921 GtkAdjustment *hadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 3922 GtkAdjustment *vadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 3923 3924 gWidgetData[nScreen].gScrolledWindowWidget = gtk_scrolled_window_new( hadj, vadj ); 3925 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrolledWindowWidget, nScreen ); 3926 } 3927 } 3928 3929 //------------------------------------- 3930 3931 static void NWEnsureGTKToolbar( int nScreen ) 3932 { 3933 if( !gWidgetData[nScreen].gToolbarWidget ) 3934 { 3935 gWidgetData[nScreen].gToolbarWidget = gtk_toolbar_new(); 3936 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarWidget, nScreen ); 3937 gWidgetData[nScreen].gToolbarButtonWidget = gtk_button_new(); 3938 gWidgetData[nScreen].gToolbarToggleWidget = gtk_toggle_button_new(); 3939 3940 GtkReliefStyle aRelief = GTK_RELIEF_NORMAL; 3941 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarWidget ); 3942 gtk_widget_style_get( gWidgetData[nScreen].gToolbarWidget, 3943 "button_relief", &aRelief, 3944 (char *)NULL); 3945 3946 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarButtonWidget), aRelief ); 3947 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_FOCUS ); 3948 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_DEFAULT ); 3949 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarButtonWidget, nScreen ); 3950 3951 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarToggleWidget), aRelief ); 3952 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_FOCUS ); 3953 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_DEFAULT ); 3954 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarToggleWidget, nScreen ); 3955 } 3956 if( ! gWidgetData[nScreen].gHandleBoxWidget ) 3957 { 3958 gWidgetData[nScreen].gHandleBoxWidget = gtk_handle_box_new(); 3959 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHandleBoxWidget, nScreen ); 3960 } 3961 } 3962 3963 //------------------------------------- 3964 3965 static void NWEnsureGTKMenubar( int nScreen ) 3966 { 3967 if( !gWidgetData[nScreen].gMenubarWidget ) 3968 { 3969 gWidgetData[nScreen].gMenubarWidget = gtk_menu_bar_new(); 3970 gWidgetData[nScreen].gMenuItemMenubarWidget = gtk_menu_item_new_with_label( "b" ); 3971 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenubarWidget ), gWidgetData[nScreen].gMenuItemMenubarWidget ); 3972 gtk_widget_show( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3973 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gMenubarWidget, nScreen ); 3974 gtk_widget_show( gWidgetData[nScreen].gMenubarWidget ); 3975 3976 // do what NWAddWidgetToCacheWindow does except adding to def container 3977 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3978 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3979 3980 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenubarWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3981 } 3982 } 3983 3984 static void NWEnsureGTKMenu( int nScreen ) 3985 { 3986 if( !gWidgetData[nScreen].gMenuWidget ) 3987 { 3988 gWidgetData[nScreen].gMenuWidget = gtk_menu_new(); 3989 gWidgetData[nScreen].gMenuItemMenuWidget = gtk_menu_item_new_with_label( "b" ); 3990 gWidgetData[nScreen].gMenuItemCheckMenuWidget = gtk_check_menu_item_new_with_label( "b" ); 3991 gWidgetData[nScreen].gMenuItemRadioMenuWidget = gtk_radio_menu_item_new_with_label( NULL, "b" ); 3992 gWidgetData[nScreen].gImageMenuItem = gtk_image_menu_item_new(); 3993 3994 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemMenuWidget ); 3995 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 3996 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 3997 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gImageMenuItem ); 3998 3999 // do what NWAddWidgetToCacheWindow does except adding to def container 4000 gtk_widget_realize( gWidgetData[nScreen].gMenuWidget ); 4001 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuWidget ); 4002 4003 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenuWidget ); 4004 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenuWidget ); 4005 4006 gtk_widget_realize( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4007 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4008 4009 gtk_widget_realize( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4010 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4011 4012 gtk_widget_realize( gWidgetData[nScreen].gImageMenuItem ); 4013 gtk_widget_ensure_style( gWidgetData[nScreen].gImageMenuItem ); 4014 4015 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuWidget ); 4016 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenuWidget ); 4017 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemCheckMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4018 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemRadioMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4019 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gImageMenuItem ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gImageMenuItem ); 4020 } 4021 } 4022 4023 static void NWEnsureGTKTooltip( int nScreen ) 4024 { 4025 if( !gWidgetData[nScreen].gTooltipPopup ) 4026 { 4027 gWidgetData[nScreen].gTooltipPopup = gtk_window_new (GTK_WINDOW_POPUP); 4028 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen ); 4029 if( pScreen ) 4030 gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gTooltipPopup), pScreen ); 4031 gtk_widget_set_name( gWidgetData[nScreen].gTooltipPopup, "gtk-tooltips"); 4032 gtk_widget_realize( gWidgetData[nScreen].gTooltipPopup ); 4033 gtk_widget_ensure_style( gWidgetData[nScreen].gTooltipPopup ); 4034 } 4035 } 4036 4037 static void NWEnsureGTKProgressBar( int nScreen ) 4038 { 4039 if( !gWidgetData[nScreen].gProgressBar ) 4040 { 4041 gWidgetData[nScreen].gProgressBar = gtk_progress_bar_new (); 4042 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gProgressBar, nScreen ); 4043 } 4044 } 4045 4046 static void NWEnsureGTKTreeView( int nScreen ) 4047 { 4048 if( !gWidgetData[nScreen].gTreeView ) 4049 { 4050 gWidgetData[nScreen].gTreeView = gtk_tree_view_new (); 4051 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gTreeView, nScreen ); 4052 } 4053 } 4054 4055 static void NWEnsureGTKSlider( int nScreen ) 4056 { 4057 if( !gWidgetData[nScreen].gHScale ) 4058 { 4059 gWidgetData[nScreen].gHScale = gtk_hscale_new_with_range(0, 10, 1); 4060 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHScale, nScreen ); 4061 } 4062 if( !gWidgetData[nScreen].gVScale ) 4063 { 4064 gWidgetData[nScreen].gVScale = gtk_vscale_new_with_range(0, 10, 1); 4065 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gVScale, nScreen ); 4066 } 4067 } 4068