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 hierachies 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 if (rNativeBoundingRegion.GetWidth()>0 && rNativeBoundingRegion.GetHeight()>0) 986 returnVal = sal_True; 987 else 988 returnVal = sal_False; 989 } 990 if( (nType == CTRL_MENUBAR) && (nPart == PART_ENTIRE_CONTROL) ) 991 { 992 NWEnsureGTKMenubar( m_nScreen ); 993 GtkRequisition aReq; 994 gtk_widget_size_request( gWidgetData[m_nScreen].gMenubarWidget, &aReq ); 995 Rectangle aMenuBarRect = rControlRegion; 996 aMenuBarRect = Rectangle( aMenuBarRect.TopLeft(), 997 Size( aMenuBarRect.GetWidth(), aReq.height+1 ) ); 998 rNativeBoundingRegion = aMenuBarRect; 999 rNativeContentRegion = rNativeBoundingRegion; 1000 returnVal = sal_True; 1001 } 1002 if( (nType == CTRL_MENU_POPUP) ) 1003 { 1004 if( (nPart == PART_MENU_ITEM_CHECK_MARK) || 1005 (nPart == PART_MENU_ITEM_RADIO_MARK) ) 1006 { 1007 NWEnsureGTKMenu( m_nScreen ); 1008 1009 gint indicator_size = 0; 1010 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ? 1011 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : gWidgetData[m_nScreen].gMenuItemRadioMenuWidget; 1012 gtk_widget_style_get( pWidget, 1013 "indicator_size", &indicator_size, 1014 (char *)NULL ); 1015 rNativeBoundingRegion = rControlRegion; 1016 Rectangle aIndicatorRect( Point( 0, 1017 (rControlRegion.GetHeight()-indicator_size)/2), 1018 Size( indicator_size, indicator_size ) ); 1019 rNativeContentRegion = aIndicatorRect; 1020 returnVal = sal_True; 1021 } 1022 } 1023 if( (nType == CTRL_RADIOBUTTON || nType == CTRL_CHECKBOX) ) 1024 { 1025 NWEnsureGTKRadio( m_nScreen ); 1026 NWEnsureGTKCheck( m_nScreen ); 1027 GtkWidget* widget = (nType == CTRL_RADIOBUTTON) ? gWidgetData[m_nScreen].gRadioWidget : gWidgetData[m_nScreen].gCheckWidget; 1028 gint indicator_size, indicator_spacing; 1029 gtk_widget_style_get( widget, 1030 "indicator_size", &indicator_size, 1031 "indicator_spacing", &indicator_spacing, 1032 (char *)NULL); 1033 indicator_size += 2*indicator_spacing; // guess overpaint of theme 1034 rNativeBoundingRegion = rControlRegion; 1035 Rectangle aIndicatorRect( Point( 0, 1036 (rControlRegion.GetHeight()-indicator_size)/2), 1037 Size( indicator_size, indicator_size ) ); 1038 rNativeContentRegion = aIndicatorRect; 1039 returnVal = sal_True; 1040 } 1041 if( (nType == CTRL_EDITBOX || nType == CTRL_SPINBOX) && nPart == PART_ENTIRE_CONTROL ) 1042 { 1043 NWEnsureGTKEditBox( m_nScreen ); 1044 GtkWidget* widget = gWidgetData[m_nScreen].gEditBoxWidget; 1045 GtkRequisition aReq; 1046 gtk_widget_size_request( widget, &aReq ); 1047 Rectangle aEditRect = rControlRegion; 1048 long nHeight = (aEditRect.GetHeight() > aReq.height+1) ? aEditRect.GetHeight() : aReq.height+1; 1049 aEditRect = Rectangle( aEditRect.TopLeft(), 1050 Size( aEditRect.GetWidth(), nHeight ) ); 1051 rNativeBoundingRegion = aEditRect; 1052 rNativeContentRegion = rNativeBoundingRegion; 1053 returnVal = sal_True; 1054 } 1055 if( (nType == CTRL_SLIDER) && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) ) 1056 { 1057 NWEnsureGTKSlider( m_nScreen ); 1058 GtkWidget* widget = (nPart == PART_THUMB_HORZ) ? gWidgetData[m_nScreen].gHScale : gWidgetData[m_nScreen].gVScale; 1059 gint slider_length = 10; 1060 gint slider_width = 10; 1061 gtk_widget_style_get( widget, 1062 "slider-width", &slider_width, 1063 "slider-length", &slider_length, 1064 (char *)NULL); 1065 Rectangle aRect( rControlRegion ); 1066 if( nPart == PART_THUMB_HORZ ) 1067 { 1068 aRect.Right() = aRect.Left() + slider_length - 1; 1069 aRect.Bottom() = aRect.Top() + slider_width - 1; 1070 } 1071 else 1072 { 1073 aRect.Bottom() = aRect.Top() + slider_length - 1; 1074 aRect.Right() = aRect.Left() + slider_width - 1; 1075 } 1076 rNativeBoundingRegion = rNativeContentRegion = aRect; 1077 returnVal = sal_True; 1078 } 1079 1080 return( returnVal ); 1081 } 1082 1083 1084 /************************************************************************ 1085 * Individual control drawing functions 1086 ************************************************************************/ 1087 sal_Bool GtkSalGraphics::NWPaintGTKButton( 1088 GdkDrawable* gdkDrawable, 1089 ControlType, ControlPart, 1090 const Rectangle& rControlRectangle, 1091 const clipList& rClipList, 1092 ControlState nState, const ImplControlValue&, 1093 const OUString& ) 1094 { 1095 GtkStateType stateType; 1096 GtkShadowType shadowType; 1097 gboolean interiorFocus; 1098 gint focusWidth; 1099 gint focusPad; 1100 sal_Bool bDrawFocus = sal_True; 1101 gint x, y, w, h; 1102 GtkBorder aDefBorder; 1103 GtkBorder* pBorder; 1104 GdkRectangle clipRect; 1105 1106 NWEnsureGTKButton( m_nScreen ); 1107 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1108 1109 x = rControlRectangle.Left(); 1110 y = rControlRectangle.Top(); 1111 w = rControlRectangle.GetWidth(); 1112 h = rControlRectangle.GetHeight(); 1113 1114 // Grab some button style attributes 1115 gtk_widget_style_get( gWidgetData[m_nScreen].gBtnWidget, "focus-line-width", &focusWidth, 1116 "focus-padding", &focusPad, 1117 "interior_focus", &interiorFocus, 1118 "default_border", &pBorder, 1119 (char *)NULL ); 1120 1121 // Make sure the border values exist, otherwise use some defaults 1122 if ( pBorder ) 1123 { 1124 NW_gtk_border_set_from_border( aDefBorder, pBorder ); 1125 gtk_border_free( pBorder ); 1126 } 1127 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder ); 1128 1129 // If the button is too small, don't ever draw focus or grab more space 1130 if ( (w < 16) || (h < 16) ) 1131 bDrawFocus = sal_False; 1132 1133 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 1134 1135 gint xi = x, yi = y, wi = w, hi = h; 1136 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus ) 1137 { 1138 xi += aDefBorder.left; 1139 yi += aDefBorder.top; 1140 wi -= aDefBorder.left + aDefBorder.right; 1141 hi -= aDefBorder.top + aDefBorder.bottom; 1142 } 1143 1144 if ( !interiorFocus && bDrawFocus ) 1145 { 1146 xi += focusWidth + focusPad; 1147 yi += focusWidth + focusPad; 1148 wi -= 2 * (focusWidth + focusPad); 1149 hi -= 2 * (focusWidth + focusPad); 1150 } 1151 1152 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it) 1153 { 1154 clipRect.x = it->Left(); 1155 clipRect.y = it->Top(); 1156 clipRect.width = it->GetWidth(); 1157 clipRect.height = it->GetHeight(); 1158 1159 // Buttons must paint opaque since some themes have alpha-channel enabled buttons 1160 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 1161 &clipRect, m_pWindow, "base", x, y, w, h ); 1162 1163 if ( (nState & CTRL_STATE_DEFAULT) && (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief == GTK_RELIEF_NORMAL) ) 1164 { 1165 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, 1166 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "buttondefault", x, y, w, h ); 1167 } 1168 1169 if ( (GTK_BUTTON(gWidgetData[m_nScreen].gBtnWidget)->relief != GTK_RELIEF_NONE) 1170 || (nState & CTRL_STATE_PRESSED) 1171 || (nState & CTRL_STATE_ROLLOVER) ) 1172 { 1173 gtk_paint_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, shadowType, 1174 &clipRect, gWidgetData[m_nScreen].gBtnWidget, "button", xi, yi, wi, hi ); 1175 } 1176 } 1177 #if 0 // VCL draws focus rects 1178 // Draw focus rect 1179 if ( (nState & CTRL_STATE_FOCUSED) && (nState & CTRL_STATE_ENABLED) && bDrawFocus ) 1180 { 1181 if (interiorFocus) 1182 { 1183 x += gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad; 1184 y += gWidgetData[m_nScreen].gBtnWidget->style->ythickness + focusPad; 1185 w -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad); 1186 h -= 2 * (gWidgetData[m_nScreen].gBtnWidget->style->xthickness + focusPad); 1187 } 1188 else 1189 { 1190 x -= focusWidth + focusPad; 1191 y -= focusWidth + focusPad; 1192 w += 2 * (focusWidth + focusPad); 1193 h += 2 * (focusWidth + focusPad); 1194 } 1195 if ( !interiorFocus ) 1196 gtk_paint_focus( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, stateType, &clipRect, 1197 gWidgetData[m_nScreen].gBtnWidget, "button", x, y, w, h ); 1198 } 1199 #endif 1200 1201 return( sal_True ); 1202 } 1203 1204 static Rectangle NWGetButtonArea( int nScreen, 1205 ControlType, ControlPart, Rectangle aAreaRect, ControlState nState, 1206 const ImplControlValue&, const OUString& ) 1207 { 1208 gboolean interiorFocus; 1209 gint focusWidth; 1210 gint focusPad; 1211 GtkBorder aDefBorder; 1212 GtkBorder * pBorder; 1213 sal_Bool bDrawFocus = sal_True; 1214 Rectangle aRect; 1215 gint x, y, w, h; 1216 1217 NWEnsureGTKButton( nScreen ); 1218 gtk_widget_style_get( gWidgetData[nScreen].gBtnWidget, 1219 "focus-line-width", &focusWidth, 1220 "focus-padding", &focusPad, 1221 "interior_focus", &interiorFocus, 1222 "default_border", &pBorder, 1223 (char *)NULL ); 1224 1225 // Make sure the border values exist, otherwise use some defaults 1226 if ( pBorder ) 1227 { 1228 NW_gtk_border_set_from_border( aDefBorder, pBorder ); 1229 gtk_border_free( pBorder ); 1230 } 1231 else NW_gtk_border_set_from_border( aDefBorder, &aDefDefBorder ); 1232 1233 x = aAreaRect.Left(); 1234 y = aAreaRect.Top(); 1235 w = aAreaRect.GetWidth(); 1236 h = aAreaRect.GetHeight(); 1237 1238 // If the button is too small, don't ever draw focus or grab more space 1239 if ( (w < 16) || (h < 16) ) 1240 bDrawFocus = sal_False; 1241 1242 if ( (nState & CTRL_STATE_DEFAULT) && bDrawFocus ) 1243 { 1244 x -= aDefBorder.left; 1245 y -= aDefBorder.top; 1246 w += aDefBorder.left + aDefBorder.right; 1247 h += aDefBorder.top + aDefBorder.bottom; 1248 } 1249 1250 aRect = Rectangle( Point( x, y ), Size( w, h ) ); 1251 1252 return( aRect ); 1253 } 1254 1255 //------------------------------------- 1256 1257 sal_Bool GtkSalGraphics::NWPaintGTKRadio( GdkDrawable* gdkDrawable, 1258 ControlType, ControlPart, 1259 const Rectangle& rControlRectangle, 1260 const clipList& rClipList, 1261 ControlState nState, 1262 const ImplControlValue& aValue, 1263 const OUString& ) 1264 { 1265 GtkStateType stateType; 1266 GtkShadowType shadowType; 1267 sal_Bool isChecked = (aValue.getTristateVal()==BUTTONVALUE_ON); 1268 gint x, y; 1269 GdkRectangle clipRect; 1270 1271 NWEnsureGTKButton( m_nScreen ); 1272 NWEnsureGTKRadio( m_nScreen ); 1273 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1274 1275 gint indicator_size; 1276 gtk_widget_style_get( gWidgetData[m_nScreen].gRadioWidget, "indicator_size", &indicator_size, (char *)NULL); 1277 1278 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2; 1279 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2; 1280 1281 // Set the shadow based on if checked or not so we get a freakin checkmark. 1282 shadowType = isChecked ? GTK_SHADOW_IN : GTK_SHADOW_OUT; 1283 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidget, nState, stateType ); 1284 NWSetWidgetState( gWidgetData[m_nScreen].gRadioWidgetSibling, nState, stateType ); 1285 1286 // GTK enforces radio groups, so that if we don't have 2 buttons in the group, 1287 // the single button will always be active. So we have to have 2 buttons. 1288 1289 // #i59666# set the members directly where we should use 1290 // gtk_toggle_button_set_active. reason: there are animated themes 1291 // which are in active state only after a while leading to painting 1292 // intermediate states between active/inactive. Let's hope that 1293 // GtkToggleButtone stays binary compatible. 1294 if (!isChecked) 1295 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidgetSibling)->active = sal_True; 1296 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gRadioWidget)->active = isChecked; 1297 1298 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1299 { 1300 clipRect.x = it->Left(); 1301 clipRect.y = it->Top(); 1302 clipRect.width = it->GetWidth(); 1303 clipRect.height = it->GetHeight(); 1304 1305 gtk_paint_option( gWidgetData[m_nScreen].gRadioWidget->style, gdkDrawable, stateType, shadowType, 1306 &clipRect, gWidgetData[m_nScreen].gRadioWidget, "radiobutton", 1307 x, y, indicator_size, indicator_size ); 1308 } 1309 1310 return( sal_True ); 1311 } 1312 1313 //------------------------------------- 1314 1315 sal_Bool GtkSalGraphics::NWPaintGTKCheck( GdkDrawable* gdkDrawable, 1316 ControlType, ControlPart, 1317 const Rectangle& rControlRectangle, 1318 const clipList& rClipList, 1319 ControlState nState, 1320 const ImplControlValue& aValue, 1321 const OUString& ) 1322 { 1323 GtkStateType stateType; 1324 GtkShadowType shadowType; 1325 bool isChecked = (aValue.getTristateVal() == BUTTONVALUE_ON); 1326 bool isInconsistent = (aValue.getTristateVal() == BUTTONVALUE_MIXED); 1327 GdkRectangle clipRect; 1328 gint x,y; 1329 1330 NWEnsureGTKButton( m_nScreen ); 1331 NWEnsureGTKCheck( m_nScreen ); 1332 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1333 1334 gint indicator_size; 1335 gtk_widget_style_get( gWidgetData[m_nScreen].gCheckWidget, "indicator_size", &indicator_size, (char *)NULL); 1336 1337 x = rControlRectangle.Left() + (rControlRectangle.GetWidth()-indicator_size)/2; 1338 y = rControlRectangle.Top() + (rControlRectangle.GetHeight()-indicator_size)/2; 1339 1340 // Set the shadow based on if checked or not so we get a checkmark. 1341 shadowType = isChecked ? GTK_SHADOW_IN : isInconsistent ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_OUT; 1342 NWSetWidgetState( gWidgetData[m_nScreen].gCheckWidget, nState, stateType ); 1343 GTK_TOGGLE_BUTTON(gWidgetData[m_nScreen].gCheckWidget)->active = isChecked; 1344 1345 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1346 { 1347 clipRect.x = it->Left(); 1348 clipRect.y = it->Top(); 1349 clipRect.width = it->GetWidth(); 1350 clipRect.height = it->GetHeight(); 1351 1352 gtk_paint_check( gWidgetData[m_nScreen].gCheckWidget->style, gdkDrawable, stateType, shadowType, 1353 &clipRect, gWidgetData[m_nScreen].gCheckWidget, "checkbutton", 1354 x, y, indicator_size, indicator_size ); 1355 } 1356 1357 return( sal_True ); 1358 } 1359 1360 //------------------------------------- 1361 static void NWCalcArrowRect( const Rectangle& rButton, Rectangle& rArrow ) 1362 { 1363 // Size the arrow appropriately 1364 Size aSize( rButton.GetWidth()/2, rButton.GetHeight()/2 ); 1365 rArrow.SetSize( aSize ); 1366 1367 rArrow.SetPos( Point( 1368 rButton.Left() + ( rButton.GetWidth() - rArrow.GetWidth() ) / 2, 1369 rButton.Top() + ( rButton.GetHeight() - rArrow.GetHeight() ) / 2 1370 ) ); 1371 } 1372 1373 sal_Bool GtkSalGraphics::NWPaintGTKScrollbar( ControlType, ControlPart nPart, 1374 const Rectangle& rControlRectangle, 1375 const clipList&, 1376 ControlState nState, 1377 const ImplControlValue& aValue, 1378 const OUString& ) 1379 { 1380 OSL_ASSERT( aValue.getType() == CTRL_SCROLLBAR ); 1381 const ScrollbarValue* pScrollbarVal = (aValue.getType() == CTRL_SCROLLBAR) ? static_cast<const ScrollbarValue*>(&aValue) : NULL; 1382 GdkPixmap* pixmap = NULL; 1383 Rectangle pixmapRect, scrollbarRect; 1384 GtkStateType stateType; 1385 GtkShadowType shadowType; 1386 GtkScrollbar * scrollbarWidget; 1387 GtkStyle * style; 1388 GtkAdjustment* scrollbarValues = NULL; 1389 GtkOrientation scrollbarOrientation; 1390 Rectangle thumbRect = pScrollbarVal->maThumbRect; 1391 Rectangle button11BoundRect = pScrollbarVal->maButton1Rect; // backward 1392 Rectangle button22BoundRect = pScrollbarVal->maButton2Rect; // forward 1393 Rectangle button12BoundRect = pScrollbarVal->maButton1Rect; // secondary forward 1394 Rectangle button21BoundRect = pScrollbarVal->maButton2Rect; // secondary backward 1395 GtkArrowType button1Type; // backward 1396 GtkArrowType button2Type; // forward 1397 gchar * scrollbarTagH = (gchar *) "hscrollbar"; 1398 gchar * scrollbarTagV = (gchar *) "vscrollbar"; 1399 gchar * scrollbarTag = NULL; 1400 Rectangle arrowRect; 1401 gint slider_width = 0; 1402 gint stepper_size = 0; 1403 gint stepper_spacing = 0; 1404 gint trough_border = 0; 1405 gint min_slider_length = 0; 1406 gint vShim = 0; 1407 gint hShim = 0; 1408 gint x,y,w,h; 1409 1410 // make controlvalue rectangles relative to area 1411 thumbRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1412 button11BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1413 button22BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1414 button12BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1415 button21BoundRect.Move( -rControlRectangle.Left(), -rControlRectangle.Top() ); 1416 1417 NWEnsureGTKButton( m_nScreen ); 1418 NWEnsureGTKScrollbars( m_nScreen ); 1419 NWEnsureGTKArrow( m_nScreen ); 1420 1421 // Find the overall bounding rect of the control 1422 pixmapRect = rControlRectangle; 1423 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 1, 1424 pixmapRect.GetHeight() + 1 ) ); 1425 scrollbarRect = pixmapRect; 1426 1427 if ( (scrollbarRect.GetWidth() <= 1) || (scrollbarRect.GetHeight() <= 1) ) 1428 return( sal_True ); 1429 1430 // Grab some button style attributes 1431 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, 1432 "slider_width", &slider_width, 1433 "stepper_size", &stepper_size, 1434 "trough_border", &trough_border, 1435 "stepper_spacing", &stepper_spacing, 1436 "min_slider_length", &min_slider_length, (char *)NULL ); 1437 gboolean has_forward; 1438 gboolean has_forward2; 1439 gboolean has_backward; 1440 gboolean has_backward2; 1441 1442 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, "has-forward-stepper", &has_forward, 1443 "has-secondary-forward-stepper", &has_forward2, 1444 "has-backward-stepper", &has_backward, 1445 "has-secondary-backward-stepper", &has_backward2, (char *)NULL ); 1446 gint magic = trough_border ? 1 : 0; 1447 gint nFirst = 0; 1448 1449 if ( has_backward ) nFirst += 1; 1450 if ( has_forward2 ) nFirst += 1; 1451 1452 if ( nPart == PART_DRAW_BACKGROUND_HORZ ) 1453 { 1454 unsigned int sliderHeight = slider_width + (trough_border * 2); 1455 vShim = (pixmapRect.GetHeight() - sliderHeight) / 2; 1456 1457 scrollbarRect.Move( 0, vShim ); 1458 scrollbarRect.SetSize( Size( scrollbarRect.GetWidth(), sliderHeight ) ); 1459 1460 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollHorizWidget ); 1461 scrollbarOrientation = GTK_ORIENTATION_HORIZONTAL; 1462 scrollbarTag = scrollbarTagH; 1463 button1Type = GTK_ARROW_LEFT; 1464 button2Type = GTK_ARROW_RIGHT; 1465 1466 if ( has_backward ) 1467 { 1468 button12BoundRect.Move( stepper_size - trough_border, 1469 (scrollbarRect.GetHeight() - slider_width) / 2 ); 1470 } 1471 1472 button11BoundRect.Move( trough_border, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1473 button11BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1474 button12BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1475 1476 if ( has_backward2 ) 1477 { 1478 button22BoundRect.Move( stepper_size+(trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1479 button21BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1480 } 1481 else 1482 { 1483 button22BoundRect.Move( (trough_border+1)/2, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1484 } 1485 1486 button21BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1487 button22BoundRect.SetSize( Size( stepper_size, slider_width ) ); 1488 1489 thumbRect.Bottom() = thumbRect.Top() + slider_width - 1; 1490 // Make sure the thumb is at least the default width (so we don't get tiny thumbs), 1491 // but if the VCL gives us a size smaller than the theme's default thumb size, 1492 // honor the VCL size 1493 #if 0 1494 if ( (thumbRect.GetWidth() < min_slider_length) 1495 && ((scrollbarRect.GetWidth()-button1BoundRect.GetWidth()-button2BoundRect.GetWidth()) > min_slider_length) ) 1496 thumbRect.SetSize( Size( min_slider_length, thumbRect.GetHeight() ) ); 1497 #endif 1498 1499 thumbRect.Right() += magic; 1500 // Center vertically in the track 1501 thumbRect.Move( 0, (scrollbarRect.GetHeight() - slider_width) / 2 ); 1502 } 1503 else 1504 { 1505 unsigned int sliderWidth = slider_width + (trough_border * 2); 1506 hShim = (pixmapRect.GetWidth() - sliderWidth) / 2; 1507 1508 scrollbarRect.Move( hShim, 0 ); 1509 scrollbarRect.SetSize( Size( sliderWidth, scrollbarRect.GetHeight() ) ); 1510 1511 scrollbarWidget = GTK_SCROLLBAR( gWidgetData[m_nScreen].gScrollVertWidget ); 1512 scrollbarOrientation = GTK_ORIENTATION_VERTICAL; 1513 scrollbarTag = scrollbarTagV; 1514 button1Type = GTK_ARROW_UP; 1515 button2Type = GTK_ARROW_DOWN; 1516 1517 if ( has_backward ) 1518 { 1519 button12BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 1520 stepper_size + trough_border ); 1521 } 1522 button11BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, trough_border ); 1523 button11BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1524 button12BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1525 1526 if ( has_backward2 ) 1527 { 1528 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, stepper_size+(trough_border+1)/2 ); 1529 button21BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 ); 1530 } 1531 else 1532 { 1533 button22BoundRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, (trough_border+1)/2 ); 1534 } 1535 1536 button21BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1537 button22BoundRect.SetSize( Size( slider_width, stepper_size ) ); 1538 1539 thumbRect.Right() = thumbRect.Left() + slider_width - 1; 1540 #if 0 1541 // Make sure the thumb is at least the default width (so we don't get tiny thumbs), 1542 // but if the VCL gives us a size smaller than the theme's default thumb size, 1543 // honor the VCL size 1544 if ( (thumbRect.GetHeight() < min_slider_length) 1545 && ((scrollbarRect.GetHeight()-button1BoundRect.GetHeight()-button2BoundRect.GetHeight()) > min_slider_length) ) 1546 thumbRect.SetSize( Size( thumbRect.GetWidth(), min_slider_length ) ); 1547 #endif 1548 1549 thumbRect.Bottom() += magic; 1550 // Center horizontally in the track 1551 thumbRect.Move( (scrollbarRect.GetWidth() - slider_width) / 2, 0 ); 1552 } 1553 1554 sal_Bool has_slider = ( thumbRect.GetWidth() > 0 && thumbRect.GetHeight() > 0 ); 1555 1556 scrollbarValues = gtk_range_get_adjustment( GTK_RANGE(scrollbarWidget) ); 1557 if ( scrollbarValues == NULL ) 1558 scrollbarValues = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 1559 if ( nPart == PART_DRAW_BACKGROUND_HORZ ) 1560 { 1561 scrollbarValues->lower = pScrollbarVal->mnMin; 1562 scrollbarValues->upper = pScrollbarVal->mnMax; 1563 scrollbarValues->value = pScrollbarVal->mnCur; 1564 scrollbarValues->page_size = scrollbarRect.GetWidth() / 2; 1565 } 1566 else 1567 { 1568 scrollbarValues->lower = pScrollbarVal->mnMin; 1569 scrollbarValues->upper = pScrollbarVal->mnMax; 1570 scrollbarValues->value = pScrollbarVal->mnCur; 1571 scrollbarValues->page_size = scrollbarRect.GetHeight() / 2; 1572 } 1573 gtk_adjustment_changed( scrollbarValues ); 1574 1575 // as multiple paints are required for the scrollbar 1576 // painting them directly to the window flickers 1577 pixmap = NWGetPixmapFromScreen( pixmapRect ); 1578 if( ! pixmap ) 1579 return sal_False; 1580 x = y = 0; 1581 1582 w = pixmapRect.GetWidth(); 1583 h = pixmapRect.GetHeight(); 1584 1585 GdkDrawable* const &gdkDrawable = GDK_DRAWABLE( pixmap ); 1586 GdkRectangle* gdkRect = NULL; 1587 1588 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1589 NWSetWidgetState( GTK_WIDGET(scrollbarWidget), nState, stateType ); 1590 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 1591 style = GTK_WIDGET( scrollbarWidget )->style; 1592 1593 // ----------------- TROUGH 1594 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, 1595 GTK_STATE_NORMAL, GTK_SHADOW_NONE, gdkRect, 1596 m_pWindow, "base", x, y, 1597 w, h ); 1598 gtk_paint_box( style, gdkDrawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, 1599 gdkRect, GTK_WIDGET(scrollbarWidget), "trough", 1600 x, y, 1601 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() ); 1602 1603 if ( nState & CTRL_STATE_FOCUSED ) 1604 { 1605 gtk_paint_focus( style, gdkDrawable, GTK_STATE_ACTIVE, 1606 gdkRect, GTK_WIDGET(scrollbarWidget), "trough", 1607 x, y, 1608 scrollbarRect.GetWidth(), scrollbarRect.GetHeight() ); 1609 } 1610 1611 // ----------------- THUMB 1612 if ( has_slider ) 1613 { 1614 NWConvertVCLStateToGTKState( pScrollbarVal->mnThumbState, &stateType, &shadowType ); 1615 if ( pScrollbarVal->mnThumbState & CTRL_STATE_PRESSED ) stateType = GTK_STATE_PRELIGHT; 1616 gtk_paint_slider( style, gdkDrawable, stateType, GTK_SHADOW_OUT, 1617 gdkRect, GTK_WIDGET(scrollbarWidget), "slider", 1618 x+hShim+thumbRect.Left(), y+vShim+thumbRect.Top(), 1619 thumbRect.GetWidth(), thumbRect.GetHeight(), scrollbarOrientation ); 1620 } 1621 // ----------------- BUTTON 1 // 1622 if ( has_backward ) 1623 { 1624 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType ); 1625 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1626 gtk_paint_box( style, gdkDrawable, stateType, shadowType, 1627 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper", 1628 x+hShim+button11BoundRect.Left(), y+vShim+button11BoundRect.Top(), 1629 button11BoundRect.GetWidth(), button11BoundRect.GetHeight() ); 1630 // ----------------- ARROW 1 1631 NWCalcArrowRect( button11BoundRect, arrowRect ); 1632 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1633 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True, 1634 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1635 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1636 } 1637 if ( has_forward2 ) 1638 { 1639 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType ); 1640 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1641 gtk_paint_box( style, gdkDrawable, stateType, shadowType, 1642 gdkRect, GTK_WIDGET(scrollbarWidget), "stepper", 1643 x+hShim+button12BoundRect.Left(), y+vShim+button12BoundRect.Top(), 1644 button12BoundRect.GetWidth(), button12BoundRect.GetHeight() ); 1645 // ----------------- ARROW 1 1646 NWCalcArrowRect( button12BoundRect, arrowRect ); 1647 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1648 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True, 1649 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1650 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1651 } 1652 // ----------------- BUTTON 2 1653 if ( has_backward2 ) 1654 { 1655 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton1State, &stateType, &shadowType ); 1656 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1657 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect, 1658 GTK_WIDGET(scrollbarWidget), "stepper", 1659 x+hShim+button21BoundRect.Left(), y+vShim+button21BoundRect.Top(), 1660 button21BoundRect.GetWidth(), button21BoundRect.GetHeight() ); 1661 // ----------------- ARROW 2 1662 NWCalcArrowRect( button21BoundRect, arrowRect ); 1663 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1664 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button1Type, sal_True, 1665 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1666 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1667 } 1668 if ( has_forward ) 1669 { 1670 NWConvertVCLStateToGTKState( pScrollbarVal->mnButton2State, &stateType, &shadowType ); 1671 if ( stateType == GTK_STATE_INSENSITIVE ) stateType = GTK_STATE_NORMAL; 1672 gtk_paint_box( style, gdkDrawable, stateType, shadowType, gdkRect, 1673 GTK_WIDGET(scrollbarWidget), "stepper", 1674 x+hShim+button22BoundRect.Left(), y+vShim+button22BoundRect.Top(), 1675 button22BoundRect.GetWidth(), button22BoundRect.GetHeight() ); 1676 // ----------------- ARROW 2 1677 NWCalcArrowRect( button22BoundRect, arrowRect ); 1678 gtk_paint_arrow( style, gdkDrawable, stateType, shadowType, 1679 gdkRect, GTK_WIDGET(scrollbarWidget), scrollbarTag, button2Type, sal_True, 1680 x+hShim+arrowRect.Left(), y+vShim+arrowRect.Top(), 1681 arrowRect.GetWidth(), arrowRect.GetHeight() ); 1682 } 1683 1684 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) ) 1685 { 1686 g_object_unref( pixmap ); 1687 return( sal_False ); 1688 } 1689 g_object_unref( pixmap ); 1690 1691 return( sal_True ); 1692 } 1693 1694 //--- 1695 1696 static Rectangle NWGetScrollButtonRect( int nScreen, ControlPart nPart, Rectangle aAreaRect ) 1697 { 1698 gint slider_width; 1699 gint stepper_size; 1700 gint stepper_spacing; 1701 gint trough_border; 1702 1703 NWEnsureGTKScrollbars( nScreen ); 1704 1705 // Grab some button style attributes 1706 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget, 1707 "slider-width", &slider_width, 1708 "stepper-size", &stepper_size, 1709 "trough-border", &trough_border, 1710 "stepper-spacing", &stepper_spacing, (char *)NULL ); 1711 1712 gboolean has_forward; 1713 gboolean has_forward2; 1714 gboolean has_backward; 1715 gboolean has_backward2; 1716 1717 gtk_widget_style_get( gWidgetData[nScreen].gScrollHorizWidget, 1718 "has-forward-stepper", &has_forward, 1719 "has-secondary-forward-stepper", &has_forward2, 1720 "has-backward-stepper", &has_backward, 1721 "has-secondary-backward-stepper", &has_backward2, (char *)NULL ); 1722 gint buttonWidth; 1723 gint buttonHeight; 1724 Rectangle buttonRect; 1725 1726 gint nFirst = 0; 1727 gint nSecond = 0; 1728 1729 if ( has_forward ) nSecond += 1; 1730 if ( has_forward2 ) nFirst += 1; 1731 if ( has_backward ) nFirst += 1; 1732 if ( has_backward2 ) nSecond += 1; 1733 1734 if ( ( nPart == PART_BUTTON_UP ) || ( nPart == PART_BUTTON_DOWN ) ) 1735 { 1736 buttonWidth = slider_width + 2 * trough_border; 1737 buttonHeight = stepper_size + trough_border + stepper_spacing; 1738 } 1739 else 1740 { 1741 buttonWidth = stepper_size + trough_border + stepper_spacing; 1742 buttonHeight = slider_width + 2 * trough_border; 1743 } 1744 1745 if ( nPart == PART_BUTTON_UP ) 1746 { 1747 buttonHeight *= nFirst; 1748 buttonHeight -= 1; 1749 buttonRect.setX( aAreaRect.Left() ); 1750 buttonRect.setY( aAreaRect.Top() ); 1751 } 1752 else if ( nPart == PART_BUTTON_LEFT ) 1753 { 1754 buttonWidth *= nFirst; 1755 buttonWidth -= 1; 1756 buttonRect.setX( aAreaRect.Left() ); 1757 buttonRect.setY( aAreaRect.Top() ); 1758 } 1759 else if ( nPart == PART_BUTTON_DOWN ) 1760 { 1761 buttonHeight *= nSecond; 1762 buttonRect.setX( aAreaRect.Left() ); 1763 buttonRect.setY( aAreaRect.Top() + aAreaRect.GetHeight() - buttonHeight ); 1764 } 1765 else if ( nPart == PART_BUTTON_RIGHT ) 1766 { 1767 buttonWidth *= nSecond; 1768 buttonRect.setX( aAreaRect.Left() + aAreaRect.GetWidth() - buttonWidth ); 1769 buttonRect.setY( aAreaRect.Top() ); 1770 } 1771 1772 buttonRect.SetSize( Size( buttonWidth, buttonHeight ) ); 1773 1774 return( buttonRect ); 1775 } 1776 1777 //------------------------------------- 1778 1779 sal_Bool GtkSalGraphics::NWPaintGTKEditBox( GdkDrawable* gdkDrawable, 1780 ControlType nType, ControlPart nPart, 1781 const Rectangle& rControlRectangle, 1782 const clipList& rClipList, 1783 ControlState nState, 1784 const ImplControlValue& aValue, 1785 const OUString& rCaption ) 1786 { 1787 Rectangle pixmapRect; 1788 GdkRectangle clipRect; 1789 1790 // Find the overall bounding rect of the buttons's drawing area, 1791 // plus its actual draw rect excluding adornment 1792 pixmapRect = NWGetEditBoxPixmapRect( m_nScreen, nType, nPart, rControlRectangle, 1793 nState, aValue, rCaption ); 1794 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 1795 { 1796 clipRect.x = it->Left(); 1797 clipRect.y = it->Top(); 1798 clipRect.width = it->GetWidth(); 1799 clipRect.height = it->GetHeight(); 1800 1801 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, pixmapRect, nState, aValue, rCaption ); 1802 } 1803 1804 return( sal_True ); 1805 } 1806 1807 1808 /* Take interior/exterior focus into account and return 1809 * the bounding rectangle of the edit box including 1810 * any focus requirements. 1811 */ 1812 static Rectangle NWGetEditBoxPixmapRect(int nScreen, 1813 ControlType, 1814 ControlPart, 1815 Rectangle aAreaRect, 1816 ControlState, 1817 const ImplControlValue&, 1818 const OUString& ) 1819 { 1820 Rectangle pixmapRect = aAreaRect; 1821 gboolean interiorFocus; 1822 gint focusWidth; 1823 1824 NWEnsureGTKEditBox( nScreen ); 1825 1826 // Grab some entry style attributes 1827 gtk_widget_style_get( gWidgetData[nScreen].gEditBoxWidget, 1828 "focus-line-width", &focusWidth, 1829 "interior-focus", &interiorFocus, (char *)NULL ); 1830 1831 if ( !interiorFocus ) 1832 { 1833 pixmapRect.Move( -(focusWidth), -(focusWidth) ); 1834 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + (2*(focusWidth)), 1835 pixmapRect.GetHeight() + (2*(focusWidth)) ) ); 1836 } 1837 1838 return( pixmapRect ); 1839 } 1840 1841 1842 /* Paint a GTK Entry widget into the specified GdkPixmap. 1843 * All coordinates should be local to the Pixmap, NOT 1844 * screen/window coordinates. 1845 */ 1846 static void NWPaintOneEditBox( int nScreen, 1847 GdkDrawable * gdkDrawable, 1848 GdkRectangle * gdkRect, 1849 ControlType nType, 1850 ControlPart, 1851 Rectangle aEditBoxRect, 1852 ControlState nState, 1853 const ImplControlValue&, 1854 const OUString& ) 1855 { 1856 GtkStateType stateType; 1857 GtkShadowType shadowType; 1858 GtkWidget *widget; 1859 1860 NWEnsureGTKButton( nScreen ); 1861 NWEnsureGTKEditBox( nScreen ); 1862 NWEnsureGTKSpinButton( nScreen ); 1863 NWEnsureGTKCombo( nScreen ); 1864 NWEnsureGTKScrolledWindow( nScreen ); 1865 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1866 1867 /* border's shadowType for gtk entries is always GTK_SHADOW_IN (see gtkentry.c) 1868 shadowType = GTK_SHADOW_IN; 1869 */ 1870 1871 switch ( nType ) 1872 { 1873 case CTRL_SPINBOX: 1874 widget = gWidgetData[nScreen].gSpinButtonWidget; 1875 break; 1876 1877 case CTRL_MULTILINE_EDITBOX: 1878 widget = gWidgetData[nScreen].gScrolledWindowWidget; 1879 break; 1880 case CTRL_COMBOBOX: 1881 widget = GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry; 1882 break; 1883 1884 default: 1885 widget = gWidgetData[nScreen].gEditBoxWidget; 1886 break; 1887 } 1888 1889 if ( stateType == GTK_STATE_PRELIGHT ) 1890 stateType = GTK_STATE_NORMAL; 1891 1892 // Blueprint needs to paint entry_bg with a Button widget, not an Entry widget to get 1893 // a nice white (or whatever default color) background 1894 GtkWidget* pBGWidget = widget; 1895 if( GtkSalGraphics::bNeedButtonStyleAsEditBackgroundWorkaround ) 1896 { 1897 NWSetWidgetState( gWidgetData[nScreen].gBtnWidget, nState, stateType ); 1898 pBGWidget = gWidgetData[nScreen].gBtnWidget; 1899 } 1900 NWSetWidgetState( widget, nState, stateType ); 1901 1902 gtk_paint_flat_box( pBGWidget->style, gdkDrawable, stateType, GTK_SHADOW_NONE, 1903 gdkRect, pBGWidget, "entry_bg", 1904 aEditBoxRect.Left(), aEditBoxRect.Top(), 1905 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() ); 1906 gtk_paint_shadow( widget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, 1907 gdkRect, widget, "entry", 1908 aEditBoxRect.Left(), aEditBoxRect.Top(), 1909 aEditBoxRect.GetWidth(), aEditBoxRect.GetHeight() ); 1910 1911 } 1912 1913 1914 1915 //------------------------------------- 1916 1917 sal_Bool GtkSalGraphics::NWPaintGTKSpinBox( ControlType nType, ControlPart nPart, 1918 const Rectangle& rControlRectangle, 1919 const clipList&, 1920 ControlState nState, 1921 const ImplControlValue& aValue, 1922 const OUString& rCaption ) 1923 { 1924 GdkPixmap * pixmap; 1925 Rectangle pixmapRect; 1926 GtkStateType stateType; 1927 GtkShadowType shadowType; 1928 const SpinbuttonValue * pSpinVal = (aValue.getType() == CTRL_SPINBUTTONS) ? static_cast<const SpinbuttonValue *>(&aValue) : NULL; 1929 Rectangle upBtnRect; 1930 ControlPart upBtnPart = PART_BUTTON_UP; 1931 ControlState upBtnState = CTRL_STATE_ENABLED; 1932 Rectangle downBtnRect; 1933 ControlPart downBtnPart = PART_BUTTON_DOWN; 1934 ControlState downBtnState = CTRL_STATE_ENABLED; 1935 1936 NWEnsureGTKButton( m_nScreen ); 1937 NWEnsureGTKSpinButton( m_nScreen ); 1938 NWEnsureGTKArrow( m_nScreen ); 1939 1940 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 1941 1942 if ( pSpinVal ) 1943 { 1944 upBtnPart = pSpinVal->mnUpperPart; 1945 upBtnState = pSpinVal->mnUpperState; 1946 1947 downBtnPart = pSpinVal->mnLowerPart; 1948 downBtnState = pSpinVal->mnLowerState; 1949 } 1950 1951 // CTRL_SPINBUTTONS pass their area in pSpinVal, not in rControlRectangle 1952 if ( nType == CTRL_SPINBUTTONS ) 1953 { 1954 if ( !pSpinVal ) 1955 { 1956 std::fprintf( stderr, "Tried to draw CTRL_SPINBUTTONS, but the SpinButtons data structure didn't exist!\n" ); 1957 return( false ); 1958 } 1959 pixmapRect = pSpinVal->maUpperRect; 1960 pixmapRect.Union( pSpinVal->maLowerRect ); 1961 } 1962 else 1963 pixmapRect = rControlRectangle; 1964 1965 1966 pixmap = NWGetPixmapFromScreen( pixmapRect ); 1967 if ( !pixmap ) 1968 return( sal_False ); 1969 1970 upBtnRect = NWGetSpinButtonRect( m_nScreen, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); 1971 downBtnRect = NWGetSpinButtonRect( m_nScreen, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); 1972 1973 if ( (nType==CTRL_SPINBOX) && (nPart!=PART_ALL_BUTTONS) ) 1974 { 1975 // Draw an edit field for SpinBoxes and ComboBoxes 1976 Rectangle aEditBoxRect( pixmapRect ); 1977 aEditBoxRect.SetSize( Size( upBtnRect.Left() - pixmapRect.Left(), aEditBoxRect.GetHeight() ) ); 1978 aEditBoxRect.setX( 0 ); 1979 aEditBoxRect.setY( 0 ); 1980 1981 NWPaintOneEditBox( m_nScreen, pixmap, NULL, nType, nPart, aEditBoxRect, nState, aValue, rCaption ); 1982 } 1983 1984 NWSetWidgetState( gWidgetData[m_nScreen].gSpinButtonWidget, nState, stateType ); 1985 gtk_widget_style_get( gWidgetData[m_nScreen].gSpinButtonWidget, "shadow_type", &shadowType, (char *)NULL ); 1986 1987 if ( shadowType != GTK_SHADOW_NONE ) 1988 { 1989 Rectangle shadowRect( upBtnRect ); 1990 1991 shadowRect.Union( downBtnRect ); 1992 gtk_paint_box( gWidgetData[m_nScreen].gSpinButtonWidget->style, pixmap, GTK_STATE_NORMAL, shadowType, NULL, 1993 gWidgetData[m_nScreen].gSpinButtonWidget, "spinbutton", 1994 (shadowRect.Left() - pixmapRect.Left()), (shadowRect.Top() - pixmapRect.Top()), 1995 shadowRect.GetWidth(), shadowRect.GetHeight() ); 1996 } 1997 1998 NWPaintOneSpinButton( m_nScreen, pixmap, nType, upBtnPart, pixmapRect, upBtnState, aValue, rCaption ); 1999 NWPaintOneSpinButton( m_nScreen, pixmap, nType, downBtnPart, pixmapRect, downBtnState, aValue, rCaption ); 2000 2001 if( !NWRenderPixmapToScreen(pixmap, pixmapRect) ) 2002 { 2003 g_object_unref( pixmap ); 2004 return( sal_False ); 2005 } 2006 2007 g_object_unref( pixmap ); 2008 return( sal_True ); 2009 } 2010 2011 //--- 2012 2013 static Rectangle NWGetSpinButtonRect( int nScreen, 2014 ControlType, 2015 ControlPart nPart, 2016 Rectangle aAreaRect, 2017 ControlState, 2018 const ImplControlValue&, 2019 const OUString& ) 2020 { 2021 gint buttonSize; 2022 Rectangle buttonRect; 2023 2024 NWEnsureGTKSpinButton( nScreen ); 2025 2026 buttonSize = MAX( PANGO_PIXELS( pango_font_description_get_size(GTK_WIDGET(gWidgetData[nScreen].gSpinButtonWidget)->style->font_desc) ), 2027 MIN_SPIN_ARROW_WIDTH ); 2028 buttonSize -= buttonSize % 2 - 1; /* force odd */ 2029 buttonRect.SetSize( Size( buttonSize + 2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness, 2030 buttonRect.GetHeight() ) ); 2031 buttonRect.setX( aAreaRect.Left() + (aAreaRect.GetWidth() - buttonRect.GetWidth()) ); 2032 if ( nPart == PART_BUTTON_UP ) 2033 { 2034 buttonRect.setY( aAreaRect.Top() ); 2035 buttonRect.Bottom() = buttonRect.Top() + (aAreaRect.GetHeight() / 2); 2036 } 2037 else if( nPart == PART_BUTTON_DOWN ) 2038 { 2039 buttonRect.setY( aAreaRect.Top() + (aAreaRect.GetHeight() / 2) ); 2040 buttonRect.Bottom() = aAreaRect.Bottom(); // cover area completely 2041 } 2042 else 2043 { 2044 buttonRect.Right() = buttonRect.Left()-1; 2045 buttonRect.Left() = aAreaRect.Left(); 2046 buttonRect.Top() = aAreaRect.Top(); 2047 buttonRect.Bottom() = aAreaRect.Bottom(); 2048 } 2049 2050 return( buttonRect ); 2051 } 2052 2053 //--- 2054 2055 static void NWPaintOneSpinButton( int nScreen, 2056 GdkPixmap* pixmap, 2057 ControlType nType, 2058 ControlPart nPart, 2059 Rectangle aAreaRect, 2060 ControlState nState, 2061 const ImplControlValue& aValue, 2062 const OUString& rCaption ) 2063 { 2064 Rectangle buttonRect; 2065 GtkStateType stateType; 2066 GtkShadowType shadowType; 2067 Rectangle arrowRect; 2068 gint arrowSize; 2069 2070 NWEnsureGTKSpinButton( nScreen ); 2071 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2072 2073 buttonRect = NWGetSpinButtonRect( nScreen, nType, nPart, aAreaRect, nState, aValue, rCaption ); 2074 2075 NWSetWidgetState( gWidgetData[nScreen].gSpinButtonWidget, nState, stateType ); 2076 gtk_paint_box( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, shadowType, NULL, gWidgetData[nScreen].gSpinButtonWidget, 2077 (nPart == PART_BUTTON_UP) ? "spinbutton_up" : "spinbutton_down", 2078 (buttonRect.Left() - aAreaRect.Left()), (buttonRect.Top() - aAreaRect.Top()), 2079 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2080 2081 arrowSize = (buttonRect.GetWidth() - (2 * gWidgetData[nScreen].gSpinButtonWidget->style->xthickness)) - 4; 2082 arrowSize -= arrowSize % 2 - 1; /* force odd */ 2083 arrowRect.SetSize( Size( arrowSize, arrowSize ) ); 2084 arrowRect.setX( buttonRect.Left() + (buttonRect.GetWidth() - arrowRect.GetWidth()) / 2 ); 2085 if ( nPart == PART_BUTTON_UP ) 2086 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 + 1); 2087 else 2088 arrowRect.setY( buttonRect.Top() + (buttonRect.GetHeight() - arrowRect.GetHeight()) / 2 - 1); 2089 2090 gtk_paint_arrow( gWidgetData[nScreen].gSpinButtonWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[nScreen].gSpinButtonWidget, 2091 "spinbutton", (nPart == PART_BUTTON_UP) ? GTK_ARROW_UP : GTK_ARROW_DOWN, sal_True, 2092 (arrowRect.Left() - aAreaRect.Left()), (arrowRect.Top() - aAreaRect.Top()), 2093 arrowRect.GetWidth(), arrowRect.GetHeight() ); 2094 } 2095 2096 2097 //------------------------------------- 2098 2099 sal_Bool GtkSalGraphics::NWPaintGTKComboBox( GdkDrawable* gdkDrawable, 2100 ControlType nType, ControlPart nPart, 2101 const Rectangle& rControlRectangle, 2102 const clipList& rClipList, 2103 ControlState nState, 2104 const ImplControlValue& aValue, 2105 const OUString& rCaption ) 2106 { 2107 Rectangle pixmapRect; 2108 Rectangle buttonRect; 2109 GtkStateType stateType; 2110 GtkShadowType shadowType; 2111 Rectangle arrowRect; 2112 gint x,y; 2113 GdkRectangle clipRect; 2114 2115 NWEnsureGTKButton( m_nScreen ); 2116 NWEnsureGTKArrow( m_nScreen ); 2117 NWEnsureGTKCombo( m_nScreen ); 2118 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2119 2120 // Find the overall bounding rect of the buttons's drawing area, 2121 // plus its actual draw rect excluding adornment 2122 pixmapRect = rControlRectangle; 2123 x = rControlRectangle.Left(); 2124 y = rControlRectangle.Top(); 2125 2126 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 2127 NWSetWidgetState( gWidgetData[m_nScreen].gComboWidget, nState, stateType ); 2128 NWSetWidgetState( gWidgetData[m_nScreen].gArrowWidget, nState, stateType ); 2129 2130 buttonRect = NWGetComboBoxButtonRect( m_nScreen, nType, PART_BUTTON_DOWN, pixmapRect, nState, aValue, rCaption ); 2131 if( nPart == PART_BUTTON_DOWN ) 2132 buttonRect.Left() += 1; 2133 2134 Rectangle aEditBoxRect( pixmapRect ); 2135 aEditBoxRect.SetSize( Size( pixmapRect.GetWidth() - buttonRect.GetWidth(), aEditBoxRect.GetHeight() ) ); 2136 2137 #define ARROW_EXTENT 0.7 2138 arrowRect.SetSize( Size( (gint)(MIN_ARROW_SIZE * ARROW_EXTENT), 2139 (gint)(MIN_ARROW_SIZE * ARROW_EXTENT) ) ); 2140 arrowRect.SetPos( Point( buttonRect.Left() + (gint)((buttonRect.GetWidth() - arrowRect.GetWidth()) / 2), 2141 buttonRect.Top() + (gint)((buttonRect.GetHeight() - arrowRect.GetHeight()) / 2) ) ); 2142 2143 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2144 { 2145 clipRect.x = it->Left(); 2146 clipRect.y = it->Top(); 2147 clipRect.width = it->GetWidth(); 2148 clipRect.height = it->GetHeight(); 2149 2150 if( nPart == PART_ENTIRE_CONTROL ) 2151 NWPaintOneEditBox( m_nScreen, gdkDrawable, &clipRect, nType, nPart, aEditBoxRect, 2152 nState, aValue, rCaption ); 2153 2154 // Buttons must paint opaque since some themes have alpha-channel enabled buttons 2155 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 2156 &clipRect, m_pWindow, "base", 2157 x+(buttonRect.Left() - pixmapRect.Left()), 2158 y+(buttonRect.Top() - pixmapRect.Top()), 2159 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2160 gtk_paint_box( GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button->style, gdkDrawable, stateType, shadowType, 2161 &clipRect, GTK_COMBO(gWidgetData[m_nScreen].gComboWidget)->button, "button", 2162 x+(buttonRect.Left() - pixmapRect.Left()), 2163 y+(buttonRect.Top() - pixmapRect.Top()), 2164 buttonRect.GetWidth(), buttonRect.GetHeight() ); 2165 2166 gtk_paint_arrow( gWidgetData[m_nScreen].gArrowWidget->style, gdkDrawable, stateType, shadowType, 2167 &clipRect, gWidgetData[m_nScreen].gArrowWidget, "arrow", GTK_ARROW_DOWN, sal_True, 2168 x+(arrowRect.Left() - pixmapRect.Left()), y+(arrowRect.Top() - pixmapRect.Top()), 2169 arrowRect.GetWidth(), arrowRect.GetHeight() ); 2170 } 2171 2172 return( sal_True ); 2173 } 2174 2175 //---- 2176 2177 static Rectangle NWGetComboBoxButtonRect( int nScreen, 2178 ControlType, 2179 ControlPart nPart, 2180 Rectangle aAreaRect, 2181 ControlState, 2182 const ImplControlValue&, 2183 const OUString& ) 2184 { 2185 Rectangle aButtonRect; 2186 gint nArrowWidth; 2187 gint nButtonWidth; 2188 gint nFocusWidth; 2189 gint nFocusPad; 2190 2191 NWEnsureGTKArrow( nScreen ); 2192 2193 // Grab some button style attributes 2194 gtk_widget_style_get( gWidgetData[nScreen].gDropdownWidget, 2195 "focus-line-width", &nFocusWidth, 2196 "focus-padding", &nFocusPad, (char *)NULL ); 2197 2198 nArrowWidth = MIN_ARROW_SIZE + (GTK_MISC(gWidgetData[nScreen].gArrowWidget)->xpad * 2); 2199 nButtonWidth = nArrowWidth + 2200 ((BTN_CHILD_SPACING + gWidgetData[nScreen].gDropdownWidget->style->xthickness) * 2) 2201 + (2 * (nFocusWidth+nFocusPad)); 2202 if( nPart == PART_BUTTON_DOWN ) 2203 { 2204 aButtonRect.SetSize( Size( nButtonWidth, aAreaRect.GetHeight() ) ); 2205 aButtonRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - nButtonWidth, 2206 aAreaRect.Top() ) ); 2207 } 2208 else if( nPart == PART_SUB_EDIT ) 2209 { 2210 NWEnsureGTKCombo( nScreen ); 2211 2212 gint adjust_x = GTK_CONTAINER(gWidgetData[nScreen].gComboWidget)->border_width + 2213 nFocusWidth + 2214 nFocusPad; 2215 gint adjust_y = adjust_x + gWidgetData[nScreen].gComboWidget->style->ythickness; 2216 adjust_x += gWidgetData[nScreen].gComboWidget->style->xthickness; 2217 aButtonRect.SetSize( Size( aAreaRect.GetWidth() - nButtonWidth - 2 * adjust_x, 2218 aAreaRect.GetHeight() - 2 * adjust_y ) ); 2219 Point aEditPos = aAreaRect.TopLeft(); 2220 aEditPos.X() += adjust_x; 2221 aEditPos.Y() += adjust_y; 2222 aButtonRect.SetPos( aEditPos ); 2223 } 2224 2225 return( aButtonRect ); 2226 } 2227 2228 //------------------------------------- 2229 2230 2231 2232 sal_Bool GtkSalGraphics::NWPaintGTKTabItem( ControlType nType, ControlPart, 2233 const Rectangle& rControlRectangle, 2234 const clipList&, 2235 ControlState nState, 2236 const ImplControlValue& aValue, 2237 const OUString& ) 2238 { 2239 OSL_ASSERT( nType != CTRL_TAB_ITEM || aValue.getType() == CTRL_TAB_ITEM ); 2240 GdkPixmap * pixmap; 2241 Rectangle pixmapRect; 2242 Rectangle tabRect; 2243 GtkStateType stateType; 2244 GtkShadowType shadowType; 2245 if( ! gWidgetData[ m_nScreen ].gCacheTabItems ) 2246 { 2247 gWidgetData[ m_nScreen ].gCacheTabItems = new NWPixmapCache( m_nScreen ); 2248 gWidgetData[ m_nScreen ].gCacheTabPages = new NWPixmapCache( m_nScreen ); 2249 } 2250 NWPixmapCache& aCacheItems = *gWidgetData[ m_nScreen ].gCacheTabItems; 2251 NWPixmapCache& aCachePage = *gWidgetData[ m_nScreen ].gCacheTabPages; 2252 2253 if( !aCacheItems.GetSize() ) 2254 aCacheItems.SetSize( 20 ); 2255 if( !aCachePage.GetSize() ) 2256 aCachePage.SetSize( 1 ); 2257 2258 if ( (nType == CTRL_TAB_ITEM) && (aValue.getType() != CTRL_TAB_ITEM) ) 2259 { 2260 return( false ); 2261 } 2262 2263 NWEnsureGTKButton( m_nScreen ); 2264 NWEnsureGTKNotebook( m_nScreen ); 2265 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2266 2267 // Find the overall bounding rect of the buttons's drawing area, 2268 // plus its actual draw rect excluding adornment 2269 pixmapRect = rControlRectangle; 2270 if ( nType == CTRL_TAB_ITEM ) 2271 { 2272 const TabitemValue * pTabitemValue = static_cast<const TabitemValue *>(&aValue); 2273 if ( !pTabitemValue->isFirst() ) 2274 { 2275 // GTK+ tabs overlap on the right edge (the top tab obscures the 2276 // left edge of the tab right "below" it, so adjust the rectangle 2277 // to draw tabs slightly large so the overlap happens 2278 pixmapRect.Move( -2, 0 ); 2279 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, pixmapRect.GetHeight() ) ); 2280 } 2281 if ( nState & CTRL_STATE_SELECTED ) 2282 { 2283 // In GTK+, the selected tab is 2px taller than all other tabs 2284 pixmapRect.Move( 0, -2 ); 2285 pixmapRect.Bottom() += 2; 2286 tabRect = pixmapRect; 2287 // Only draw over 1 pixel of the tab pane that this tab is drawn on top of. 2288 tabRect.Bottom() -= 1; 2289 } 2290 else 2291 tabRect = pixmapRect; 2292 2293 // Allow the tab to draw a right border if needed 2294 tabRect.Right() -= 1; 2295 2296 // #129732# avoid degenerate cases which might lead to crashes 2297 if( tabRect.GetWidth() <= 1 || tabRect.GetHeight() <= 1 ) 2298 return false; 2299 } 2300 2301 if( nType == CTRL_TAB_ITEM ) 2302 { 2303 if( aCacheItems.Find( nType, nState, pixmapRect, &pixmap ) ) 2304 return NWRenderPixmapToScreen( pixmap, pixmapRect ); 2305 } 2306 else 2307 { 2308 if( aCachePage.Find( nType, nState, pixmapRect, &pixmap ) ) 2309 return NWRenderPixmapToScreen( pixmap, pixmapRect ); 2310 } 2311 2312 2313 // gtk_widget_set_state( gWidgetData[m_nScreen].gNotebookWidget, stateType ); 2314 2315 pixmap = gdk_pixmap_new( NULL, pixmapRect.GetWidth(), pixmapRect.GetHeight(), 2316 GetX11SalData()->GetDisplay()->GetVisual( m_nScreen ).GetDepth() ); 2317 GdkRectangle paintRect; 2318 paintRect.x = paintRect.y = 0; 2319 paintRect.width = pixmapRect.GetWidth(); 2320 paintRect.height = pixmapRect.GetHeight(); 2321 2322 gtk_paint_flat_box( m_pWindow->style, pixmap, GTK_STATE_NORMAL, 2323 GTK_SHADOW_NONE, &paintRect, m_pWindow, "base", 0, 0, -1, -1); 2324 2325 NWSetWidgetState( gWidgetData[m_nScreen].gNotebookWidget, nState, stateType ); 2326 2327 switch( nType ) 2328 { 2329 case CTRL_TAB_BODY: 2330 break; 2331 2332 case CTRL_FIXEDBORDER: 2333 case CTRL_TAB_PANE: 2334 gtk_paint_box_gap( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, GTK_STATE_NORMAL, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget, 2335 (char *)"notebook", 0, 0, pixmapRect.GetWidth(), pixmapRect.GetHeight(), GTK_POS_TOP, 0, 0 ); 2336 break; 2337 2338 case CTRL_TAB_ITEM: 2339 stateType = ( nState & CTRL_STATE_SELECTED ) ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE; 2340 2341 gtk_paint_extension( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_OUT, NULL, gWidgetData[m_nScreen].gNotebookWidget, 2342 (char *)"tab", (tabRect.Left() - pixmapRect.Left()), (tabRect.Top() - pixmapRect.Top()), 2343 tabRect.GetWidth(), tabRect.GetHeight(), GTK_POS_BOTTOM ); 2344 2345 if ( nState & CTRL_STATE_SELECTED ) 2346 { 2347 gtk_paint_flat_box( gWidgetData[m_nScreen].gNotebookWidget->style, pixmap, stateType, GTK_SHADOW_NONE, NULL, m_pWindow, 2348 (char *)"base", 0, (pixmapRect.GetHeight() - 1), pixmapRect.GetWidth(), 1 ); 2349 } 2350 break; 2351 2352 default: 2353 break; 2354 } 2355 2356 // Crux seems to think it can make the pane without a left edge 2357 if ( nType == CTRL_FIXEDBORDER ) 2358 pixmapRect.Move( 1, 0 ); 2359 2360 // cache data 2361 if( nType == CTRL_TAB_ITEM ) 2362 aCacheItems.Fill( nType, nState, pixmapRect, pixmap ); 2363 else 2364 aCachePage.Fill( nType, nState, pixmapRect, pixmap ); 2365 2366 sal_Bool bSuccess = NWRenderPixmapToScreen(pixmap, pixmapRect); 2367 g_object_unref( pixmap ); 2368 return bSuccess; 2369 } 2370 2371 //------------------------------------- 2372 2373 sal_Bool GtkSalGraphics::NWPaintGTKListBox( GdkDrawable* gdkDrawable, 2374 ControlType nType, ControlPart nPart, 2375 const Rectangle& rControlRectangle, 2376 const clipList& rClipList, 2377 ControlState nState, 2378 const ImplControlValue& aValue, 2379 const OUString& rCaption ) 2380 { 2381 Rectangle pixmapRect; 2382 Rectangle widgetRect; 2383 Rectangle aIndicatorRect; 2384 GtkStateType stateType; 2385 GtkShadowType shadowType; 2386 gint bInteriorFocus; 2387 gint nFocusLineWidth; 2388 gint nFocusPadding; 2389 gint x,y; 2390 GdkRectangle clipRect; 2391 2392 NWEnsureGTKButton( m_nScreen ); 2393 NWEnsureGTKOptionMenu( m_nScreen ); 2394 NWEnsureGTKScrolledWindow( m_nScreen ); 2395 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2396 2397 // Find the overall bounding rect of the buttons's drawing area, 2398 // plus its actual draw rect excluding adornment 2399 pixmapRect = rControlRectangle; 2400 if ( nPart == PART_WINDOW ) 2401 { 2402 // Make the widget a _bit_ bigger 2403 pixmapRect.SetPos( Point( pixmapRect.Left() - 1, 2404 pixmapRect.Top() - 1 ) ); 2405 pixmapRect.SetSize( Size( pixmapRect.GetWidth() + 2, 2406 pixmapRect.GetHeight() + 2 ) ); 2407 } 2408 2409 widgetRect = pixmapRect; 2410 x = pixmapRect.Left(); 2411 y = pixmapRect.Top(); 2412 2413 // set up references to correct drawable and cliprect 2414 NWSetWidgetState( gWidgetData[m_nScreen].gBtnWidget, nState, stateType ); 2415 NWSetWidgetState( gWidgetData[m_nScreen].gOptionMenuWidget, nState, stateType ); 2416 NWSetWidgetState( gWidgetData[m_nScreen].gScrolledWindowWidget, nState, stateType ); 2417 2418 if ( nPart != PART_WINDOW ) 2419 { 2420 gtk_widget_style_get( gWidgetData[m_nScreen].gOptionMenuWidget, 2421 "interior_focus", &bInteriorFocus, 2422 "focus_line_width", &nFocusLineWidth, 2423 "focus_padding", &nFocusPadding, 2424 (char *)NULL); 2425 } 2426 2427 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2428 { 2429 clipRect.x = it->Left(); 2430 clipRect.y = it->Top(); 2431 clipRect.width = it->GetWidth(); 2432 clipRect.height = it->GetHeight(); 2433 2434 if ( nPart != PART_WINDOW ) 2435 { 2436 // Listboxes must paint opaque since some themes have alpha-channel enabled bodies 2437 gtk_paint_flat_box( gWidgetData[m_nScreen].gBtnWidget->style, gdkDrawable, GTK_STATE_NORMAL, GTK_SHADOW_NONE, 2438 &clipRect, m_pWindow, "base", x, y, 2439 pixmapRect.GetWidth(), pixmapRect.GetHeight() ); 2440 gtk_paint_box( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect, 2441 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenu", 2442 x+(widgetRect.Left() - pixmapRect.Left()), 2443 y+(widgetRect.Top() - pixmapRect.Top()), 2444 widgetRect.GetWidth(), widgetRect.GetHeight() ); 2445 aIndicatorRect = NWGetListBoxIndicatorRect( m_nScreen, nType, nPart, widgetRect, nState, 2446 aValue, rCaption ); 2447 gtk_paint_tab( gWidgetData[m_nScreen].gOptionMenuWidget->style, gdkDrawable, stateType, shadowType, &clipRect, 2448 gWidgetData[m_nScreen].gOptionMenuWidget, "optionmenutab", 2449 x+(aIndicatorRect.Left() - pixmapRect.Left()), 2450 y+(aIndicatorRect.Top() - pixmapRect.Top()), 2451 aIndicatorRect.GetWidth(), aIndicatorRect.GetHeight() ); 2452 } 2453 else 2454 { 2455 shadowType = GTK_SHADOW_IN; 2456 2457 gtk_paint_shadow( gWidgetData[m_nScreen].gScrolledWindowWidget->style, gdkDrawable, GTK_STATE_NORMAL, shadowType, 2458 &clipRect, gWidgetData[m_nScreen].gScrolledWindowWidget, "scrolled_window", 2459 x+(widgetRect.Left() - pixmapRect.Left()), y+(widgetRect.Top() - pixmapRect.Top()), 2460 widgetRect.GetWidth(), widgetRect.GetHeight() ); 2461 } 2462 } 2463 2464 return( sal_True ); 2465 } 2466 2467 sal_Bool GtkSalGraphics::NWPaintGTKToolbar( 2468 GdkDrawable* gdkDrawable, 2469 ControlType, ControlPart nPart, 2470 const Rectangle& rControlRectangle, 2471 const clipList& rClipList, 2472 ControlState nState, const ImplControlValue& aValue, 2473 const OUString& ) 2474 { 2475 GtkStateType stateType; 2476 GtkShadowType shadowType; 2477 gint x, y, w, h; 2478 gint g_x=0, g_y=0, g_w=10, g_h=10; 2479 bool bPaintButton = true; 2480 GtkWidget* pButtonWidget = gWidgetData[m_nScreen].gToolbarButtonWidget; 2481 GdkRectangle clipRect; 2482 2483 NWEnsureGTKToolbar( m_nScreen ); 2484 if( nPart == PART_BUTTON ) // toolbar buttons cannot focus in gtk 2485 nState &= ~CTRL_STATE_FOCUSED; 2486 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2487 2488 x = rControlRectangle.Left(); 2489 y = rControlRectangle.Top(); 2490 w = rControlRectangle.GetWidth(); 2491 h = rControlRectangle.GetHeight(); 2492 2493 // handle toolbar 2494 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 2495 { 2496 NWSetWidgetState( gWidgetData[m_nScreen].gToolbarWidget, nState, stateType ); 2497 2498 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE ); 2499 if ( nState & CTRL_STATE_ENABLED ) 2500 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gToolbarWidget, GTK_SENSITIVE ); 2501 2502 if( nPart == PART_DRAW_BACKGROUND_HORZ ) 2503 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_HORIZONTAL ); 2504 else 2505 gtk_toolbar_set_orientation( GTK_TOOLBAR(gWidgetData[m_nScreen].gToolbarWidget), GTK_ORIENTATION_VERTICAL ); 2506 } 2507 // handle grip 2508 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 2509 { 2510 NWSetWidgetState( gWidgetData[m_nScreen].gHandleBoxWidget, nState, stateType ); 2511 2512 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE ); 2513 if ( nState & CTRL_STATE_ENABLED ) 2514 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gHandleBoxWidget, GTK_SENSITIVE ); 2515 2516 gtk_handle_box_set_shadow_type( GTK_HANDLE_BOX(gWidgetData[m_nScreen].gHandleBoxWidget), shadowType ); 2517 2518 // evaluate grip rect 2519 if( aValue.getType() == CTRL_TOOLBAR ) 2520 { 2521 const ToolbarValue* pVal = static_cast<const ToolbarValue*>(&aValue); 2522 g_x = pVal->maGripRect.Left(); 2523 g_y = pVal->maGripRect.Top(); 2524 g_w = pVal->maGripRect.GetWidth(); 2525 g_h = pVal->maGripRect.GetHeight(); 2526 } 2527 } 2528 // handle button 2529 else if( nPart == PART_BUTTON ) 2530 { 2531 bPaintButton = 2532 (GTK_BUTTON(pButtonWidget)->relief != GTK_RELIEF_NONE) 2533 || (nState & CTRL_STATE_PRESSED) 2534 || (nState & CTRL_STATE_ROLLOVER); 2535 if( aValue.getTristateVal() == BUTTONVALUE_ON ) 2536 { 2537 pButtonWidget = gWidgetData[m_nScreen].gToolbarToggleWidget; 2538 shadowType = GTK_SHADOW_IN; 2539 stateType = GTK_STATE_ACTIVE; 2540 // special case stateType value for depressed toggle buttons 2541 // cf. gtk+/gtk/gtktogglebutton.c (gtk_toggle_button_update_state) 2542 if( (nState & (CTRL_STATE_ROLLOVER|CTRL_STATE_PRESSED)) ) 2543 { 2544 stateType = GTK_STATE_PRELIGHT; 2545 shadowType = GTK_SHADOW_OUT; 2546 } 2547 bPaintButton = true; 2548 } 2549 else 2550 stateType = GTK_STATE_PRELIGHT; // only for bPaintButton = true, in which case always rollver is meant 2551 2552 NWSetWidgetState( pButtonWidget, nState, stateType ); 2553 gtk_widget_ensure_style( pButtonWidget ); 2554 } 2555 2556 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2557 { 2558 clipRect.x = it->Left(); 2559 clipRect.y = it->Top(); 2560 clipRect.width = it->GetWidth(); 2561 clipRect.height = it->GetHeight(); 2562 2563 // draw toolbar 2564 if( nPart == PART_DRAW_BACKGROUND_HORZ || nPart == PART_DRAW_BACKGROUND_VERT ) 2565 { 2566 gtk_paint_flat_box( gWidgetData[m_nScreen].gToolbarWidget->style, 2567 gdkDrawable, 2568 (GtkStateType)GTK_STATE_NORMAL, 2569 GTK_SHADOW_NONE, 2570 &clipRect, 2571 gWidgetData[m_nScreen].gToolbarWidget, 2572 "base", 2573 x, y, w, h ); 2574 gtk_paint_box( gWidgetData[m_nScreen].gToolbarWidget->style, 2575 gdkDrawable, 2576 stateType, 2577 shadowType, 2578 &clipRect, 2579 gWidgetData[m_nScreen].gToolbarWidget, 2580 "toolbar", 2581 x, y, w, h ); 2582 } 2583 // draw grip 2584 else if( nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT ) 2585 { 2586 gtk_paint_handle( gWidgetData[m_nScreen].gHandleBoxWidget->style, 2587 gdkDrawable, 2588 GTK_STATE_NORMAL, 2589 GTK_SHADOW_OUT, 2590 &clipRect, 2591 gWidgetData[m_nScreen].gHandleBoxWidget, 2592 "handlebox", 2593 g_x, g_y, g_w, g_h, 2594 nPart == PART_THUMB_HORZ ? 2595 GTK_ORIENTATION_HORIZONTAL : 2596 GTK_ORIENTATION_VERTICAL 2597 ); 2598 } 2599 // draw button 2600 else if( nPart == PART_BUTTON ) 2601 { 2602 if( bPaintButton ) 2603 { 2604 gtk_paint_box( pButtonWidget->style, gdkDrawable, 2605 stateType, 2606 shadowType, 2607 &clipRect, 2608 pButtonWidget, "button", x, y, w, h ); 2609 } 2610 } 2611 } 2612 2613 return( sal_True ); 2614 } 2615 2616 //---- 2617 2618 sal_Bool GtkSalGraphics::NWPaintGTKMenubar( 2619 GdkDrawable* gdkDrawable, 2620 ControlType, ControlPart nPart, 2621 const Rectangle& rControlRectangle, 2622 const clipList& rClipList, 2623 ControlState nState, const ImplControlValue&, 2624 const OUString& ) 2625 { 2626 GtkStateType stateType; 2627 GtkShadowType shadowType; 2628 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT; 2629 gint x, y, w, h; 2630 GdkRectangle clipRect; 2631 2632 NWEnsureGTKMenubar( m_nScreen ); 2633 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2634 2635 x = rControlRectangle.Left(); 2636 y = rControlRectangle.Top(); 2637 w = rControlRectangle.GetWidth(); 2638 h = rControlRectangle.GetHeight(); 2639 2640 if( nPart == PART_MENU_ITEM ) 2641 { 2642 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2643 { 2644 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenubarWidget, 2645 "selected_shadow_type", &selected_shadow_type, 2646 (char *)NULL); 2647 } 2648 } 2649 2650 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2651 { 2652 clipRect.x = it->Left(); 2653 clipRect.y = it->Top(); 2654 clipRect.width = it->GetWidth(); 2655 clipRect.height = it->GetHeight(); 2656 2657 // handle Menubar 2658 if( nPart == PART_ENTIRE_CONTROL ) 2659 { 2660 NWSetWidgetState( gWidgetData[m_nScreen].gMenubarWidget, nState, stateType ); 2661 2662 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE ); 2663 if ( nState & CTRL_STATE_ENABLED ) 2664 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenubarWidget, GTK_SENSITIVE ); 2665 2666 // #118704# for translucent menubar styles paint background first 2667 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenubarWidget->style, 2668 gdkDrawable, 2669 GTK_STATE_NORMAL, 2670 GTK_SHADOW_NONE, 2671 &clipRect, 2672 GTK_WIDGET(m_pWindow), 2673 "base", 2674 x, y, w, h ); 2675 gtk_paint_box( gWidgetData[m_nScreen].gMenubarWidget->style, 2676 gdkDrawable, 2677 stateType, 2678 shadowType, 2679 &clipRect, 2680 gWidgetData[m_nScreen].gMenubarWidget, 2681 "menubar", 2682 x, y, w, h ); 2683 } 2684 else if( nPart == PART_MENU_ITEM ) 2685 { 2686 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2687 { 2688 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenubarWidget->style, 2689 gdkDrawable, 2690 GTK_STATE_PRELIGHT, 2691 selected_shadow_type, 2692 &clipRect, 2693 gWidgetData[m_nScreen].gMenuItemMenubarWidget, 2694 "menuitem", 2695 x, y, w, h); 2696 } 2697 } 2698 } 2699 2700 return( sal_True ); 2701 } 2702 2703 sal_Bool GtkSalGraphics::NWPaintGTKPopupMenu( 2704 GdkDrawable* gdkDrawable, 2705 ControlType, ControlPart nPart, 2706 const Rectangle& rControlRectangle, 2707 const clipList& rClipList, 2708 ControlState nState, const ImplControlValue&, 2709 const OUString& ) 2710 { 2711 // #i50745# gtk does not draw disabled menu entries (and crux theme 2712 // even crashes), draw them using vcl functionality. 2713 if( nPart == PART_MENU_ITEM && ! (nState & CTRL_STATE_ENABLED) ) 2714 return sal_False; 2715 2716 GtkStateType stateType; 2717 GtkShadowType shadowType; 2718 GtkShadowType selected_shadow_type = GTK_SHADOW_OUT; 2719 gint x, y, w, h; 2720 GdkRectangle clipRect; 2721 2722 NWEnsureGTKMenu( m_nScreen ); 2723 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2724 2725 x = rControlRectangle.Left(); 2726 y = rControlRectangle.Top(); 2727 w = rControlRectangle.GetWidth(); 2728 h = rControlRectangle.GetHeight(); 2729 2730 if( nPart == PART_MENU_ITEM && 2731 ( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) ) 2732 { 2733 gtk_widget_style_get( gWidgetData[m_nScreen].gMenuItemMenuWidget, 2734 "selected_shadow_type", &selected_shadow_type, 2735 (char *)NULL); 2736 } 2737 2738 NWSetWidgetState( gWidgetData[m_nScreen].gMenuWidget, nState, stateType ); 2739 2740 GTK_WIDGET_UNSET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE ); 2741 if ( nState & CTRL_STATE_ENABLED ) 2742 GTK_WIDGET_SET_FLAGS( gWidgetData[m_nScreen].gMenuWidget, GTK_SENSITIVE ); 2743 2744 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2745 { 2746 clipRect.x = it->Left(); 2747 clipRect.y = it->Top(); 2748 clipRect.width = it->GetWidth(); 2749 clipRect.height = it->GetHeight(); 2750 2751 if( nPart == PART_ENTIRE_CONTROL ) 2752 { 2753 // #118704# for translucent menubar styles paint background first 2754 gtk_paint_flat_box( gWidgetData[m_nScreen].gMenuWidget->style, 2755 gdkDrawable, 2756 GTK_STATE_NORMAL, 2757 GTK_SHADOW_NONE, 2758 &clipRect, 2759 GTK_WIDGET(m_pWindow), 2760 "base", 2761 x, y, w, h ); 2762 gtk_paint_box( gWidgetData[m_nScreen].gMenuWidget->style, 2763 gdkDrawable, 2764 GTK_STATE_NORMAL, 2765 GTK_SHADOW_OUT, 2766 &clipRect, 2767 gWidgetData[m_nScreen].gMenuWidget, 2768 "menu", 2769 x, y, w, h ); 2770 } 2771 else if( nPart == PART_MENU_ITEM ) 2772 { 2773 if( nState & (CTRL_STATE_SELECTED|CTRL_STATE_ROLLOVER) ) 2774 { 2775 if( nState & CTRL_STATE_ENABLED ) 2776 gtk_paint_box( gWidgetData[m_nScreen].gMenuItemMenuWidget->style, 2777 gdkDrawable, 2778 GTK_STATE_PRELIGHT, 2779 selected_shadow_type, 2780 &clipRect, 2781 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2782 "menuitem", 2783 x, y, w, h); 2784 } 2785 } 2786 else if( nPart == PART_MENU_ITEM_CHECK_MARK || nPart == PART_MENU_ITEM_RADIO_MARK ) 2787 { 2788 GtkWidget* pWidget = (nPart == PART_MENU_ITEM_CHECK_MARK) ? 2789 gWidgetData[m_nScreen].gMenuItemCheckMenuWidget : 2790 gWidgetData[m_nScreen].gMenuItemRadioMenuWidget; 2791 2792 GtkStateType nStateType = GTK_STATE_NORMAL; 2793 GtkShadowType nShadowType; 2794 2795 if ( nState & CTRL_STATE_SELECTED ) 2796 nStateType = GTK_STATE_PRELIGHT; 2797 2798 NWSetWidgetState( pWidget, nState, nStateType ); 2799 2800 if ( nState & CTRL_STATE_PRESSED ) 2801 nShadowType = GTK_SHADOW_IN; 2802 else 2803 nShadowType = GTK_SHADOW_OUT; 2804 2805 if ( nPart == PART_MENU_ITEM_CHECK_MARK ) 2806 { 2807 gtk_paint_check( pWidget->style, 2808 gdkDrawable, 2809 nStateType, 2810 nShadowType, 2811 &clipRect, 2812 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2813 "check", 2814 x, y, w, h ); 2815 } 2816 else 2817 { 2818 gtk_paint_option( pWidget->style, 2819 gdkDrawable, 2820 nStateType, 2821 nShadowType, 2822 &clipRect, 2823 gWidgetData[m_nScreen].gMenuItemMenuWidget, 2824 "option", 2825 x, y, w, h ); 2826 } 2827 } 2828 } 2829 2830 return( sal_True ); 2831 } 2832 2833 sal_Bool GtkSalGraphics::NWPaintGTKTooltip( 2834 GdkDrawable* gdkDrawable, 2835 ControlType, ControlPart, 2836 const Rectangle& rControlRectangle, 2837 const clipList& rClipList, 2838 ControlState, const ImplControlValue&, 2839 const OUString& ) 2840 { 2841 NWEnsureGTKTooltip( m_nScreen ); 2842 2843 gint x, y, w, h; 2844 GdkRectangle clipRect; 2845 2846 x = rControlRectangle.Left(); 2847 y = rControlRectangle.Top(); 2848 w = rControlRectangle.GetWidth(); 2849 h = rControlRectangle.GetHeight(); 2850 2851 for( clipList::const_iterator it = rClipList.begin(); it != rClipList.end(); ++it ) 2852 { 2853 clipRect.x = it->Left(); 2854 clipRect.y = it->Top(); 2855 clipRect.width = it->GetWidth(); 2856 clipRect.height = it->GetHeight(); 2857 2858 gtk_paint_flat_box( gWidgetData[m_nScreen].gTooltipPopup->style, 2859 gdkDrawable, 2860 GTK_STATE_NORMAL, 2861 GTK_SHADOW_OUT, 2862 &clipRect, 2863 gWidgetData[m_nScreen].gTooltipPopup, 2864 "tooltip", 2865 x, y, w, h ); 2866 } 2867 2868 return( sal_True ); 2869 } 2870 2871 sal_Bool GtkSalGraphics::NWPaintGTKListNode( 2872 GdkDrawable*, 2873 ControlType, ControlPart, 2874 const Rectangle& rControlRectangle, 2875 const clipList&, 2876 ControlState nState, const ImplControlValue& rValue, 2877 const OUString& ) 2878 { 2879 NWEnsureGTKTreeView( m_nScreen ); 2880 2881 Rectangle aRect( rControlRectangle ); 2882 aRect.Left() -= 2; 2883 aRect.Right() += 2; 2884 aRect.Top() -= 2; 2885 aRect.Bottom() += 2; 2886 gint w, h; 2887 w = aRect.GetWidth(); 2888 h = aRect.GetHeight(); 2889 2890 GtkStateType stateType; 2891 GtkShadowType shadowType; 2892 NWConvertVCLStateToGTKState( nState, &stateType, &shadowType ); 2893 2894 ButtonValue aButtonValue = rValue.getTristateVal(); 2895 GtkExpanderStyle eStyle = GTK_EXPANDER_EXPANDED; 2896 2897 switch( aButtonValue ) 2898 { 2899 case BUTTONVALUE_ON: eStyle = GTK_EXPANDER_EXPANDED;break; 2900 case BUTTONVALUE_OFF: eStyle = GTK_EXPANDER_COLLAPSED; break; 2901 default: 2902 break; 2903 } 2904 2905 GdkPixmap* pixmap = NWGetPixmapFromScreen( aRect ); 2906 if( ! pixmap ) 2907 return sal_False; 2908 2909 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 2910 gtk_paint_expander( gWidgetData[m_nScreen].gTreeView->style, 2911 pixDrawable, 2912 stateType, 2913 NULL, 2914 gWidgetData[m_nScreen].gTreeView, 2915 "treeview", 2916 w/2, h/2, 2917 eStyle ); 2918 2919 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, aRect ); 2920 g_object_unref( pixmap ); 2921 2922 return bRet; 2923 } 2924 2925 sal_Bool GtkSalGraphics::NWPaintGTKProgress( 2926 GdkDrawable*, 2927 ControlType, ControlPart, 2928 const Rectangle& rControlRectangle, 2929 const clipList&, 2930 ControlState, const ImplControlValue& rValue, 2931 const OUString& ) 2932 { 2933 NWEnsureGTKProgressBar( m_nScreen ); 2934 2935 gint w, h; 2936 w = rControlRectangle.GetWidth(); 2937 h = rControlRectangle.GetHeight(); 2938 2939 long nProgressWidth = rValue.getNumericVal(); 2940 2941 GdkPixmap* pixmap = NWGetPixmapFromScreen( Rectangle( Point( 0, 0 ), Size( w, h ) ) ); 2942 if( ! pixmap ) 2943 return sal_False; 2944 2945 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 2946 2947 // paint background 2948 gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style, 2949 pixDrawable, 2950 GTK_STATE_NORMAL, 2951 GTK_SHADOW_NONE, 2952 NULL, 2953 gWidgetData[m_nScreen].gProgressBar, 2954 "trough", 2955 0, 0, w, h ); 2956 if( nProgressWidth > 0 ) 2957 { 2958 // paint progress 2959 if( Application::GetSettings().GetLayoutRTL() ) 2960 { 2961 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 2962 pixDrawable, 2963 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 2964 NULL, 2965 gWidgetData[m_nScreen].gProgressBar, 2966 "bar", 2967 w-nProgressWidth, 0, nProgressWidth, h 2968 ); 2969 } 2970 else 2971 { 2972 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 2973 pixDrawable, 2974 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 2975 NULL, 2976 gWidgetData[m_nScreen].gProgressBar, 2977 "bar", 2978 0, 0, nProgressWidth, h 2979 ); 2980 } 2981 } 2982 2983 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); 2984 g_object_unref( pixmap ); 2985 2986 return bRet; 2987 } 2988 2989 sal_Bool GtkSalGraphics::NWPaintGTKSlider( 2990 GdkDrawable*, 2991 ControlType, ControlPart nPart, 2992 const Rectangle& rControlRectangle, 2993 const clipList&, 2994 ControlState nState, const ImplControlValue& rValue, 2995 const OUString& ) 2996 { 2997 OSL_ASSERT( rValue.getType() == CTRL_SLIDER ); 2998 NWEnsureGTKSlider( m_nScreen ); 2999 3000 gint w, h; 3001 w = rControlRectangle.GetWidth(); 3002 h = rControlRectangle.GetHeight(); 3003 3004 const SliderValue* pVal = static_cast<const SliderValue*>(&rValue); 3005 3006 GdkPixmap* pixmap = NWGetPixmapFromScreen( rControlRectangle ); 3007 if( ! pixmap ) 3008 return sal_False; 3009 3010 GdkDrawable* const &pixDrawable = GDK_DRAWABLE( pixmap ); 3011 GtkWidget* pWidget = (nPart == PART_TRACK_HORZ_AREA) 3012 ? GTK_WIDGET(gWidgetData[m_nScreen].gHScale) 3013 : GTK_WIDGET(gWidgetData[m_nScreen].gVScale); 3014 const gchar* pDetail = (nPart == PART_TRACK_HORZ_AREA) ? "hscale" : "vscale"; 3015 GtkOrientation eOri = (nPart == PART_TRACK_HORZ_AREA) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; 3016 GtkStateType eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_ACTIVE : GTK_STATE_INSENSITIVE; 3017 gint slider_width = 10; 3018 gint slider_length = 10; 3019 gint trough_border = 0; 3020 gtk_widget_style_get( pWidget, 3021 "slider-width", &slider_width, 3022 "slider-length", &slider_length, 3023 "trough-border", &trough_border, 3024 NULL); 3025 3026 eState = (nState & CTRL_STATE_ENABLED) ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; 3027 if( nPart == PART_TRACK_HORZ_AREA ) 3028 { 3029 gtk_paint_box( pWidget->style, 3030 pixDrawable, 3031 eState, 3032 GTK_SHADOW_IN, 3033 NULL, 3034 pWidget, 3035 "trough", 3036 0, (h-slider_width-2*trough_border)/2, w, slider_width + 2*trough_border); 3037 gint x = (w - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); 3038 gtk_paint_slider( pWidget->style, 3039 pixDrawable, 3040 eState, 3041 GTK_SHADOW_OUT, 3042 NULL, 3043 pWidget, 3044 pDetail, 3045 x, (h-slider_width)/2, 3046 slider_length, slider_width, 3047 eOri ); 3048 } 3049 else 3050 { 3051 gtk_paint_box( pWidget->style, 3052 pixDrawable, 3053 eState, 3054 GTK_SHADOW_IN, 3055 NULL, 3056 pWidget, 3057 "trough", 3058 (w-slider_width-2*trough_border)/2, 0, slider_width + 2*trough_border, h); 3059 gint y = (h - slider_length + 1) * (pVal->mnCur - pVal->mnMin) / (pVal->mnMax - pVal->mnMin); 3060 gtk_paint_slider( pWidget->style, 3061 pixDrawable, 3062 eState, 3063 GTK_SHADOW_OUT, 3064 NULL, 3065 pWidget, 3066 pDetail, 3067 (w-slider_width)/2, y, 3068 slider_width, slider_length, 3069 eOri ); 3070 } 3071 #if 0 3072 // paint background 3073 gtk_paint_flat_box( gWidgetData[m_nScreen].gProgressBar->style, 3074 pixDrawable, 3075 GTK_STATE_NORMAL, 3076 GTK_SHADOW_NONE, 3077 NULL, 3078 gWidgetData[m_nScreen].gProgressBar, 3079 "trough", 3080 0, 0, w, h ); 3081 if( nProgressWidth > 0 ) 3082 { 3083 // paint progress 3084 if( Application::GetSettings().GetLayoutRTL() ) 3085 { 3086 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 3087 pixDrawable, 3088 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 3089 NULL, 3090 gWidgetData[m_nScreen].gProgressBar, 3091 "bar", 3092 w-nProgressWidth, 0, nProgressWidth, h 3093 ); 3094 } 3095 else 3096 { 3097 gtk_paint_box( gWidgetData[m_nScreen].gProgressBar->style, 3098 pixDrawable, 3099 GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, 3100 NULL, 3101 gWidgetData[m_nScreen].gProgressBar, 3102 "bar", 3103 0, 0, nProgressWidth, h 3104 ); 3105 } 3106 } 3107 #endif 3108 3109 sal_Bool bRet = NWRenderPixmapToScreen( pixmap, rControlRectangle ); 3110 g_object_unref( pixmap ); 3111 3112 return bRet; 3113 } 3114 3115 //---- 3116 3117 static Rectangle NWGetListBoxButtonRect( int nScreen, 3118 ControlType, 3119 ControlPart nPart, 3120 Rectangle aAreaRect, 3121 ControlState, 3122 const ImplControlValue&, 3123 const OUString& ) 3124 { 3125 Rectangle aPartRect; 3126 GtkRequisition *pIndicatorSize = NULL; 3127 GtkBorder *pIndicatorSpacing = NULL; 3128 gint width = 13; // GTK+ default 3129 gint right = 5; // GTK+ default 3130 gint nButtonAreaWidth = 0; 3131 gint xthickness = 0; 3132 3133 NWEnsureGTKOptionMenu( nScreen ); 3134 3135 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget, 3136 "indicator_size", &pIndicatorSize, 3137 "indicator_spacing",&pIndicatorSpacing, (char *)NULL); 3138 3139 if ( pIndicatorSize ) 3140 width = pIndicatorSize->width; 3141 3142 if ( pIndicatorSpacing ) 3143 right = pIndicatorSpacing->right; 3144 3145 Size aPartSize( 0, aAreaRect.GetHeight() ); 3146 Point aPartPos ( 0, aAreaRect.Top() ); 3147 3148 xthickness = gWidgetData[nScreen].gOptionMenuWidget->style->xthickness; 3149 nButtonAreaWidth = width + right + (xthickness * 2); 3150 switch( nPart ) 3151 { 3152 case PART_BUTTON_DOWN: 3153 aPartSize.Width() = nButtonAreaWidth; 3154 aPartPos.X() = aAreaRect.Left() + aAreaRect.GetWidth() - aPartSize.Width(); 3155 break; 3156 3157 case PART_SUB_EDIT: 3158 aPartSize.Width() = aAreaRect.GetWidth() - nButtonAreaWidth - xthickness; 3159 aPartPos.X() = aAreaRect.Left() + xthickness; 3160 break; 3161 3162 default: 3163 aPartSize.Width() = aAreaRect.GetWidth(); 3164 aPartPos.X() = aAreaRect.Left(); 3165 break; 3166 } 3167 aPartRect = Rectangle( aPartPos, aPartSize ); 3168 3169 if ( pIndicatorSize ) 3170 gtk_requisition_free( pIndicatorSize ); 3171 if ( pIndicatorSpacing ) 3172 gtk_border_free( pIndicatorSpacing ); 3173 3174 return( aPartRect ); 3175 } 3176 3177 //---- 3178 3179 static Rectangle NWGetListBoxIndicatorRect( int nScreen, 3180 ControlType, 3181 ControlPart, 3182 Rectangle aAreaRect, 3183 ControlState, 3184 const ImplControlValue&, 3185 const OUString& ) 3186 { 3187 Rectangle aIndicatorRect; 3188 GtkRequisition *pIndicatorSize = NULL; 3189 GtkBorder *pIndicatorSpacing = NULL; 3190 gint width = 13; // GTK+ default 3191 gint height = 13; // GTK+ default 3192 gint right = 5; // GTK+ default 3193 3194 NWEnsureGTKOptionMenu( nScreen ); 3195 3196 gtk_widget_style_get( gWidgetData[nScreen].gOptionMenuWidget, 3197 "indicator_size", &pIndicatorSize, 3198 "indicator_spacing",&pIndicatorSpacing, (char *)NULL); 3199 3200 if ( pIndicatorSize ) 3201 { 3202 width = pIndicatorSize->width; 3203 height = pIndicatorSize->height; 3204 } 3205 3206 if ( pIndicatorSpacing ) 3207 right = pIndicatorSpacing->right; 3208 3209 aIndicatorRect.SetSize( Size( width, height ) ); 3210 aIndicatorRect.SetPos( Point( aAreaRect.Left() + aAreaRect.GetWidth() - width - right - gWidgetData[nScreen].gOptionMenuWidget->style->xthickness, 3211 aAreaRect.Top() + ((aAreaRect.GetHeight() - height) / 2) ) ); 3212 3213 // If height is odd, move the indicator down 1 pixel 3214 if ( aIndicatorRect.GetHeight() % 2 ) 3215 aIndicatorRect.Move( 0, 1 ); 3216 3217 if ( pIndicatorSize ) 3218 gtk_requisition_free( pIndicatorSize ); 3219 if ( pIndicatorSpacing ) 3220 gtk_border_free( pIndicatorSpacing ); 3221 3222 return( aIndicatorRect ); 3223 } 3224 3225 static Rectangle NWGetToolbarRect( int nScreen, 3226 ControlType, 3227 ControlPart nPart, 3228 Rectangle aAreaRect, 3229 ControlState, 3230 const ImplControlValue&, 3231 const OUString& ) 3232 { 3233 Rectangle aRet; 3234 3235 if( nPart == PART_DRAW_BACKGROUND_HORZ || 3236 nPart == PART_DRAW_BACKGROUND_VERT ) 3237 aRet = aAreaRect; 3238 else if( nPart == PART_THUMB_HORZ ) 3239 aRet = Rectangle( Point( 0, 0 ), Size( aAreaRect.GetWidth(), 10 ) ); 3240 else if( nPart == PART_THUMB_VERT ) 3241 aRet = Rectangle( Point( 0, 0 ), Size( 10, aAreaRect.GetHeight() ) ); 3242 else if( nPart == PART_BUTTON ) 3243 { 3244 aRet = aAreaRect; 3245 3246 NWEnsureGTKToolbar( nScreen ); 3247 3248 gint nMinWidth = 3249 2*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness 3250 + 1 // CHILD_SPACING constant, found in gtk_button.c 3251 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->xthickness; // Murphy factor 3252 gint nMinHeight = 3253 2*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness 3254 + 1 // CHILD_SPACING constant, found in gtk_button.c 3255 + 3*gWidgetData[nScreen].gToolbarButtonWidget->style->ythickness; // Murphy factor 3256 3257 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarButtonWidget ); 3258 if( aAreaRect.GetWidth() < nMinWidth ) 3259 aRet.Right() = aRet.Left() + nMinWidth; 3260 if( aAreaRect.GetHeight() < nMinHeight ) 3261 aRet.Bottom() = aRet.Top() + nMinHeight; 3262 } 3263 3264 return aRet; 3265 } 3266 3267 /************************************************************************ 3268 * helper for GtkSalFrame 3269 ************************************************************************/ 3270 static inline Color getColor( const GdkColor& rCol ) 3271 { 3272 return Color( rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 ); 3273 } 3274 3275 #if OSL_DEBUG_LEVEL > 1 3276 3277 void printColor( const char* name, const GdkColor& rCol ) 3278 { 3279 std::fprintf( stderr, " %s = 0x%2x 0x%2x 0x%2x\n", 3280 name, 3281 rCol.red >> 8, rCol.green >> 8, rCol.blue >> 8 ); 3282 } 3283 3284 void printStyleColors( GtkStyle* pStyle ) 3285 { 3286 static const char* pStates[] = { "NORMAL", "ACTIVE", "PRELIGHT", "SELECTED", "INSENSITIVE" }; 3287 3288 for( int i = 0; i < 5; i++ ) 3289 { 3290 std::fprintf( stderr, "state %s colors:\n", pStates[i] ); 3291 printColor( "bg ", pStyle->bg[i] ); 3292 printColor( "fg ", pStyle->fg[i] ); 3293 printColor( "light ", pStyle->light[i] ); 3294 printColor( "dark ", pStyle->dark[i] ); 3295 printColor( "mid ", pStyle->mid[i] ); 3296 printColor( "text ", pStyle->text[i] ); 3297 printColor( "base ", pStyle->base[i] ); 3298 printColor( "text_aa", pStyle->text_aa[i] ); 3299 } 3300 } 3301 #endif 3302 3303 void GtkSalGraphics::updateSettings( AllSettings& rSettings ) 3304 { 3305 // get the widgets in place 3306 NWEnsureGTKMenu( m_nScreen ); 3307 NWEnsureGTKMenubar( m_nScreen ); 3308 NWEnsureGTKScrollbars( m_nScreen ); 3309 NWEnsureGTKEditBox( m_nScreen ); 3310 NWEnsureGTKTooltip( m_nScreen ); 3311 3312 gtk_widget_ensure_style( m_pWindow ); 3313 GtkStyle* pStyle = gtk_widget_get_style( m_pWindow ); 3314 3315 StyleSettings aStyleSet = rSettings.GetStyleSettings(); 3316 3317 #if OSL_DEBUG_LEVEL > 2 3318 printStyleColors( pStyle ); 3319 #endif 3320 3321 // text colors 3322 Color aTextColor = getColor( pStyle->text[GTK_STATE_NORMAL] ); 3323 aStyleSet.SetDialogTextColor( aTextColor ); 3324 aStyleSet.SetButtonTextColor( aTextColor ); 3325 aStyleSet.SetRadioCheckTextColor( aTextColor ); 3326 aStyleSet.SetGroupTextColor( aTextColor ); 3327 aStyleSet.SetLabelTextColor( aTextColor ); 3328 aStyleSet.SetInfoTextColor( aTextColor ); 3329 aStyleSet.SetWindowTextColor( aTextColor ); 3330 aStyleSet.SetFieldTextColor( aTextColor ); 3331 3332 // Tooltip colors 3333 GtkStyle* pTooltipStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gTooltipPopup ); 3334 aTextColor = getColor( pTooltipStyle->fg[ GTK_STATE_NORMAL ] ); 3335 aStyleSet.SetHelpTextColor( aTextColor ); 3336 3337 // mouse over text colors 3338 aTextColor = getColor( pStyle->fg[ GTK_STATE_PRELIGHT ] ); 3339 aStyleSet.SetButtonRolloverTextColor( aTextColor ); 3340 aStyleSet.SetFieldRolloverTextColor( aTextColor ); 3341 3342 // background colors 3343 Color aBackColor = getColor( pStyle->bg[GTK_STATE_NORMAL] ); 3344 Color aBackFieldColor = getColor( pStyle->base[ GTK_STATE_NORMAL ] ); 3345 aStyleSet.Set3DColors( aBackColor ); 3346 aStyleSet.SetFaceColor( aBackColor ); 3347 aStyleSet.SetDialogColor( aBackColor ); 3348 aStyleSet.SetWorkspaceColor( aBackColor ); 3349 aStyleSet.SetFieldColor( aBackFieldColor ); 3350 aStyleSet.SetWindowColor( aBackFieldColor ); 3351 // aStyleSet.SetHelpColor( aBackColor ); 3352 // ancient wisdom tells us a mystic algorithm how to set checked color 3353 if( aBackColor == COL_LIGHTGRAY ) 3354 aStyleSet.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) ); 3355 else 3356 { 3357 Color aColor2 = aStyleSet.GetLightColor(); 3358 Color aCheck( (sal_uInt8)(((sal_uInt16)aBackColor.GetRed()+(sal_uInt16)aColor2.GetRed())/2), 3359 (sal_uInt8)(((sal_uInt16)aBackColor.GetGreen()+(sal_uInt16)aColor2.GetGreen())/2), 3360 (sal_uInt8)(((sal_uInt16)aBackColor.GetBlue()+(sal_uInt16)aColor2.GetBlue())/2) 3361 ); 3362 aStyleSet.SetCheckedColor( aCheck ); 3363 } 3364 3365 // highlighting colors 3366 Color aHighlightColor = getColor( pStyle->base[GTK_STATE_SELECTED] ); 3367 Color aHighlightTextColor = getColor( pStyle->text[GTK_STATE_SELECTED] ); 3368 aStyleSet.SetHighlightColor( aHighlightColor ); 3369 aStyleSet.SetHighlightTextColor( aHighlightTextColor ); 3370 3371 if( ! gtk_check_version( 2, 10, 0 ) ) // link colors came in with 2.10, avoid an assertion 3372 { 3373 // hyperlink colors 3374 GdkColor *link_color = NULL; 3375 gtk_widget_style_get (m_pWindow, "link-color", &link_color, NULL); 3376 if (link_color) 3377 { 3378 aStyleSet.SetLinkColor(getColor(*link_color)); 3379 gdk_color_free (link_color); 3380 link_color = NULL; 3381 } 3382 gtk_widget_style_get (m_pWindow, "visited-link-color", &link_color, NULL); 3383 if (link_color) 3384 { 3385 aStyleSet.SetVisitedLinkColor(getColor(*link_color)); 3386 gdk_color_free (link_color); 3387 } 3388 } 3389 3390 // Tab colors 3391 aStyleSet.SetActiveTabColor( aBackFieldColor ); // same as the window color. 3392 Color aSelectedBackColor = getColor( pStyle->bg[GTK_STATE_ACTIVE] ); 3393 aStyleSet.SetInactiveTabColor( aSelectedBackColor ); 3394 3395 // menu disabled entries handling 3396 aStyleSet.SetSkipDisabledInMenus( sal_True ); 3397 // menu colors 3398 GtkStyle* pMenuStyle = gtk_widget_get_style( gWidgetData[m_nScreen].gMenuWidget ); 3399 GtkStyle* pMenuItemStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenuItemMenuWidget ); 3400 GtkStyle* pMenubarStyle = gtk_rc_get_style( gWidgetData[m_nScreen].gMenubarWidget ); 3401 GtkStyle* pMenuTextStyle = gtk_rc_get_style( gtk_bin_get_child( GTK_BIN(gWidgetData[m_nScreen].gMenuItemMenuWidget) ) ); 3402 3403 aBackColor = getColor( pMenubarStyle->bg[GTK_STATE_NORMAL] ); 3404 aStyleSet.SetMenuBarColor( aBackColor ); 3405 aBackColor = getColor( pMenuStyle->bg[GTK_STATE_NORMAL] ); 3406 aTextColor = getColor( pMenuTextStyle->fg[GTK_STATE_NORMAL] ); 3407 aStyleSet.SetMenuColor( aBackColor ); 3408 aStyleSet.SetMenuTextColor( aTextColor ); 3409 3410 aTextColor = getColor( pMenubarStyle->fg[GTK_STATE_NORMAL] ); 3411 aStyleSet.SetMenuBarTextColor( aTextColor ); 3412 3413 #if OSL_DEBUG_LEVEL > 1 3414 std::fprintf( stderr, "==\n" ); 3415 std::fprintf( stderr, "MenuColor = %x (%d)\n", (int)aStyleSet.GetMenuColor().GetColor(), aStyleSet.GetMenuColor().GetLuminance() ); 3416 std::fprintf( stderr, "MenuTextColor = %x (%d)\n", (int)aStyleSet.GetMenuTextColor().GetColor(), aStyleSet.GetMenuTextColor().GetLuminance() ); 3417 std::fprintf( stderr, "MenuBarColor = %x (%d)\n", (int)aStyleSet.GetMenuBarColor().GetColor(), aStyleSet.GetMenuBarColor().GetLuminance() ); 3418 std::fprintf( stderr, "MenuBarTextColor = %x (%d)\n", (int)aStyleSet.GetMenuBarTextColor().GetColor(), aStyleSet.GetMenuBarTextColor().GetLuminance() ); 3419 std::fprintf( stderr, "LightColor = %x (%d)\n", (int)aStyleSet.GetLightColor().GetColor(), aStyleSet.GetLightColor().GetLuminance() ); 3420 std::fprintf( stderr, "ShadowColor = %x (%d)\n", (int)aStyleSet.GetShadowColor().GetColor(), aStyleSet.GetShadowColor().GetLuminance() ); 3421 #endif 3422 3423 // Awful hack for menu separators in the Sonar and similar themes. 3424 // If the menu color is not too dark, and the menu text color is lighter, 3425 // make the "light" color lighter than the menu color and the "shadow" 3426 // color darker than it. 3427 if ( aStyleSet.GetMenuColor().GetLuminance() >= 32 && 3428 aStyleSet.GetMenuColor().GetLuminance() <= aStyleSet.GetMenuTextColor().GetLuminance() ) 3429 { 3430 Color temp = aStyleSet.GetMenuColor(); 3431 temp.IncreaseLuminance( 8 ); 3432 aStyleSet.SetLightColor( temp ); 3433 temp = aStyleSet.GetMenuColor(); 3434 temp.DecreaseLuminance( 16 ); 3435 aStyleSet.SetShadowColor( temp ); 3436 } 3437 3438 aHighlightColor = getColor( pMenuItemStyle->bg[ GTK_STATE_SELECTED ] ); 3439 aHighlightTextColor = getColor( pMenuTextStyle->fg[ GTK_STATE_PRELIGHT ] ); 3440 if( aHighlightColor == aHighlightTextColor ) 3441 aHighlightTextColor = (aHighlightColor.GetLuminance() < 128) ? Color( COL_WHITE ) : Color( COL_BLACK ); 3442 aStyleSet.SetMenuHighlightColor( aHighlightColor ); 3443 aStyleSet.SetMenuHighlightTextColor( aHighlightTextColor ); 3444 3445 // UI font 3446 OString aFamily = pango_font_description_get_family( pStyle->font_desc ); 3447 int nPangoHeight = pango_font_description_get_size( pStyle->font_desc ); 3448 PangoStyle eStyle = pango_font_description_get_style( pStyle->font_desc ); 3449 PangoWeight eWeight = pango_font_description_get_weight( pStyle->font_desc ); 3450 PangoStretch eStretch = pango_font_description_get_stretch( pStyle->font_desc ); 3451 3452 psp::FastPrintFontInfo aInfo; 3453 // set family name 3454 aInfo.m_aFamilyName = OStringToOUString( aFamily, RTL_TEXTENCODING_UTF8 ); 3455 // set italic 3456 switch( eStyle ) 3457 { 3458 case PANGO_STYLE_NORMAL: aInfo.m_eItalic = psp::italic::Upright;break; 3459 case PANGO_STYLE_ITALIC: aInfo.m_eItalic = psp::italic::Italic;break; 3460 case PANGO_STYLE_OBLIQUE: aInfo.m_eItalic = psp::italic::Oblique;break; 3461 } 3462 // set weight 3463 if( eWeight <= PANGO_WEIGHT_ULTRALIGHT ) 3464 aInfo.m_eWeight = psp::weight::UltraLight; 3465 else if( eWeight <= PANGO_WEIGHT_LIGHT ) 3466 aInfo.m_eWeight = psp::weight::Light; 3467 else if( eWeight <= PANGO_WEIGHT_NORMAL ) 3468 aInfo.m_eWeight = psp::weight::Normal; 3469 else if( eWeight <= PANGO_WEIGHT_BOLD ) 3470 aInfo.m_eWeight = psp::weight::Bold; 3471 else 3472 aInfo.m_eWeight = psp::weight::UltraBold; 3473 // set width 3474 switch( eStretch ) 3475 { 3476 case PANGO_STRETCH_ULTRA_CONDENSED: aInfo.m_eWidth = psp::width::UltraCondensed;break; 3477 case PANGO_STRETCH_EXTRA_CONDENSED: aInfo.m_eWidth = psp::width::ExtraCondensed;break; 3478 case PANGO_STRETCH_CONDENSED: aInfo.m_eWidth = psp::width::Condensed;break; 3479 case PANGO_STRETCH_SEMI_CONDENSED: aInfo.m_eWidth = psp::width::SemiCondensed;break; 3480 case PANGO_STRETCH_NORMAL: aInfo.m_eWidth = psp::width::Normal;break; 3481 case PANGO_STRETCH_SEMI_EXPANDED: aInfo.m_eWidth = psp::width::SemiExpanded;break; 3482 case PANGO_STRETCH_EXPANDED: aInfo.m_eWidth = psp::width::Expanded;break; 3483 case PANGO_STRETCH_EXTRA_EXPANDED: aInfo.m_eWidth = psp::width::ExtraExpanded;break; 3484 case PANGO_STRETCH_ULTRA_EXPANDED: aInfo.m_eWidth = psp::width::UltraExpanded;break; 3485 } 3486 3487 #if OSL_DEBUG_LEVEL > 1 3488 std::fprintf( stderr, "font name BEFORE system match: \"%s\"\n", aFamily.getStr() ); 3489 #endif 3490 3491 // match font to e.g. resolve "Sans" 3492 psp::PrintFontManager::get().matchFont( aInfo, rSettings.GetUILocale() ); 3493 3494 #if OSL_DEBUG_LEVEL > 1 3495 std::fprintf( stderr, "font match %s, name AFTER: \"%s\"\n", 3496 aInfo.m_nID != 0 ? "succeeded" : "failed", 3497 OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() ); 3498 #endif 3499 3500 sal_Int32 nDispDPIY = GetDisplay()->GetResolution().B(); 3501 int nPointHeight = 0; 3502 static gboolean(*pAbso)(const PangoFontDescription*) = 3503 (gboolean(*)(const PangoFontDescription*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "pango_font_description_get_size_is_absolute" ); 3504 3505 if( pAbso && pAbso( pStyle->font_desc ) ) 3506 nPointHeight = (nPangoHeight * 72 + nDispDPIY*PANGO_SCALE/2) / (nDispDPIY * PANGO_SCALE); 3507 else 3508 nPointHeight = nPangoHeight/PANGO_SCALE; 3509 3510 Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) ); 3511 if( aInfo.m_eWeight != psp::weight::Unknown ) 3512 aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) ); 3513 if( aInfo.m_eWidth != psp::width::Unknown ) 3514 aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) ); 3515 if( aInfo.m_eItalic != psp::italic::Unknown ) 3516 aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) ); 3517 if( aInfo.m_ePitch != psp::pitch::Unknown ) 3518 aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) ); 3519 3520 aStyleSet.SetAppFont( aFont ); 3521 aStyleSet.SetHelpFont( aFont ); 3522 aStyleSet.SetTitleFont( aFont ); 3523 aStyleSet.SetFloatTitleFont( aFont ); 3524 aStyleSet.SetMenuFont( aFont ); 3525 aStyleSet.SetToolFont( aFont ); 3526 aStyleSet.SetLabelFont( aFont ); 3527 aStyleSet.SetInfoFont( aFont ); 3528 aStyleSet.SetRadioCheckFont( aFont ); 3529 aStyleSet.SetPushButtonFont( aFont ); 3530 aStyleSet.SetFieldFont( aFont ); 3531 aStyleSet.SetIconFont( aFont ); 3532 aStyleSet.SetGroupFont( aFont ); 3533 3534 // get cursor blink time 3535 GtkSettings *pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gEditBoxWidget ); 3536 gboolean blink = false; 3537 3538 g_object_get( pSettings, "gtk-cursor-blink", &blink, (char *)NULL ); 3539 if( blink ) 3540 { 3541 gint blink_time = STYLE_CURSOR_NOBLINKTIME; 3542 g_object_get( pSettings, "gtk-cursor-blink-time", &blink_time, (char *)NULL ); 3543 // set the blink_time if there is a setting and it is reasonable 3544 // else leave the default value 3545 if( blink_time > 100 && blink_time != gint(STYLE_CURSOR_NOBLINKTIME) ) 3546 aStyleSet.SetCursorBlinkTime( blink_time/2 ); 3547 } 3548 else 3549 aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME ); 3550 3551 gboolean showmenuicons = true; 3552 pSettings = gtk_widget_get_settings( gWidgetData[m_nScreen].gImageMenuItem ); 3553 g_object_get( pSettings, "gtk-menu-images", &showmenuicons, (char *)NULL ); 3554 aStyleSet.SetUseImagesInMenus( showmenuicons ); 3555 3556 // set scrollbar settings 3557 gint slider_width = 14; 3558 gint trough_border = 1; 3559 gint min_slider_length = 21; 3560 3561 // Grab some button style attributes 3562 gtk_widget_style_get( gWidgetData[m_nScreen].gScrollHorizWidget, 3563 "slider-width", &slider_width, 3564 "trough-border", &trough_border, 3565 "min-slider-length", &min_slider_length, 3566 (char *)NULL ); 3567 gint magic = trough_border ? 1 : 0; 3568 aStyleSet.SetScrollBarSize( slider_width + 2*trough_border ); 3569 aStyleSet.SetMinThumbSize( min_slider_length - magic ); 3570 3571 // preferred icon style 3572 gchar* pIconThemeName = NULL; 3573 g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &pIconThemeName, (char *)NULL ); 3574 aStyleSet.SetPreferredSymbolsStyleName( OUString::createFromAscii( pIconThemeName ) ); 3575 g_free( pIconThemeName ); 3576 3577 // FIXME: need some way of fetching toolbar icon size. 3578 // aStyleSet.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_SMALL ); 3579 3580 const cairo_font_options_t* pNewOptions = NULL; 3581 if( GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), m_nScreen ) ) 3582 { 3583 //#if !GTK_CHECK_VERSION(2,8,1) 3584 #if !GTK_CHECK_VERSION(2,9,0) 3585 static cairo_font_options_t* (*gdk_screen_get_font_options)(GdkScreen*) = 3586 (cairo_font_options_t*(*)(GdkScreen*))osl_getAsciiFunctionSymbol( GetSalData()->m_pPlugin, "gdk_screen_get_font_options" ); 3587 if( gdk_screen_get_font_options != NULL ) 3588 #endif 3589 pNewOptions = gdk_screen_get_font_options( pScreen ); 3590 } 3591 aStyleSet.SetCairoFontOptions( pNewOptions ); 3592 3593 // finally update the collected settings 3594 rSettings.SetStyleSettings( aStyleSet ); 3595 3596 #if OSL_DEBUG_LEVEL > 1 3597 { 3598 GtkSettings* pGtkSettings = gtk_settings_get_default(); 3599 GValue aValue; 3600 memset( &aValue, 0, sizeof(GValue) ); 3601 g_value_init( &aValue, G_TYPE_STRING ); 3602 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue ); 3603 const gchar* pThemeName = g_value_get_string( &aValue ); 3604 std::fprintf( stderr, "Theme name is \"%s\"\n", pThemeName ); 3605 g_value_unset( &aValue ); 3606 } 3607 #endif 3608 GtkSettings* pGtkSettings = gtk_settings_get_default(); 3609 GValue aValue; 3610 memset( &aValue, 0, sizeof(GValue) ); 3611 g_value_init( &aValue, G_TYPE_STRING ); 3612 g_object_get_property( G_OBJECT(pGtkSettings), "gtk-theme-name", &aValue ); 3613 const gchar* pThemeName = g_value_get_string( &aValue ); 3614 3615 // default behaviour 3616 bNeedPixmapPaint = bGlobalNeedPixmapPaint; 3617 bToolbarGripWorkaround = false; 3618 bNeedButtonStyleAsEditBackgroundWorkaround = false; 3619 3620 // setup some workarounds for "blueprint" theme 3621 if( pThemeName 3622 && ( strncasecmp( pThemeName, "blueprint", 9 ) == 0 3623 || strncasecmp( pThemeName, "Adwaita", 7 ) == 0 )) 3624 { 3625 bNeedButtonStyleAsEditBackgroundWorkaround = true; 3626 if( GetX11SalData()->GetDisplay()->GetServerVendor() == vendor_sun ) 3627 { 3628 // #i52570#, #i61532# workaround a weird paint issue; 3629 // on a Sunray Xserver sometimes painting buttons and edits 3630 // won't work when using the blueprint theme 3631 // not reproducible with simpler programs or other themes 3632 if( pThemeName && strncasecmp( pThemeName, "blueprint", 9 ) == 0 ) 3633 { 3634 bNeedPixmapPaint = true; 3635 bToolbarGripWorkaround = true; 3636 } 3637 } 3638 } 3639 // clean up 3640 g_value_unset( &aValue ); 3641 } 3642 3643 3644 /************************************************************************ 3645 * Create a GdkPixmap filled with the contents of an area of an Xlib window 3646 ************************************************************************/ 3647 3648 GdkPixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect ) 3649 { 3650 // Create a new pixmap to hold the composite of the window background and the control 3651 GdkPixmap * pPixmap = gdk_pixmap_new( GDK_DRAWABLE(GetGdkWindow()), srcRect.GetWidth(), srcRect.GetHeight(), -1 ); 3652 GdkGC * pPixmapGC = gdk_gc_new( pPixmap ); 3653 3654 if( !pPixmap || !pPixmapGC ) 3655 { 3656 if ( pPixmap ) 3657 g_object_unref( pPixmap ); 3658 if ( pPixmapGC ) 3659 g_object_unref( pPixmapGC ); 3660 std::fprintf( stderr, "salnativewidgets-gtk.cxx: could not get valid pixmap from screen\n" ); 3661 return( NULL ); 3662 } 3663 3664 // Copy the background of the screen into a composite pixmap 3665 CopyScreenArea( GetXDisplay(), 3666 GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(), 3667 gdk_x11_drawable_get_xid(pPixmap), 3668 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ), 3669 gdk_drawable_get_depth( GDK_DRAWABLE( pPixmap ) ), 3670 gdk_x11_gc_get_xgc(pPixmapGC), 3671 srcRect.Left(), srcRect.Top(), srcRect.GetWidth(), srcRect.GetHeight(), 0, 0 ); 3672 3673 g_object_unref( pPixmapGC ); 3674 return( pPixmap ); 3675 } 3676 3677 3678 3679 3680 /************************************************************************ 3681 * Copy an alpha pixmap to screen using a gc with clipping 3682 ************************************************************************/ 3683 3684 sal_Bool GtkSalGraphics::NWRenderPixmapToScreen( GdkPixmap* pPixmap, Rectangle dstRect ) 3685 { 3686 // The GC can't be null, otherwise we'd have no clip region 3687 GC aFontGC = GetFontGC(); 3688 if( aFontGC == NULL ) 3689 { 3690 std::fprintf(stderr, "salnativewidgets.cxx: no valid GC\n" ); 3691 return( sal_False ); 3692 } 3693 3694 if ( !pPixmap ) 3695 return( sal_False ); 3696 3697 // Copy the background of the screen into a composite pixmap 3698 CopyScreenArea( GetXDisplay(), 3699 GDK_DRAWABLE_XID(pPixmap), 3700 gdk_screen_get_number( gdk_drawable_get_screen( GDK_DRAWABLE(pPixmap) ) ), 3701 gdk_drawable_get_depth( GDK_DRAWABLE(pPixmap) ), 3702 GetDrawable(), m_nScreen, GetVisual().GetDepth(), 3703 aFontGC, 3704 0, 0, dstRect.GetWidth(), dstRect.GetHeight(), dstRect.Left(), dstRect.Top() ); 3705 3706 return( sal_True ); 3707 } 3708 3709 3710 /************************************************************************ 3711 * State conversion 3712 ************************************************************************/ 3713 static void NWConvertVCLStateToGTKState( ControlState nVCLState, 3714 GtkStateType* nGTKState, GtkShadowType* nGTKShadow ) 3715 { 3716 *nGTKShadow = GTK_SHADOW_OUT; 3717 *nGTKState = GTK_STATE_INSENSITIVE; 3718 3719 if ( nVCLState & CTRL_STATE_ENABLED ) 3720 { 3721 if ( nVCLState & CTRL_STATE_PRESSED ) 3722 { 3723 *nGTKState = GTK_STATE_ACTIVE; 3724 *nGTKShadow = GTK_SHADOW_IN; 3725 } 3726 else if ( nVCLState & CTRL_STATE_ROLLOVER ) 3727 { 3728 *nGTKState = GTK_STATE_PRELIGHT; 3729 *nGTKShadow = GTK_SHADOW_OUT; 3730 } 3731 else 3732 { 3733 *nGTKState = GTK_STATE_NORMAL; 3734 *nGTKShadow = GTK_SHADOW_OUT; 3735 } 3736 } 3737 } 3738 3739 /************************************************************************ 3740 * Set widget flags 3741 ************************************************************************/ 3742 static void NWSetWidgetState( GtkWidget* widget, ControlState nState, GtkStateType nGtkState ) 3743 { 3744 // Set to default state, then build up from there 3745 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_DEFAULT ); 3746 GTK_WIDGET_UNSET_FLAGS( widget, GTK_HAS_FOCUS ); 3747 GTK_WIDGET_UNSET_FLAGS( widget, GTK_SENSITIVE ); 3748 GTK_WIDGET_SET_FLAGS( widget, gWidgetDefaultFlags[(long)widget] ); 3749 3750 if ( nState & CTRL_STATE_DEFAULT ) 3751 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_DEFAULT ); 3752 if ( !GTK_IS_TOGGLE_BUTTON(widget) && (nState & CTRL_STATE_FOCUSED) ) 3753 GTK_WIDGET_SET_FLAGS( widget, GTK_HAS_FOCUS ); 3754 if ( nState & CTRL_STATE_ENABLED ) 3755 GTK_WIDGET_SET_FLAGS( widget, GTK_SENSITIVE ); 3756 gtk_widget_set_state( widget, nGtkState ); 3757 } 3758 3759 /************************************************************************ 3760 * Widget ensure functions - make sure cached objects are valid 3761 ************************************************************************/ 3762 3763 //------------------------------------- 3764 3765 static void NWAddWidgetToCacheWindow( GtkWidget* widget, int nScreen ) 3766 { 3767 NWFWidgetData& rData = gWidgetData[nScreen]; 3768 if ( !rData.gCacheWindow || !rData.gDumbContainer ) 3769 { 3770 if ( !rData.gCacheWindow ) 3771 { 3772 rData.gCacheWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL ); 3773 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen ); 3774 if( pScreen ) 3775 gtk_window_set_screen( GTK_WINDOW(rData.gCacheWindow), pScreen ); 3776 } 3777 if ( !rData.gDumbContainer ) 3778 rData.gDumbContainer = gtk_fixed_new(); 3779 gtk_container_add( GTK_CONTAINER(rData.gCacheWindow), rData.gDumbContainer ); 3780 gtk_widget_realize( rData.gDumbContainer ); 3781 gtk_widget_realize( rData.gCacheWindow ); 3782 } 3783 3784 gtk_container_add( GTK_CONTAINER(rData.gDumbContainer), widget ); 3785 gtk_widget_realize( widget ); 3786 gtk_widget_ensure_style( widget ); 3787 3788 // Store widget's default flags 3789 gWidgetDefaultFlags[ (long)widget ] = GTK_WIDGET_FLAGS( widget ); 3790 } 3791 3792 //------------------------------------- 3793 3794 static void NWEnsureGTKButton( int nScreen ) 3795 { 3796 if ( !gWidgetData[nScreen].gBtnWidget ) 3797 { 3798 gWidgetData[nScreen].gBtnWidget = gtk_button_new_with_label( "" ); 3799 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gBtnWidget, nScreen ); 3800 } 3801 } 3802 3803 //------------------------------------- 3804 3805 static void NWEnsureGTKRadio( int nScreen ) 3806 { 3807 if ( !gWidgetData[nScreen].gRadioWidget || !gWidgetData[nScreen].gRadioWidgetSibling ) 3808 { 3809 gWidgetData[nScreen].gRadioWidget = gtk_radio_button_new( NULL ); 3810 gWidgetData[nScreen].gRadioWidgetSibling = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(gWidgetData[nScreen].gRadioWidget) ); 3811 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidget, nScreen ); 3812 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gRadioWidgetSibling, nScreen ); 3813 } 3814 } 3815 3816 //------------------------------------- 3817 3818 static void NWEnsureGTKCheck( int nScreen ) 3819 { 3820 if ( !gWidgetData[nScreen].gCheckWidget ) 3821 { 3822 gWidgetData[nScreen].gCheckWidget = gtk_check_button_new(); 3823 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gCheckWidget, nScreen ); 3824 } 3825 } 3826 3827 //------------------------------------- 3828 3829 static void NWEnsureGTKScrollbars( int nScreen ) 3830 { 3831 if ( !gWidgetData[nScreen].gScrollHorizWidget ) 3832 { 3833 gWidgetData[nScreen].gScrollHorizWidget = gtk_hscrollbar_new( NULL ); 3834 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollHorizWidget, nScreen ); 3835 } 3836 3837 if ( !gWidgetData[nScreen].gScrollVertWidget ) 3838 { 3839 gWidgetData[nScreen].gScrollVertWidget = gtk_vscrollbar_new( NULL ); 3840 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrollVertWidget, nScreen ); 3841 } 3842 } 3843 3844 //------------------------------------- 3845 3846 static void NWEnsureGTKArrow( int nScreen ) 3847 { 3848 if ( !gWidgetData[nScreen].gArrowWidget || !gWidgetData[nScreen].gDropdownWidget ) 3849 { 3850 gWidgetData[nScreen].gDropdownWidget = gtk_toggle_button_new(); 3851 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gDropdownWidget, nScreen ); 3852 gWidgetData[nScreen].gArrowWidget = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT ); 3853 gtk_container_add( GTK_CONTAINER(gWidgetData[nScreen].gDropdownWidget), gWidgetData[nScreen].gArrowWidget ); 3854 gtk_widget_set_rc_style( gWidgetData[nScreen].gArrowWidget ); 3855 gtk_widget_realize( gWidgetData[nScreen].gArrowWidget ); 3856 } 3857 } 3858 3859 //------------------------------------- 3860 3861 static void NWEnsureGTKEditBox( int nScreen ) 3862 { 3863 if ( !gWidgetData[nScreen].gEditBoxWidget ) 3864 { 3865 gWidgetData[nScreen].gEditBoxWidget = gtk_entry_new(); 3866 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gEditBoxWidget, nScreen ); 3867 } 3868 } 3869 3870 //------------------------------------- 3871 3872 static void NWEnsureGTKSpinButton( int nScreen ) 3873 { 3874 if ( !gWidgetData[nScreen].gSpinButtonWidget ) 3875 { 3876 GtkAdjustment *adj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 1, 1, 1, 0) ); 3877 gWidgetData[nScreen].gSpinButtonWidget = gtk_spin_button_new( adj, 1, 2 ); 3878 3879 //Setting non-editable means it doesn't blink, so there's no timeouts 3880 //running around to nobble us 3881 gtk_editable_set_editable(GTK_EDITABLE(gWidgetData[nScreen].gSpinButtonWidget), false); 3882 3883 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gSpinButtonWidget, nScreen ); 3884 } 3885 } 3886 3887 //------------------------------------- 3888 3889 static void NWEnsureGTKNotebook( int nScreen ) 3890 { 3891 if ( !gWidgetData[nScreen].gNotebookWidget ) 3892 { 3893 gWidgetData[nScreen].gNotebookWidget = gtk_notebook_new(); 3894 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gNotebookWidget, nScreen ); 3895 } 3896 } 3897 3898 //------------------------------------- 3899 3900 static void NWEnsureGTKOptionMenu( int nScreen ) 3901 { 3902 if ( !gWidgetData[nScreen].gOptionMenuWidget ) 3903 { 3904 gWidgetData[nScreen].gOptionMenuWidget = gtk_option_menu_new(); 3905 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gOptionMenuWidget, nScreen ); 3906 } 3907 } 3908 3909 //------------------------------------- 3910 3911 static void NWEnsureGTKCombo( int nScreen ) 3912 { 3913 if ( !gWidgetData[nScreen].gComboWidget ) 3914 { 3915 gWidgetData[nScreen].gComboWidget = gtk_combo_new(); 3916 3917 // #i59129# Setting non-editable means it doesn't blink, so 3918 // there are no timeouts running around to nobble us 3919 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry), false); 3920 3921 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gComboWidget, nScreen ); 3922 // Must realize the ComboBox's children, since GTK 3923 // does not do this for us in GtkCombo::gtk_widget_realize() 3924 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->button ); 3925 gtk_widget_realize( GTK_COMBO(gWidgetData[nScreen].gComboWidget)->entry ); 3926 } 3927 } 3928 3929 //------------------------------------- 3930 3931 static void NWEnsureGTKScrolledWindow( int nScreen ) 3932 { 3933 if ( !gWidgetData[nScreen].gScrolledWindowWidget ) 3934 { 3935 GtkAdjustment *hadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 3936 GtkAdjustment *vadj = GTK_ADJUSTMENT( gtk_adjustment_new(0, 0, 0, 0, 0, 0) ); 3937 3938 gWidgetData[nScreen].gScrolledWindowWidget = gtk_scrolled_window_new( hadj, vadj ); 3939 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gScrolledWindowWidget, nScreen ); 3940 } 3941 } 3942 3943 //------------------------------------- 3944 3945 static void NWEnsureGTKToolbar( int nScreen ) 3946 { 3947 if( !gWidgetData[nScreen].gToolbarWidget ) 3948 { 3949 gWidgetData[nScreen].gToolbarWidget = gtk_toolbar_new(); 3950 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarWidget, nScreen ); 3951 gWidgetData[nScreen].gToolbarButtonWidget = gtk_button_new(); 3952 gWidgetData[nScreen].gToolbarToggleWidget = gtk_toggle_button_new(); 3953 3954 GtkReliefStyle aRelief = GTK_RELIEF_NORMAL; 3955 gtk_widget_ensure_style( gWidgetData[nScreen].gToolbarWidget ); 3956 gtk_widget_style_get( gWidgetData[nScreen].gToolbarWidget, 3957 "button_relief", &aRelief, 3958 (char *)NULL); 3959 3960 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarButtonWidget), aRelief ); 3961 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_FOCUS ); 3962 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarButtonWidget, GTK_CAN_DEFAULT ); 3963 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarButtonWidget, nScreen ); 3964 3965 gtk_button_set_relief( GTK_BUTTON(gWidgetData[nScreen].gToolbarToggleWidget), aRelief ); 3966 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_FOCUS ); 3967 GTK_WIDGET_UNSET_FLAGS( gWidgetData[nScreen].gToolbarToggleWidget, GTK_CAN_DEFAULT ); 3968 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gToolbarToggleWidget, nScreen ); 3969 } 3970 if( ! gWidgetData[nScreen].gHandleBoxWidget ) 3971 { 3972 gWidgetData[nScreen].gHandleBoxWidget = gtk_handle_box_new(); 3973 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHandleBoxWidget, nScreen ); 3974 } 3975 } 3976 3977 //------------------------------------- 3978 3979 static void NWEnsureGTKMenubar( int nScreen ) 3980 { 3981 if( !gWidgetData[nScreen].gMenubarWidget ) 3982 { 3983 gWidgetData[nScreen].gMenubarWidget = gtk_menu_bar_new(); 3984 gWidgetData[nScreen].gMenuItemMenubarWidget = gtk_menu_item_new_with_label( "b" ); 3985 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenubarWidget ), gWidgetData[nScreen].gMenuItemMenubarWidget ); 3986 gtk_widget_show( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3987 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gMenubarWidget, nScreen ); 3988 gtk_widget_show( gWidgetData[nScreen].gMenubarWidget ); 3989 3990 // do what NWAddWidgetToCacheWindow does except adding to def container 3991 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3992 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3993 3994 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenubarWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenubarWidget ); 3995 } 3996 } 3997 3998 static void NWEnsureGTKMenu( int nScreen ) 3999 { 4000 if( !gWidgetData[nScreen].gMenuWidget ) 4001 { 4002 gWidgetData[nScreen].gMenuWidget = gtk_menu_new(); 4003 gWidgetData[nScreen].gMenuItemMenuWidget = gtk_menu_item_new_with_label( "b" ); 4004 gWidgetData[nScreen].gMenuItemCheckMenuWidget = gtk_check_menu_item_new_with_label( "b" ); 4005 gWidgetData[nScreen].gMenuItemRadioMenuWidget = gtk_radio_menu_item_new_with_label( NULL, "b" ); 4006 gWidgetData[nScreen].gImageMenuItem = gtk_image_menu_item_new(); 4007 4008 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemMenuWidget ); 4009 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4010 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4011 gtk_menu_shell_append( GTK_MENU_SHELL( gWidgetData[nScreen].gMenuWidget ), gWidgetData[nScreen].gImageMenuItem ); 4012 4013 // do what NWAddWidgetToCacheWindow does except adding to def container 4014 gtk_widget_realize( gWidgetData[nScreen].gMenuWidget ); 4015 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuWidget ); 4016 4017 gtk_widget_realize( gWidgetData[nScreen].gMenuItemMenuWidget ); 4018 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemMenuWidget ); 4019 4020 gtk_widget_realize( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4021 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4022 4023 gtk_widget_realize( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4024 gtk_widget_ensure_style( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4025 4026 gtk_widget_realize( gWidgetData[nScreen].gImageMenuItem ); 4027 gtk_widget_ensure_style( gWidgetData[nScreen].gImageMenuItem ); 4028 4029 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuWidget ); 4030 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemMenuWidget ); 4031 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemCheckMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemCheckMenuWidget ); 4032 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gMenuItemRadioMenuWidget ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gMenuItemRadioMenuWidget ); 4033 gWidgetDefaultFlags[ (long)gWidgetData[nScreen].gImageMenuItem ] = GTK_WIDGET_FLAGS( gWidgetData[nScreen].gImageMenuItem ); 4034 } 4035 } 4036 4037 static void NWEnsureGTKTooltip( int nScreen ) 4038 { 4039 if( !gWidgetData[nScreen].gTooltipPopup ) 4040 { 4041 gWidgetData[nScreen].gTooltipPopup = gtk_window_new (GTK_WINDOW_POPUP); 4042 GdkScreen* pScreen = gdk_display_get_screen( gdk_display_get_default(), nScreen ); 4043 if( pScreen ) 4044 gtk_window_set_screen( GTK_WINDOW(gWidgetData[nScreen].gTooltipPopup), pScreen ); 4045 gtk_widget_set_name( gWidgetData[nScreen].gTooltipPopup, "gtk-tooltips"); 4046 gtk_widget_realize( gWidgetData[nScreen].gTooltipPopup ); 4047 gtk_widget_ensure_style( gWidgetData[nScreen].gTooltipPopup ); 4048 } 4049 } 4050 4051 static void NWEnsureGTKProgressBar( int nScreen ) 4052 { 4053 if( !gWidgetData[nScreen].gProgressBar ) 4054 { 4055 gWidgetData[nScreen].gProgressBar = gtk_progress_bar_new (); 4056 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gProgressBar, nScreen ); 4057 } 4058 } 4059 4060 static void NWEnsureGTKTreeView( int nScreen ) 4061 { 4062 if( !gWidgetData[nScreen].gTreeView ) 4063 { 4064 gWidgetData[nScreen].gTreeView = gtk_tree_view_new (); 4065 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gTreeView, nScreen ); 4066 } 4067 } 4068 4069 static void NWEnsureGTKSlider( int nScreen ) 4070 { 4071 if( !gWidgetData[nScreen].gHScale ) 4072 { 4073 gWidgetData[nScreen].gHScale = gtk_hscale_new_with_range(0, 10, 1); 4074 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gHScale, nScreen ); 4075 } 4076 if( !gWidgetData[nScreen].gVScale ) 4077 { 4078 gWidgetData[nScreen].gVScale = gtk_vscale_new_with_range(0, 10, 1); 4079 NWAddWidgetToCacheWindow( gWidgetData[nScreen].gVScale, nScreen ); 4080 } 4081 } 4082