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