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