File indexing completed on 2024-04-28 05:32:20
0001 /* 0002 this file is part of the oxygen gtk engine 0003 SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0004 SPDX-FileCopyrightText: 2010 Ruslan Kabatsayev <b7.10110111@gmail.com> 0005 0006 based on the Null Theme Engine for Gtk+. 0007 SPDX-FileCopyrightText: 2008 Robert Staudinger <robert.staudinger@gmail.com> 0008 0009 Icon rendering code from Walmis 0010 <http://gnome-look.org/content/show.php?content=77783&forumpage=3> 0011 0012 SPDX-License-Identifier: LGPL-2.0-or-later 0013 */ 0014 0015 #include "oxygenstylewrapper.h" 0016 0017 #include "oxygen.h" 0018 #include "oxygenanimations.h" 0019 #include "oxygenargbhelper.h" 0020 #include "oxygencairoutils.h" 0021 #include "oxygendefines.h" 0022 #include "oxygengtkcellinfo.h" 0023 #include "oxygengtkdetails.h" 0024 #include "oxygengtktypenames.h" 0025 #include "oxygengtkutils.h" 0026 #include "oxygenmetrics.h" 0027 #include "oxygenstyle.h" 0028 #include "oxygenwidgetexplorer.h" 0029 #include "oxygenwindowmanager.h" 0030 #include "oxygencolorutils.h" 0031 #include "config.h" 0032 0033 #include <iostream> 0034 namespace Oxygen 0035 { 0036 0037 //___________________________________________________________________________________________________________ 0038 GtkStyleClass* StyleWrapper::_parentClass = 0L; 0039 GTypeInfo StyleWrapper::_typeInfo; 0040 GType StyleWrapper::_type = 0L; 0041 XulInfo StyleWrapper::_xulInfo = XulInfo(); 0042 0043 //___________________________________________________________________________________________________________ 0044 static void draw_animated_button( 0045 GdkWindow* window, 0046 GdkRectangle* clipRect, 0047 GtkWidget* widget ) 0048 { 0049 0050 #if OXYGEN_DEBUG 0051 std::cerr 0052 << "Oxygen::draw_animated_button -" 0053 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 0054 << std::endl; 0055 #endif 0056 0057 ToolBarStateEngine& engine( Style::instance().animations().toolBarStateEngine() ); 0058 engine.registerWidget(widget); 0059 if( engine.animatedRectangleIsValid( widget ) ) 0060 { 0061 0062 const GdkRectangle& rect( engine.animatedRectangle( widget ) ); 0063 Style::instance().renderButtonSlab( window, clipRect, rect.x, rect.y, rect.width, rect.height, Flat|Hover ); 0064 0065 } else if( engine.isLocked( widget ) && gtk_widget_get_state( engine.widget( widget, AnimationCurrent ) ) != GTK_STATE_ACTIVE ) { 0066 0067 const GdkRectangle& rect( engine.rectangle( widget, AnimationCurrent ) ); 0068 Style::instance().renderButtonSlab( window, clipRect, rect.x, rect.y, rect.width, rect.height, Flat|Hover ); 0069 0070 } else if( engine.isAnimated( widget, AnimationPrevious ) && gtk_widget_get_state( engine.widget( widget, AnimationPrevious ) ) != GTK_STATE_ACTIVE ) { 0071 0072 const AnimationData data( engine.animationData( widget, AnimationPrevious ) ); 0073 const GdkRectangle& rect( engine.rectangle( widget, AnimationPrevious ) ); 0074 Style::instance().renderButtonSlab( window, clipRect, rect.x, rect.y, rect.width, rect.height, Flat|Hover, data ); 0075 0076 } 0077 0078 } 0079 0080 //___________________________________________________________________________________________________________ 0081 static void draw_flat_box( 0082 GtkStyle* style, 0083 GdkWindow* window, 0084 GtkStateType state, 0085 GtkShadowType shadow, 0086 GdkRectangle* clipRect, 0087 GtkWidget* widget, 0088 const char* detail, 0089 gint x, 0090 gint y, 0091 gint w, 0092 gint h ) 0093 { 0094 g_return_if_fail( style && window ); 0095 Style::instance().sanitizeSize( window, w, h ); 0096 0097 #if OXYGEN_DEBUG 0098 std::cerr 0099 << "Oxygen::draw_flat_box -" 0100 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 0101 << " state: " << Gtk::TypeNames::state( state ) 0102 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 0103 << " detail: " << (detail ? detail:"0x0" ) 0104 << std::endl; 0105 #endif 0106 0107 const Gtk::Detail d( detail ); 0108 0109 // Render tab background 0110 if(Style::instance().settings().applicationName().isOpenOffice() && GTK_IS_NOTEBOOK(widget)) 0111 { 0112 Style::instance().renderWindowBackground(window,widget,NULL,x,y,w,h); 0113 return; 0114 } 0115 0116 if( d.isBase() || d.isEventBox() || (d.isNull() && Gtk::g_object_is_a( G_OBJECT( widget ), "ShellWindow" ) ) ) 0117 { 0118 0119 // if background pixmap is provided, fallback to default painting 0120 if( style->bg_pixmap[state] ) 0121 { 0122 StyleWrapper::parentClass()->draw_flat_box( style, window, state, 0123 shadow, clipRect, widget, detail, 0124 x, y, w, h ); 0125 0126 return; 0127 } 0128 0129 // for opera, render flat background, always 0130 // (using renderwindowbackground will at best fall back to flat, at worse, render garbage) 0131 if( Style::instance().settings().applicationName().isOpera() ) 0132 { 0133 Style::instance().fill( window, clipRect, x, y, w, h, Palette::Window ); 0134 return; 0135 } 0136 0137 // do nothing for mozilla, acrobat, gnome applets, and other hint-specific windows 0138 if( 0139 Style::instance().settings().applicationName().useFlatBackground( widget ) || 0140 Gtk::gtk_widget_is_applet( widget ) || 0141 Gtk::gdk_window_nobackground( window ) ) 0142 { return; } 0143 0144 // if background has been modified, simply fill with background color 0145 /* 0146 note: this is an inconsistent design choice. In principle we could just 0147 - register the widgets to the relevant engines as below 0148 - pass the modified color to renderWindowBackground 0149 */ 0150 if( Gtk::gtk_widget_style_is_modified( widget, state, GTK_RC_BG ) ) 0151 { 0152 Style::instance().animations().flatWidgetEngine().registerFlatWidget( widget ); 0153 Style::instance().fill( window, clipRect, x, y, w, h, Gtk::gdk_get_color( style->bg[state] ) ); 0154 return; 0155 } 0156 0157 // register to relevant engines 0158 if( GTK_IS_WINDOW( widget ) ) 0159 { 0160 0161 Style::instance().animations().mainWindowEngine().registerWidget( widget ); 0162 0163 } else if( GtkWidget* parent = Gtk::gtk_parent_scrolled_window( widget ) ) { 0164 0165 Style::instance().animations().scrollBarEngine().registerScrolledWindow( parent ); 0166 0167 } 0168 0169 // change gtk dialog button order 0170 GtkWidget *toplevel = gtk_widget_get_toplevel( widget ); 0171 if( GTK_IS_DIALOG( toplevel ) ) 0172 { Style::instance().animations().dialogEngine().registerWidget( toplevel ); } 0173 0174 // render background gradient 0175 StyleOptions options; 0176 options._customColors.insert( Palette::Window, Gtk::gdk_get_color( style->bg[state] ) ); 0177 const bool success( Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h, options ) ); 0178 0179 // if widget has flat parent, store in flatWidget engine so that children gets the right background nonetheless 0180 if( success && Style::instance().animations().flatWidgetEngine().flatParent( widget ) ) 0181 { Style::instance().animations().flatWidgetEngine().registerPaintWidget( widget ); } 0182 0183 // register to window manager 0184 if( success && 0185 Gtk::gdk_window_is_base( window ) && 0186 !( GTK_IS_EVENT_BOX( widget ) && 0187 !gtk_event_box_get_above_child( GTK_EVENT_BOX( widget ) ) ) ) 0188 { 0189 BackgroundHints hints( BackgroundGradient ); 0190 if( Style::instance().hasBackgroundSurface() ) hints |= BackgroundPixmap; 0191 Style::instance().animations().backgroundHintEngine().registerWidget( widget, hints ); 0192 } 0193 0194 // possible groupbox background 0195 if( d.isEventBox() && Gtk::gtk_parent_groupbox( widget ) ) 0196 { 0197 options |= Blend; 0198 Style::instance().renderGroupBoxBackground( window, widget, clipRect, x, y, w, h, options ); 0199 } 0200 0201 // also draw possible animated tool button 0202 if( !d.isNull() ) 0203 { draw_animated_button( window, clipRect, widget ); } 0204 0205 return; 0206 0207 } else if( d.isViewportBin() ) { 0208 0209 // do nothing for gnome applets 0210 if( Gtk::gtk_widget_is_applet( widget ) ) return; 0211 0212 // for modified bg, fill with flat custom color 0213 if( Gtk::gtk_widget_style_is_modified( widget, state, GTK_RC_BG ) ) 0214 { 0215 0216 Style::instance().fill( window, clipRect, x, y, w, h, Gtk::gdk_get_color( style->bg[state] ) ); 0217 0218 } else if( 0219 Style::instance().settings().applicationName().useFlatBackground( widget ) || 0220 !Style::instance().animations().backgroundHintEngine().contains( gtk_widget_get_toplevel( widget ) ) ) 0221 { 0222 0223 // for mozilla and openoffice fill with flat color 0224 Style::instance().fill( window, clipRect, x, y, w, h, Palette::Window ); 0225 return; 0226 0227 } else { 0228 0229 // make sure that widget is registered to scrolledBarEngine, 0230 // so that background gets updated properly 0231 if( GtkWidget* parent = Gtk::gtk_parent_scrolled_window( widget ) ) 0232 { Style::instance().animations().scrollBarEngine().registerScrolledWindow( parent ); } 0233 0234 // render background gradient 0235 Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h ); 0236 0237 } 0238 0239 // also draw possible animated tool button 0240 draw_animated_button( window, clipRect, widget ); 0241 0242 return; 0243 0244 } else if( d.isTrough() ) { 0245 0246 if( GTK_IS_PROGRESS_BAR( widget ) ) 0247 { 0248 if( Style::instance().settings().applicationName().isOpenOffice() ) 0249 { 0250 StyleOptions options; 0251 if( Gtk::gtk_widget_is_vertical( widget ) ) options |= Vertical; 0252 Style::instance().renderProgressBarHole( window, clipRect, x,y,w,h, options ); 0253 } 0254 return; 0255 } 0256 0257 } else if( d.isTooltip() && Style::instance().settings().tooltipDrawStyledFrames() ) { 0258 0259 // mozilla and openoffice get square non Argb tooltips no matter what 0260 if( 0261 Style::instance().settings().applicationName().isOpenOffice() || 0262 Style::instance().settings().applicationName().isXul() ) 0263 { 0264 Style::instance().renderTooltipBackground( window, clipRect, x, y, w, h, StyleOptions() ); 0265 return; 0266 } 0267 0268 StyleOptions options( Round ); 0269 if( Gtk::gtk_widget_has_rgba( widget ) ) options |= Alpha; 0270 0271 if( GDK_IS_WINDOW( window ) ) 0272 { 0273 WidgetSizeEngine& engine( Style::instance().animations().widgetSizeEngine() ); 0274 engine.registerWidget( widget ); 0275 if( engine.update(widget) ) 0276 { 0277 Style::instance().adjustMask( widget, engine.width( widget ), engine.height( widget ), engine.alpha( widget ) ); 0278 Style::instance().setWindowBlur( widget, engine.alpha( widget ) ); 0279 } 0280 } 0281 0282 Style::instance().renderTooltipBackground( window, clipRect, x, y, w, h, options ); 0283 return; 0284 0285 } else if( 0286 d.isCheckButton() || 0287 d.isRadioButton() || 0288 d.isExpander() ) { 0289 0290 return; 0291 0292 } else if( d.isCell() ) { 0293 0294 StyleOptions options( widget, state ); 0295 0296 // select palete colorgroup for cell background 0297 Palette::Group group( Palette::Active ); 0298 if( options & Disabled ) group = Palette::Disabled; 0299 else if( !(options&Focus) ) group = Palette::Inactive; 0300 0301 // render background 0302 // render "normal" background 0303 bool drawTreeLines( true ); 0304 ColorUtils::Rgba background; 0305 0306 if( Gtk::gtk_widget_style_is_modified( widget, GTK_STATE_NORMAL, GTK_RC_BASE ) ) 0307 { 0308 0309 /* 0310 do not draw tree lines when a custom background color is set 0311 since it usually does not work for non-selected items 0312 */ 0313 drawTreeLines = false; 0314 0315 // assign background 0316 background = Gtk::gdk_get_color( style->base[GTK_STATE_NORMAL] ); 0317 0318 } else if( widget && std::string( G_OBJECT_TYPE_NAME( widget ) ).find( "MiroTreeView" ) != std::string::npos ) { 0319 0320 drawTreeLines = false; 0321 0322 } else if( d.isCellEven() || Gtk::gtk_combobox_is_tree_view( widget ) ) { 0323 0324 background = Style::instance().settings().palette().color( group, Palette::Base ); 0325 0326 } else if( d.isCellOdd() ) { 0327 0328 background = Style::instance().settings().palette().color( group, Palette::BaseAlternate ); 0329 0330 } 0331 0332 if( background.isValid() ) Style::instance().fill( window, clipRect, x, y, w, h, background ); 0333 if( Gtk::gtk_combobox_is_tree_view( widget ) ) 0334 { 0335 0336 // draw flat selection in combobox list 0337 if(state==GTK_STATE_SELECTED) 0338 { 0339 ColorUtils::Rgba selection( Style::instance().settings().palette().color( Palette::Active, Palette::Selected ) ); 0340 Style::instance().fill( window, clipRect, x, y, w, h, selection ); 0341 } 0342 0343 } else { 0344 0345 const bool reversed( Gtk::gtk_widget_layout_is_reversed( widget ) ); 0346 0347 // draw rounded selection in normal list, 0348 // and detect hover 0349 bool forceCellStart( false ); 0350 bool forceCellEnd( false ); 0351 if( GTK_IS_TREE_VIEW( widget ) ) 0352 { 0353 0354 GtkTreeView* treeView( GTK_TREE_VIEW( widget ) ); 0355 Gtk::CellInfo cellInfo( treeView, x, y, w, h ); 0356 0357 Style::instance().animations().treeViewEngine().registerWidget( widget ); 0358 if( Style::instance().animations().treeViewEngine().isDirty( widget ) ) 0359 { Style::instance().animations().treeViewEngine().updateHoveredCell( widget ); } 0360 0361 if( cellInfo.isValid() && Style::instance().animations().treeViewEngine().isCellHovered( widget, cellInfo ) ) 0362 { options |= Hover; } 0363 0364 const bool showExpanders( gtk_tree_view_get_show_expanders( treeView ) ); 0365 if( showExpanders && cellInfo.isValid() && cellInfo.isExpanderColumn( treeView )) 0366 { 0367 0368 // tree lines 0369 if( drawTreeLines && Style::instance().settings().viewDrawTreeBranchLines() && showExpanders ) 0370 { 0371 0372 // generate flags from cell info 0373 Gtk::CellInfoFlags cellFlags( treeView, cellInfo ); 0374 if( reversed ) cellFlags._flags |= Gtk::CellInfoFlags::Reversed; 0375 0376 // set proper options 0377 StyleOptions options( widget, state, shadow ); 0378 0379 // and render 0380 Style::instance().renderTreeLines( window, clipRect, x, y, w, h, cellFlags, options ); 0381 0382 } 0383 0384 // change selection rect so that it does not overlap with expander 0385 if( reversed ) forceCellEnd = true; 0386 else forceCellStart = true; 0387 0388 forceCellStart = true; 0389 if( options&(Selected|Hover) ) 0390 { 0391 0392 // get expander size from widget 0393 int depth( cellInfo.depth() ); 0394 int expanderSize(0); 0395 gtk_widget_style_get( widget, "expander-size", &expanderSize, NULL ); 0396 0397 int offset( 3 + expanderSize * depth + ( 4 + gtk_tree_view_get_level_indentation( treeView ) )*(depth-1) ); 0398 0399 if( reversed ) w-= offset; 0400 else { 0401 0402 x += offset; 0403 w -= offset; 0404 0405 } 0406 0407 } 0408 0409 } else if( showExpanders && (options&(Selected|Hover)) && cellInfo.isValid() && cellInfo.isLeftOfExpanderColumn( treeView ) ) { 0410 0411 if( reversed ) forceCellStart = true; 0412 else forceCellEnd = true; 0413 0414 } 0415 0416 // check if column is last 0417 if( (options&(Selected|Hover)) && cellInfo.isValid() ) 0418 { 0419 if(cellInfo.isLastVisibleColumn( treeView )) 0420 { 0421 if( reversed ) forceCellStart = true; 0422 else forceCellEnd = true; 0423 } 0424 if(cellInfo.isFirstVisibleColumn( treeView )) 0425 { 0426 if( reversed ) forceCellEnd = true; 0427 else forceCellStart = true; 0428 } 0429 } 0430 0431 } 0432 0433 if( options & (Selected|Hover) ) 0434 { 0435 0436 TileSet::Tiles tiles( TileSet::Center ); 0437 if( d.isCellStart() ) tiles |= TileSet::Left; 0438 else if( d.isCellEnd() ) tiles |= TileSet::Right; 0439 else if( !d.isCellMiddle() ) tiles = TileSet::Horizontal; 0440 0441 if( forceCellStart ) tiles |= TileSet::Left; 0442 if( forceCellEnd ) tiles |= TileSet::Right; 0443 0444 Style::instance().renderSelection( window, clipRect, x, y, w, h, tiles, options ); 0445 0446 } 0447 0448 } 0449 0450 return; 0451 0452 0453 } else if( d.isIconViewItem() ) { 0454 0455 StyleOptions options( widget, state ); 0456 if( options&(Selected|Hover) ) 0457 { 0458 // adjustments have been tuned empirically 0459 Style::instance().renderSelection( window, clipRect, x, y, w, h, TileSet::Full, options ); 0460 } 0461 return; 0462 0463 } else if( d.isEntryBg() && !Style::instance().settings().applicationName().isXul( widget ) ) { 0464 0465 // FIXME: how to detect Chromium address bar more correctly? 0466 const bool isChromeAddressBar( widget && 0467 GTK_IS_HBOX(widget) && 0468 Style::instance().settings().applicationName().isGoogleChrome() ); 0469 if(Style::instance().settings().applicationName().isOpenOffice()) 0470 { 0471 const char* ver=Style::instance().settings().applicationName().versionString(); 0472 // If ver appears non-NULL, we have at least LibO 4.0. 0473 // For now, it's enough to differentiate old version from new. 0474 // If something gets broken in newer version, we'll have to parse ver. 0475 if(ver) 0476 { 0477 x-=3; 0478 w+=6; 0479 } 0480 else 0481 { 0482 x+=2; 0483 w-=4; 0484 y+=1; 0485 h-=2; 0486 } 0487 } 0488 0489 StyleOptions options( widget, state, shadow ); 0490 if( 0491 !Style::instance().settings().applicationName().isGoogleChrome() && 0492 !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 0493 { options |= NoFill; } 0494 0495 // calculate proper offsets so that the glow/shadow match parent frame 0496 const int sideMargin( isChromeAddressBar ? 0 : std::max( 0, style->xthickness - 2 ) ); 0497 const int xOffset( style->xthickness + 1 - sideMargin ); 0498 0499 // adjust horizontal positioning and width 0500 x -= xOffset; 0501 w += 2*xOffset; 0502 0503 if( GtkWidget* parent = Gtk::gtk_parent_combobox_entry( widget ) ) 0504 { 0505 0506 // check if parent is in style map 0507 Style::instance().animations().comboBoxEntryEngine().registerWidget( parent ); 0508 Style::instance().animations().comboBoxEntryEngine().setEntry( parent, widget ); 0509 Style::instance().animations().comboBoxEntryEngine().setEntryFocus( parent, options & Focus ); 0510 0511 if( state != GTK_STATE_INSENSITIVE ) 0512 { 0513 if( Style::instance().animations().comboBoxEntryEngine().hasFocus( parent ) ) options |= Focus; 0514 else options &= ~Focus; 0515 0516 if( Style::instance().animations().comboBoxEntryEngine().hovered( parent ) ) options |= Hover; 0517 else options &= ~Hover; 0518 } 0519 0520 /* 0521 for some reason, adjusting y and h using ythickness does not work for combobox_entry 0522 one need to use parent allocation instead 0523 */ 0524 const GtkAllocation allocation( Gtk::gtk_widget_get_allocation( parent ) ); 0525 y -= (allocation.height-h + 1)/2; 0526 h = allocation.height; 0527 0528 // partial highlight 0529 TileSet::Tiles tiles( TileSet::Ring ); 0530 const AnimationData data( Style::instance().animations().widgetStateEngine().get( parent, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 0531 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 0532 { 0533 0534 // hide left part and increase width 0535 tiles &= ~TileSet::Left; 0536 Style::instance().renderHoleBackground( window, widget, clipRect, x-sideMargin-2, y, w+2*sideMargin+2, h, TileSet::Full, sideMargin ); 0537 Style::instance().renderHole( window, clipRect, x-9, y, w+9, h, options, data, tiles ); 0538 0539 } else { 0540 0541 // hide right part and increase width 0542 tiles &= ~TileSet::Right; 0543 Style::instance().renderHoleBackground( window, widget, clipRect, x-sideMargin, y, w+2*sideMargin+2, h, TileSet::Full, sideMargin ); 0544 Style::instance().renderHole( window, clipRect, x, y, w+9, h, options, data, tiles ); 0545 0546 } 0547 0548 } else if( GTK_IS_SPIN_BUTTON( widget ) ) { 0549 0550 // do nothing for frameless entries 0551 if( !gtk_entry_get_has_frame( GTK_ENTRY( widget ) ) ) 0552 { return; } 0553 0554 const int yOffset( style->ythickness + 1 ); 0555 0556 // there is no need to render anything if both offsets are larger than 4 0557 if( xOffset > 4 && yOffset > 4 ) return; 0558 0559 // adjust vertical positioning and height 0560 y -= yOffset; 0561 h += 2*yOffset; 0562 0563 // for libreoffice do nothing 0564 if( Style::instance().settings().applicationName().isOpenOffice( widget ) ) 0565 { return; } 0566 0567 if( 0568 Style::instance().animations().hoverEngine().contains( widget ) && 0569 Style::instance().animations().hoverEngine().hovered( widget ) ) 0570 { options |= Hover; } 0571 0572 // plain background 0573 ColorUtils::Rgba background( Gtk::gdk_get_color( style->base[gtk_widget_get_state(widget)] ) ); 0574 Style::instance().fill( window, clipRect, x, y, w, h, background ); 0575 0576 // animation data 0577 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 0578 0579 // hole 0580 TileSet::Tiles tiles( TileSet::Ring ); 0581 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 0582 { 0583 0584 // hide right part and adjust width 0585 tiles &= ~TileSet::Left; 0586 Style::instance().renderHoleBackground( window, widget, clipRect, x-2-sideMargin, y, w+2*sideMargin+2, h, tiles, sideMargin ); 0587 Style::instance().renderHole( window, clipRect, x-7, y, w+7, h, options, data, tiles ); 0588 0589 } else { 0590 0591 // hide right part and adjust width 0592 tiles &= ~TileSet::Right; 0593 Style::instance().renderHoleBackground( window, widget, clipRect, x-sideMargin, y, w+2*sideMargin, h, tiles, sideMargin ); 0594 Style::instance().renderHole( window, clipRect, x, y, w+7, h, options, data, tiles ); 0595 0596 } 0597 0598 } else { 0599 0600 // do nothing for frameless entries 0601 if( GTK_IS_ENTRY( widget ) && !gtk_entry_get_has_frame( GTK_ENTRY( widget ) ) ) 0602 { return; } 0603 0604 const int yOffset( style->ythickness + 1 ); 0605 0606 // there is no need to render anything if both offsets are larger than 4 0607 if( xOffset > 4 && yOffset > 4 ) return; 0608 0609 // adjust vertical positioning and height 0610 y -= yOffset; 0611 h += 2*yOffset; 0612 0613 if( 0614 Style::instance().animations().hoverEngine().contains( widget ) && 0615 Style::instance().animations().hoverEngine().hovered( widget ) ) 0616 { options |= Hover; } 0617 0618 // compare painting rect to widget rect, to decide if some sides are to be masked 0619 TileSet::Tiles tiles = TileSet::Ring; 0620 GdkWindow* widgetWindow( gtk_widget_get_window( widget ) ); 0621 if( widget && window != widgetWindow && GDK_IS_WINDOW( window ) && widgetWindow == gdk_window_get_parent( window ) ) 0622 { 0623 0624 const int widgetWindowWidth( Gtk::gtk_widget_get_allocation( widget ).width ); 0625 int localWindowX( 0 ); 0626 int localWindowWidth( 0 ); 0627 gdk_window_get_position( window, &localWindowX, 0L ); 0628 gdk_window_get_size( window, &localWindowWidth, 0L ); 0629 0630 // remove left border if needed 0631 if( localWindowX > 5 ) 0632 { 0633 tiles &= ~TileSet::Left; 0634 x -= 9; 0635 w += 9; 0636 } 0637 0638 // remove right border if needed 0639 if( localWindowX + localWindowWidth < widgetWindowWidth - 5 ) 0640 { 0641 tiles &= ~TileSet::Right; 0642 w += 9; 0643 } 0644 0645 } 0646 0647 // render hole 0648 Style::instance().renderHoleBackground( window, widget, clipRect, x-sideMargin, y, w+2*sideMargin, h, TileSet::Full, sideMargin ); 0649 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 0650 Style::instance().renderHole( window, clipRect, x, y, w, h, options, data, tiles ); 0651 0652 } 0653 0654 return; 0655 0656 } 0657 0658 // call parent method if reaching here 0659 StyleWrapper::parentClass()->draw_flat_box( style, window, state, 0660 shadow, clipRect, widget, detail, 0661 x, y, w, h ); 0662 0663 } 0664 0665 //_____________________________________________________________________________________ 0666 Cairo::Surface processTabCloseButton(GtkWidget* widget, GtkStateType state) 0667 { 0668 0669 #if OXYGEN_DEBUG 0670 std::cerr << "Oxygen::processTabCloseButton("<<widget<<","<<state <<")"<< std::endl; 0671 #endif 0672 0673 if(!widget) 0674 return 0L; 0675 0676 switch (state) 0677 { 0678 case GTK_STATE_NORMAL: 0679 { 0680 0681 // check if our button is on active page and if not, make it gray 0682 GtkNotebook* notebook=GTK_NOTEBOOK(Gtk::gtk_parent_notebook(widget)); 0683 GtkWidget* page=gtk_notebook_get_nth_page(notebook,gtk_notebook_get_current_page(notebook)); 0684 if( !page ) break; 0685 0686 GtkWidget* tabLabel=gtk_notebook_get_tab_label(notebook,page); 0687 if( !tabLabel ) break; 0688 0689 if( !Gtk::gtk_widget_is_parent( widget, tabLabel ) ) return Style::instance().tabCloseButton( Disabled ); 0690 else return Style::instance().tabCloseButton( StyleOptions() ); 0691 0692 } 0693 0694 break; 0695 0696 case GTK_STATE_ACTIVE: return Style::instance().tabCloseButton( Focus ); 0697 case GTK_STATE_PRELIGHT: return Style::instance().tabCloseButton( Hover ); 0698 default: break; 0699 0700 } 0701 0702 return 0L; 0703 0704 } 0705 0706 //___________________________________________________________________________________________________________ 0707 static void draw_box( GtkStyle* style, 0708 GdkWindow* window, 0709 GtkStateType state, 0710 GtkShadowType shadow, 0711 GdkRectangle* clipRect, 0712 GtkWidget* widget, 0713 const gchar* detail, 0714 gint x, 0715 gint y, 0716 gint w, 0717 gint h ) 0718 { 0719 g_return_if_fail( style && window ); 0720 0721 #if OXYGEN_DEBUG 0722 std::cerr 0723 << "Oxygen::draw_box -" 0724 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 0725 << " state: " << Gtk::TypeNames::state( state ) 0726 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 0727 << " detail: " << (detail ? detail:"0x0" ) 0728 << " rect: " << Gtk::gdk_rectangle( x, y, w, h ) 0729 << " thickness: " << style->xthickness << "," << style->ythickness 0730 << std::endl; 0731 #endif 0732 0733 Style::instance().sanitizeSize( window, w, h ); 0734 const Gtk::Detail d( detail ); 0735 0736 // Don't draw anything for OpenOffice or steppers will look like slabs. 0737 if( d.isStepper() && Style::instance().settings().applicationName().isOpenOffice( widget )) 0738 { return; } 0739 0740 // Don't render window bg here because it's redundant and leads to problems with bg gradient behind buttons 0741 if( GTK_IS_WINDOW(widget) && Style::instance().settings().applicationName().isOpenOffice( widget )) 0742 { return; } 0743 0744 GtkWidget* parent(0L); 0745 if( d.isInfoBar() ) 0746 { 0747 0748 Style::instance().renderInfoBar( window, clipRect, x, y, w, h, Gtk::gdk_get_color( style->bg[state] ) ); 0749 0750 0751 } else if( d.isButton() || d.isOptionMenu() || d.isToggleButton() ) { 0752 0753 // pathbar buttons 0754 if( Gtk::gtk_button_is_in_path_bar(widget) ) 0755 { 0756 0757 // https://bugzilla.gnome.org/show_bug.cgi?id=635511 0758 std::string name(G_OBJECT_TYPE_NAME( gtk_widget_get_parent( widget ) ) ); 0759 Style::instance().animations().hoverEngine().registerWidget( widget ); 0760 0761 // only two style options possible: hover or don't draw 0762 StyleOptions options; 0763 const bool reversed( Gtk::gtk_widget_layout_is_reversed( widget ) ); 0764 const bool isLast( Gtk::gtk_path_bar_button_is_last( widget ) ); 0765 if(state!=GTK_STATE_NORMAL && state!=GTK_STATE_INSENSITIVE) 0766 { 0767 if( !(state==GTK_STATE_ACTIVE && !Style::instance().animations().hoverEngine().hovered( widget ) ) ) 0768 { 0769 options |= Hover; 0770 if( isLast ) 0771 { 0772 if( reversed ) 0773 { 0774 0775 x += 10; 0776 w-=10; 0777 0778 } else w -= 10; 0779 } 0780 0781 Style::instance().renderSelection(window,clipRect,x,y,w,h,TileSet::Full,options); 0782 } 0783 } 0784 0785 if( GTK_IS_TOGGLE_BUTTON(widget) && !isLast ) 0786 { 0787 0788 options |= Contrast; 0789 0790 if( reversed ) Style::instance().renderArrow(window,NULL,GTK_ARROW_LEFT, x+3,y,5,h,QtSettings::ArrowNormal, options, Palette::WindowText); 0791 else Style::instance().renderArrow(window,NULL,GTK_ARROW_RIGHT,x+w-8,y,5,h,QtSettings::ArrowNormal, options, Palette::WindowText); 0792 0793 } 0794 0795 return; 0796 0797 } 0798 0799 // treeview headers 0800 if( Gtk::gtk_button_is_header( widget ) ) 0801 { 0802 0803 // register to scrolled window engine if any 0804 if( 0805 ( parent = Gtk::gtk_parent_scrolled_window( widget ) ) && 0806 Style::instance().animations().scrolledWindowEngine().contains( parent ) 0807 ) 0808 { Style::instance().animations().scrolledWindowEngine().registerChild( parent, widget ); } 0809 0810 // treevew header 0811 Style::instance().renderHeaderBackground( window, clipRect, x, y, w, h ); 0812 return; 0813 0814 } 0815 0816 // combobox entry buttons 0817 if( ( parent = Gtk::gtk_parent_combobox_entry( widget ) ) ) { 0818 0819 // combobox entry buttons 0820 // keep track of whether button is active (pressed-down) or pre-lighted 0821 const bool buttonActive( state == GTK_STATE_ACTIVE || state == GTK_STATE_PRELIGHT ); 0822 0823 // get the state from the combobox 0824 /* this fixes rendering issues when the arrow is disabled, but not the entry */ 0825 state = gtk_widget_get_state(parent); 0826 0827 /* 0828 editable combobox button get a hole (with left corner hidden), and a background 0829 that match the corresponding text entry background. 0830 */ 0831 0832 StyleOptions options( widget, state, shadow ); 0833 if( 0834 !Style::instance().settings().applicationName().isOpenOffice( widget ) && 0835 !Style::instance().settings().applicationName().isGoogleChrome() ) 0836 { options |= NoFill; } 0837 0838 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 0839 { options |= Blend; } 0840 0841 // focus handling 0842 Style::instance().animations().comboBoxEntryEngine().registerWidget( parent ); 0843 Style::instance().animations().comboBoxEntryEngine().setButton( parent, widget ); 0844 0845 // background 0846 int sideMargin( 0 ); 0847 { 0848 GtkWidget* entry( gtk_bin_get_child( GTK_BIN( parent ) ) ); 0849 GtkStyle* style( gtk_widget_get_style( entry ) ); 0850 sideMargin = std::max( 0, style->xthickness - 2 ); 0851 ColorUtils::Rgba background( Gtk::gdk_get_color( style->base[state] ) ); 0852 Style::instance().fill( window, clipRect, x, y, w, h, background ); 0853 } 0854 0855 // update option accordingly 0856 if( state == GTK_STATE_INSENSITIVE ) options &= ~(Hover|Focus); 0857 else { 0858 0859 Style::instance().animations().comboBoxEntryEngine().setButtonFocus( parent, options & Focus ); 0860 if( Style::instance().animations().comboBoxEntryEngine().hasFocus( parent ) ) options |= Focus; 0861 else options &= ~Focus; 0862 0863 // properly set button hover state. Pressed-down buttons are marked hovered, consistently with Qt 0864 Style::instance().animations().comboBoxEntryEngine().setButtonHovered( parent, buttonActive ); 0865 if( Style::instance().animations().comboBoxEntryEngine().hovered( parent ) ) options |= Hover; 0866 else options &= ~Hover; 0867 0868 } 0869 0870 // render 0871 TileSet::Tiles tiles( TileSet::Ring); 0872 const AnimationData data( Style::instance().animations().widgetStateEngine().get( parent, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 0873 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 0874 { 0875 0876 // hide right and adjust width 0877 tiles &= ~TileSet::Right; 0878 Style::instance().renderHoleBackground( window, widget, clipRect, x-1, y, w+6, h, tiles, sideMargin ); 0879 0880 x += sideMargin; 0881 w -= sideMargin; 0882 Style::instance().renderHole( window, clipRect, x-1, y, w+8, h, options, data, tiles ); 0883 0884 } else { 0885 0886 // hide left and adjust width 0887 tiles &= ~TileSet::Left; 0888 Style::instance().renderHoleBackground( window, widget, clipRect, x-5, y, w+6, h, tiles, sideMargin ); 0889 0890 w -= sideMargin; 0891 Style::instance().renderHole( window, clipRect, x-7, y, w+8, h, options, data, tiles ); 0892 0893 } 0894 0895 return; 0896 0897 } 0898 0899 // combobox buttons 0900 if( 0901 ( parent = Gtk::gtk_parent_combobox( widget ) ) && 0902 !Style::instance().settings().applicationName().isXul( widget ) && 0903 Gtk::gtk_combobox_appears_as_list( parent ) 0904 ) 0905 { 0906 0907 { 0908 // Set minimum combobox button height if it's smaller 0909 GtkAllocation alloc; 0910 gtk_widget_get_allocation(widget,&alloc); 0911 gtk_widget_get_size_request(widget,&alloc.width,NULL); 0912 if(alloc.height<22) 0913 gtk_widget_set_size_request(widget,alloc.width,22); 0914 } 0915 // combobox buttons 0916 const bool reversed( Gtk::gtk_widget_layout_is_reversed( widget ) ); 0917 0918 StyleOptions options( widget, state, shadow ); 0919 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 0920 { options |= Blend; } 0921 0922 Style::instance().animations().comboBoxEngine().registerWidget( parent ); 0923 Style::instance().animations().comboBoxEngine().setButton( parent, widget ); 0924 Style::instance().animations().comboBoxEngine().setButtonFocus( parent, options & Focus ); 0925 0926 if( Gtk::gtk_combobox_has_frame( parent ) ) 0927 { 0928 if( Style::instance().animations().comboBoxEngine().hovered( parent ) ) options |= Hover; 0929 0930 // tiles 0931 TileSet::Tiles tiles( TileSet::Ring ); 0932 0933 // animation state 0934 const AnimationData data( (options&Sunken) ? 0935 AnimationData(): 0936 Style::instance().animations().widgetStateEngine().get( parent, options ) ); 0937 0938 if( reversed ) 0939 { 0940 0941 tiles &= ~TileSet::Right; 0942 Style::instance().renderButtonSlab( window, clipRect, x, y, w+7, h, options, data, tiles ); 0943 0944 } else { 0945 0946 tiles &= ~TileSet::Left; 0947 Style::instance().renderButtonSlab( window, clipRect, x-7, y, w+7, h, options, data, tiles ); 0948 0949 } 0950 0951 return; 0952 0953 } else { 0954 0955 options |= Flat; 0956 if( Style::instance().animations().comboBoxEngine().hovered( parent ) ) options |= Hover; 0957 if( reversed ) Style::instance().renderButtonSlab( window, clipRect, x+1, y, w, h, options ); 0958 else Style::instance().renderButtonSlab( window, clipRect, x-1, y, w, h, options ); 0959 return; 0960 0961 } 0962 0963 } 0964 0965 // combo button 0966 if( ( parent = Gtk::gtk_parent_combo( widget ) ) ) 0967 { 0968 0969 StyleOptions options( widget, state, shadow ); 0970 if(!Style::instance().settings().applicationName().useFlatBackground(widget)) 0971 { options |= Blend; } 0972 0973 if( Style::instance().settings().applicationName().isOpenOffice( widget ) ) 0974 { 0975 0976 // Hover doesn't work correctly in OpenOffice, so disable it 0977 options &= ~(Hover|Focus); 0978 TileSet::Tiles tiles( TileSet::Full ); 0979 tiles &= ( ~TileSet::Left ); 0980 Style::instance().renderHole( window, clipRect, x-10, y-1, w+11, h+2, options, tiles ); 0981 return; 0982 0983 } else { 0984 0985 /* 0986 make button flat; disable focus and hover 0987 (this is handled when rendering the arrow 0988 This doesn't work for OpenOffice. 0989 */ 0990 options |= Flat; 0991 options &= ~(Hover|Focus); 0992 Style::instance().animations().comboEngine().registerWidget( parent ); 0993 return; 0994 0995 } 0996 0997 } 0998 0999 // notebook close buttons 1000 if( Gtk::gtk_notebook_is_close_button(widget)) 1001 { 1002 1003 if( gtk_button_get_relief(GTK_BUTTON(widget))==GTK_RELIEF_NONE ) 1004 { gtk_button_set_relief(GTK_BUTTON(widget),GTK_RELIEF_NORMAL); } 1005 1006 if( Cairo::Surface surface = processTabCloseButton(widget,state) ) 1007 { 1008 1009 // hide previous image 1010 // show ours instead 1011 if( GtkWidget* image = Gtk::gtk_button_find_image(widget) ) 1012 { gtk_widget_hide(image); } 1013 1014 // center the button image 1015 int width(0); 1016 int height(0); 1017 cairo_surface_get_size( surface, width, height ); 1018 x += (w-width)/2; 1019 y += (h-height)/2; 1020 1021 // render the image 1022 Cairo::Context context( window, clipRect ); 1023 cairo_set_source_surface( context, surface, x, y); 1024 cairo_paint(context); 1025 1026 } 1027 1028 return; 1029 1030 } 1031 1032 #if GTK_CHECK_VERSION(2, 20, 0) 1033 // tool itemgroup buttons 1034 if( GTK_IS_TOOL_ITEM_GROUP( widget ) ) return; 1035 #endif 1036 1037 // for google chrome, make GtkChromeButton appear as flat 1038 if( 1039 Style::instance().settings().applicationName().isGoogleChrome() && 1040 !Gtk::gtk_button_is_flat( widget ) && 1041 Gtk::g_object_is_a( G_OBJECT( widget ), "GtkChromeButton" ) ) 1042 { gtk_button_set_relief( GTK_BUTTON( widget ), GTK_RELIEF_NONE ); } 1043 1044 // options 1045 StyleOptions options( widget, state, shadow ); 1046 if(!Style::instance().settings().applicationName().useFlatBackground(widget)) 1047 { options |= Blend; } 1048 1049 // default case 1050 if( style ) 1051 { options._customColors.insert( options&Flat ? Palette::Window:Palette::Button, Gtk::gdk_get_color( style->bg[state] ) ); } 1052 1053 // flat buttons 1054 bool useWidgetState( true ); 1055 AnimationData data; 1056 // Such small buttons should rather be flat for OpenOffice (the only ones present there seem 1057 // to be the navigation buttons under vertical scrollbar in main window) 1058 bool ooFlat(Style::instance().settings().applicationName().isOpenOffice() && w<20 && h<20 && w==h); 1059 // LibO formula entry expand expand button is very small, would look better if rendered flat 1060 bool ooFormulaExpand(Style::instance().settings().applicationName().isOpenOffice() && w==16); 1061 1062 if( (widget && Gtk::gtk_button_is_flat( widget )) || ooFlat || ooFormulaExpand ) 1063 { 1064 1065 // set button as flat and disable focus 1066 options |= Flat; 1067 options &= ~Focus; 1068 1069 if(!Style::instance().settings().applicationName().isOpenOffice()) 1070 { 1071 // register to Hover engine and check state 1072 Style::instance().animations().hoverEngine().registerWidget( widget ); 1073 if( (options&Hover) ) Style::instance().animations().hoverEngine().setHovered( widget, true ); 1074 else if( Style::instance().animations().hoverEngine().hovered( widget ) ) options |= Hover; 1075 1076 // register to ToolBarState engine 1077 ToolBarStateEngine& engine( Style::instance().animations().toolBarStateEngine() ); 1078 GtkWidget* parent( 0L ); 1079 1080 bool toolPalette(false); 1081 #if GTK_CHECK_VERSION(2,20,0) 1082 toolPalette=Gtk::gtk_widget_find_parent( widget, GTK_TYPE_TOOL_PALETTE ); 1083 #endif 1084 1085 if( !toolPalette && (parent = engine.findParent( widget ) ) ) 1086 { 1087 1088 // register child 1089 engine.registerChild( parent, widget, options&Hover ); 1090 useWidgetState = false; 1091 1092 if( engine.animatedRectangleIsValid( parent ) && !(options&Sunken) ) { 1093 1094 return; 1095 1096 } if( engine.widget( parent, AnimationCurrent ) == widget ) { 1097 1098 data = engine.animationData( parent, AnimationCurrent ); 1099 1100 if( engine.isLocked( parent ) ) options |= Hover; 1101 1102 } else if( (options & Sunken ) && engine.widget( parent, AnimationPrevious ) == widget ) { 1103 1104 data = engine.animationData( parent, AnimationPrevious ); 1105 1106 } 1107 1108 } 1109 } 1110 else if(ooFlat) 1111 { 1112 // Fill with bottom color because the buttons are most likely at the bottom 1113 Cairo::Context context(window); 1114 cairo_set_source(context,ColorUtils::backgroundBottomColor( Style::instance().settings().palette().color( Palette::Window ))); 1115 cairo_rectangle(context,x,y,w,h); 1116 cairo_fill(context); 1117 } 1118 1119 } 1120 1121 // retrieve animation 1122 if( useWidgetState ) 1123 { data = Style::instance().animations().widgetStateEngine().get( widget, options ); } 1124 1125 if(Style::instance().settings().applicationName().isOpenOffice()) 1126 Style::instance().renderWindowBackground(window,clipRect,x,y,w,h); 1127 // render 1128 Style::instance().renderButtonSlab( window, clipRect, x, y, w, h, options, data ); 1129 1130 } else if( d.isMenuBar() ) { 1131 1132 if( !Style::instance().settings().applicationName().useFlatBackground( widget ) && 1133 !Gtk::gtk_widget_is_applet( widget ) ) 1134 { 1135 1136 StyleOptions options; 1137 1138 if( style ) 1139 { options._customColors.insert( Palette::Window, Gtk::gdk_get_color( style->bg[state] ) ); } 1140 1141 // window background 1142 Style::instance().renderWindowBackground( window, clipRect, x, y, w, h, options ); 1143 1144 // possible groupbox background 1145 if( Gtk::gtk_parent_groupbox( widget ) ) 1146 { Style::instance().renderGroupBoxBackground( window, widget, clipRect, x, y, w, h, Blend ); } 1147 1148 } 1149 // check animation state 1150 if( GTK_IS_MENU_BAR( widget ) ) 1151 { 1152 1153 MenuBarStateEngine& engine( Style::instance().animations().menuBarStateEngine() ); 1154 engine.registerWidget(widget); 1155 if( engine.animatedRectangleIsValid( widget ) ) 1156 { 1157 1158 const GdkRectangle& rect( engine.animatedRectangle( widget ) ); 1159 StyleOptions options( Hover ); 1160 if( !Style::instance().settings().applicationName().useFlatBackground( widget ) ) 1161 { options |= Blend; } 1162 1163 Style::instance().renderMenuItemRect( window, clipRect, engine.widget( widget, AnimationCurrent ), rect.x, rect.y, rect.width, rect.height, options ); 1164 1165 } else if( engine.isAnimated( widget, AnimationPrevious ) ) { 1166 1167 const AnimationData data( engine.animationData( widget, AnimationPrevious ) ); 1168 const GdkRectangle& rect( engine.rectangle( widget, AnimationPrevious ) ); 1169 StyleOptions options( Hover ); 1170 if( !Style::instance().settings().applicationName().useFlatBackground( widget ) ) 1171 { options |= Blend; } 1172 1173 Style::instance().renderMenuItemRect( window, clipRect, engine.widget( widget, AnimationPrevious ), rect.x, rect.y, rect.width, rect.height, options, data ); 1174 1175 } 1176 1177 } 1178 1179 return; 1180 1181 } else if( d.isToolBar() ) { 1182 1183 // eclipse works ok with animations, though should have flat background 1184 if( Style::instance().settings().applicationName().isEclipse() ) 1185 { 1186 1187 draw_animated_button( window, clipRect, widget ); 1188 return; 1189 1190 } else if( Style::instance().settings().applicationName().useFlatBackground( widget ) || Gtk::gtk_widget_is_applet( widget ) ) { 1191 1192 return; 1193 1194 } else { 1195 1196 Style::instance().renderWindowBackground( window, clipRect, x, y, w, h ); 1197 1198 // possible groupbox background 1199 if( Gtk::gtk_parent_groupbox( widget ) ) 1200 { Style::instance().renderGroupBoxBackground( window, widget, clipRect, x, y, w, h, Blend ); } 1201 1202 // also draw possible animated tool button 1203 draw_animated_button( window, clipRect, widget ); 1204 return; 1205 1206 } 1207 1208 } else if( d.isMenu() ) { 1209 1210 if( GTK_IS_MENU( widget ) && gtk_menu_get_tearoff_state( GTK_MENU( widget ) ) ) 1211 { 1212 1213 if( 1214 Gtk::gdk_window_is_base( window ) && 1215 !Style::instance().settings().applicationName().isXul( widget ) ) 1216 { 1217 BackgroundHints hints( BackgroundGradient ); 1218 if( Style::instance().hasBackgroundSurface() ) hints |= BackgroundPixmap; 1219 Style::instance().animations().backgroundHintEngine().registerWidget( widget, hints ); 1220 } 1221 1222 Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h ); 1223 1224 } else { 1225 1226 StyleOptions options( Menu ); 1227 1228 // set alpha flag. Special handling is needed for mozilla and openoffice. 1229 if( Style::instance().settings().applicationName().isXul( widget ) || 1230 Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1231 { 1232 1233 Style::instance().renderMenuBackground( window, clipRect, x, y, w, h, options ); 1234 1235 // since menus are rendered square anyway, we can set the alpha channel 1236 // based on the screen properties only, in order to prevent ugly shadow to be drawn 1237 if( Gtk::gdk_default_screen_is_composited() ) options |= Alpha; 1238 Style::instance().drawFloatFrame( window, clipRect, x, y, w, h, options ); 1239 return; 1240 } 1241 1242 options |= Round; 1243 if( Gtk::gtk_widget_has_rgba( widget ) ) options |= Alpha; 1244 1245 if( style ) 1246 { options._customColors.insert( Palette::Window, Gtk::gdk_get_color( style->bg[state] ) ); } 1247 1248 // add mask if needed 1249 if( GTK_IS_MENU(widget) ) 1250 { 1251 Style::instance().animations().menuItemEngine().registerMenu( widget ); 1252 1253 WidgetSizeEngine& engine( Style::instance().animations().widgetSizeEngine() ); 1254 engine.registerWidget( widget ); 1255 if( engine.update( widget ) ) 1256 { 1257 Style::instance().adjustMask( widget, engine.width( widget ), engine.height( widget ), engine.alpha( widget ) ); 1258 if( Style::instance().settings().backgroundOpacity() < 255 ) 1259 { Style::instance().setWindowBlur( widget, engine.alpha( widget ) ); } 1260 } 1261 } 1262 1263 // if render 1264 if( !Style::instance().renderMenuBackground( window, clipRect, x, y, w, h, options ) ) 1265 { options &= ~Round; } 1266 1267 Style::instance().drawFloatFrame( window, clipRect, x, y, w, h, options ); 1268 1269 } 1270 1271 // check animation state 1272 if( GTK_IS_MENU( widget ) ) 1273 { 1274 1275 MenuStateEngine& engine( Style::instance().animations().menuStateEngine() ); 1276 engine.registerWidget(widget); 1277 1278 if( engine.animatedRectangleIsValid( widget ) ) 1279 { 1280 1281 const GdkRectangle& rect( engine.animatedRectangle( widget ) ); 1282 Style::instance().renderMenuItemRect( window, clipRect, engine.widget( widget, AnimationCurrent ), rect.x, rect.y, rect.width, rect.height, Hover ); 1283 1284 } else if( engine.isLocked( widget ) ) { 1285 1286 const GdkRectangle& rect( engine.rectangle( widget, AnimationCurrent ) ); 1287 Style::instance().renderMenuItemRect( window, clipRect, engine.widget( widget, AnimationCurrent ), rect.x, rect.y, rect.width, rect.height, Hover ); 1288 1289 } else if( engine.isAnimated( widget, AnimationPrevious ) ) { 1290 1291 const AnimationData data( engine.animationData( widget, AnimationPrevious ) ); 1292 const GdkRectangle& rect( engine.rectangle( widget, AnimationPrevious ) ); 1293 Style::instance().renderMenuItemRect( window, clipRect, engine.widget( widget, AnimationPrevious ), rect.x, rect.y, rect.width, rect.height, Hover, data ); 1294 1295 } 1296 1297 } 1298 1299 1300 } else if( d.isMenuScrollArrow() ) { 1301 1302 return; 1303 1304 } else if( d.isDefaultButton() || d.isScrollBar() || d.isPaned() || d.isHandleBox() ) { 1305 1306 return; 1307 1308 } else if( d.isDockItem() ) { 1309 1310 // force window background for dock-items. Fixes inkscape docks 1311 Style::instance().renderWindowBackground( window, clipRect, x, y, w, h ); 1312 1313 } else if( d.isMenuItem() ) { 1314 1315 if( GTK_IS_MENU_ITEM( widget ) ) 1316 { 1317 GtkWidget* child( gtk_bin_get_child( GTK_BIN( widget ) ) ); 1318 Style::instance().animations().menuItemEngine().registerWidget( child ); 1319 } 1320 1321 GtkWidget* parent( gtk_widget_get_parent( widget ) ); 1322 AnimationData data; 1323 if( GTK_IS_MENU_BAR( parent ) ) 1324 { 1325 1326 MenuBarStateEngine& engine = Style::instance().animations().menuBarStateEngine(); 1327 engine.registerWidget( parent ); 1328 if( engine.animatedRectangleIsValid( parent ) ) 1329 { 1330 return; 1331 1332 } else if( engine.widget( parent, AnimationCurrent ) == widget ) { 1333 1334 data = engine.animationData( parent, AnimationCurrent ); 1335 1336 } 1337 1338 } else if( GTK_IS_MENU( parent ) ) { 1339 1340 MenuStateEngine& engine = Style::instance().animations().menuStateEngine(); 1341 engine.registerWidget( parent ); 1342 if( engine.animatedRectangleIsValid( parent ) ) 1343 { 1344 return; 1345 1346 } else if( engine.widget( parent, AnimationCurrent ) == widget ) { 1347 1348 data = engine.animationData( parent, AnimationCurrent ); 1349 1350 } 1351 1352 } 1353 1354 1355 StyleOptions options( widget, state, shadow ); 1356 if( !Style::instance().settings().applicationName().useFlatBackground( widget ) ) 1357 { options |= Blend; } 1358 1359 Style::instance().renderMenuItemRect( window, clipRect, widget, x, y, w, h, options, data ); 1360 1361 } else if( d.isTroughAny() && GTK_IS_SCALE( widget ) ) { 1362 1363 const bool vertical( Gtk::gtk_widget_is_vertical( widget ) ); 1364 const int offset( 6 ); 1365 if( vertical ) { 1366 1367 // TODO: calculate this value from the style "slider-width" property 1368 if( d.isTrough() ) Style::instance().renderSliderGroove( window, clipRect, x, y + offset, w, h - 2*offset, Vertical ); 1369 else if( d.isTroughLower() ) Style::instance().renderSliderGroove( window, clipRect, x, y + offset, w, h, Vertical ); 1370 else if( d.isTroughUpper() ) Style::instance().renderSliderGroove( window, clipRect, x, y, w, h - offset, Vertical ); 1371 1372 } else { 1373 1374 // TODO: calculate this value from the style "slider-width" property 1375 const int offset( 6 ); 1376 if( d.isTrough() ) Style::instance().renderSliderGroove( window, clipRect, x + offset, y, w - 2*offset, h, StyleOptions() ); 1377 else if( d.isTroughLower() ) Style::instance().renderSliderGroove( window, clipRect, x + offset, y, w, h, StyleOptions() ); 1378 else if( d.isTroughUpper() ) Style::instance().renderSliderGroove( window, clipRect, x, y, w - offset, h, StyleOptions() ); 1379 1380 } 1381 1382 } else if( d.isTrough() && shadow == GTK_SHADOW_IN ) { 1383 1384 if( GTK_IS_PROGRESS_BAR( widget ) ) 1385 { 1386 1387 if( !Style::instance().settings().applicationName().isXul( widget ) && 1388 !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1389 { 1390 /* 1391 need to call the parent style implementation here, 1392 otherwise some uninitialized pixels are present. 1393 Not sure why 1394 */ 1395 StyleWrapper::parentClass()->draw_box( style, window, state, shadow, clipRect, widget, detail, x, y, w, h ); 1396 1397 if( !Gtk::gtk_widget_is_applet( widget ) ) 1398 { 1399 1400 Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h ); 1401 1402 // possible groupbox background 1403 if( Gtk::gtk_parent_groupbox( widget ) ) 1404 { Style::instance().renderGroupBoxBackground( window, widget, clipRect, x, y, w, h, Blend ); } 1405 1406 } 1407 } 1408 1409 StyleOptions options; 1410 if( Gtk::gtk_widget_is_vertical( widget ) ) options |= Vertical; 1411 Style::instance().renderProgressBarHole( window, clipRect, x, y, w, h, options ); 1412 1413 } else if( GTK_IS_VSCROLLBAR( widget ) ) { 1414 1415 if(Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1416 { 1417 // adjust scrollbar hole since it has wrong geometry in OOo 1418 y-=1; 1419 } 1420 1421 1422 Style::instance().adjustScrollBarHole( x, y, w, h, Vertical ); 1423 Style::instance().renderScrollBarHole( window, clipRect, x, y+1, w-1, h-1, Vertical ); 1424 1425 } else if( GTK_IS_HSCROLLBAR( widget ) ) { 1426 1427 if(Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1428 { 1429 // adjust scrollbar hole since it has wrong geometry in OOo 1430 x-=2; w+=1; 1431 } 1432 1433 Style::instance().adjustScrollBarHole( x, y, w, h, StyleOptions() ); 1434 Style::instance().renderScrollBarHole( window, clipRect, x+1, y, w-2, h-1, StyleOptions() ); 1435 1436 } 1437 1438 } else if( d.isSpinButton()) { 1439 1440 StyleOptions options( widget, state, shadow ); 1441 options |= Blend; 1442 1443 if( Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1444 { 1445 // Do nothing for openoffice 1446 return; 1447 } else { 1448 1449 options |= NoFill; 1450 ColorUtils::Rgba background( Gtk::gdk_get_color( style->base[gtk_widget_get_state(widget)] ) ); 1451 if( Style::instance().settings().applicationName().isXul( widget ) ) 1452 { 1453 1454 /* 1455 for firefox on has to mask out the corners manually, 1456 because renderholebackground fails 1457 */ 1458 Cairo::Context context( window, clipRect ); 1459 cairo_rounded_rectangle( context, x-4, y+2, w+3, h-4, 2, CornersRight ); 1460 cairo_set_source( context, background ); 1461 cairo_fill( context ); 1462 1463 x += 1; 1464 w += 2; 1465 1466 } else Style::instance().fill( window, clipRect, x, y, w, h, background ); 1467 1468 } 1469 1470 if( 1471 Style::instance().animations().hoverEngine().contains( widget ) && 1472 Style::instance().animations().hoverEngine().hovered( widget ) ) 1473 { options |= Hover; } 1474 1475 TileSet::Tiles tiles( TileSet::Ring); 1476 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 1477 1478 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 1479 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 1480 { 1481 1482 tiles &= ~TileSet::Right; 1483 1484 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) && 1485 !Style::instance().settings().applicationName().isXul( widget ) ) 1486 { Style::instance().renderHoleBackground( window, widget, clipRect, x-1, y-1, w+6, h+2, tiles, sideMargin ); } 1487 1488 // shrink spinbox entry hole by 3px on right side 1489 x += sideMargin; 1490 w -= sideMargin; 1491 Style::instance().renderHole( window, clipRect, x-1, y-1, w+8, h+2, options, data, tiles ); 1492 1493 } else { 1494 1495 tiles &= ~TileSet::Left; 1496 1497 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) && 1498 !Style::instance().settings().applicationName().isXul( widget ) ) 1499 { Style::instance().renderHoleBackground( window, widget, clipRect, x-5, y-1, w+6, h+2, tiles, sideMargin ); } 1500 1501 // shrink spinbox entry hole by 3px on right side 1502 w -= sideMargin; 1503 Style::instance().renderHole( window, clipRect, x-7, y-1, w+8, h+2, options, data, tiles ); 1504 1505 } 1506 1507 1508 } else if( d.isSpinButtonUp() || d.isSpinButtonDown() ) 1509 { 1510 1511 if( Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1512 { 1513 if(state==GTK_STATE_ACTIVE) 1514 state=GTK_STATE_NORMAL; 1515 ColorUtils::Rgba background( Gtk::gdk_get_color( style->base[state] ) ); 1516 Cairo::Context context( window, clipRect ); 1517 StyleOptions options( NoFill ); 1518 options|=Blend; 1519 TileSet::Tiles tiles( TileSet::Ring ); 1520 tiles &= ~TileSet::Left; 1521 { 1522 int W(w-4), Y(y),H(h); 1523 if(d.isSpinButtonUp()) 1524 { 1525 tiles &= ~TileSet::Bottom; 1526 Y+=1; 1527 } 1528 else 1529 { 1530 tiles &= ~TileSet::Top; 1531 H-=2; 1532 } 1533 1534 cairo_rounded_rectangle( context, x, Y, W, H, 2, CornersRight ); 1535 cairo_set_source( context, background ); 1536 cairo_fill( context ); 1537 } 1538 1539 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 1540 if(d.isSpinButtonUp()) 1541 Style::instance().renderHole( window, clipRect, x-7, y, w+5, h+6, options, data, tiles ); 1542 else 1543 Style::instance().renderHole( window, clipRect, x-6, y-7, w+4, h+7, options, data, tiles ); 1544 return; 1545 } 1546 1547 1548 } else if( d.isSpinButtonArrow() ) { 1549 1550 return; 1551 1552 } else if( d.isBar() ) { 1553 1554 StyleOptions options( widget, state, shadow ); 1555 if(GTK_IS_PROGRESS_BAR(widget)) 1556 { 1557 1558 // active state must be set by hand cause it is not set by gtk 1559 if( !gtk_widget_is_sensitive( widget ) ) 1560 { options |= Disabled; } 1561 1562 // get orientation 1563 if( Gtk::gtk_widget_is_vertical( widget ) ) 1564 { options |= Vertical; } 1565 1566 /* 1567 need to adjust rect and clip for altered x/y thickness 1568 because gtk passes it to the handle and not to the hole 1569 */ 1570 const int delta_x = 1 - style->xthickness; 1571 const int delta_y = -style->ythickness; 1572 x += delta_x; w -= 2*delta_x; 1573 y += delta_y; h -= 2*delta_y; 1574 1575 if( clipRect ) 1576 { 1577 clipRect->x += delta_x; clipRect->width -= 2*delta_x; 1578 clipRect->y += delta_y; clipRect->height -= 2*delta_y; 1579 } 1580 1581 if(Style::instance().settings().applicationName().isOpenOffice()) 1582 { 1583 ++x; 1584 w-=2; 1585 } 1586 // need to adjust rect and clip to handle unexpected x/y thickness values 1587 Style::instance().renderProgressBarHandle( window, clipRect, x, y, w, h, options ); 1588 1589 } else { 1590 1591 // most likely it's progressbar in the list 1592 // FIXME: is it always the case ? Should we check on TREE_VIEW, CELL_VIEW, like done with scrollbar hole ? 1593 Style::instance().renderProgressBarHandle( window, clipRect, x-1, y, w+1, h, options ); 1594 1595 } 1596 1597 return; 1598 1599 } else if( d.isEntryProgress() ) { 1600 1601 StyleOptions options( widget, state, shadow ); 1602 Style::instance().renderProgressBarHandle( window, clipRect, x-2, y-1, w+4, h+2, options ); 1603 1604 } else if( d.isTroughFillLevel () ) { 1605 1606 return; 1607 1608 } else if( d.isRuler() ) { 1609 1610 Style::instance().renderWindowBackground(window,widget,clipRect,x,y,w,h); 1611 1612 } else { 1613 1614 StyleWrapper::parentClass()->draw_box( style, window, state, 1615 shadow, clipRect, widget, detail, 1616 x, y, w, h ); 1617 } 1618 1619 } 1620 1621 //___________________________________________________________________________________________________________ 1622 static void draw_shadow( 1623 GtkStyle* style, 1624 GdkWindow* window, 1625 GtkStateType state, 1626 GtkShadowType shadow, 1627 GdkRectangle* clipRect, 1628 GtkWidget* widget, 1629 const gchar* detail, 1630 gint x, 1631 gint y, 1632 gint w, 1633 gint h ) 1634 { 1635 g_return_if_fail( style && window ); 1636 Style::instance().sanitizeSize( window, w, h ); 1637 1638 #if OXYGEN_DEBUG 1639 std::cerr 1640 << "Oxygen::draw_shadow -" 1641 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 1642 << " state: " << Gtk::TypeNames::state( state ) 1643 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 1644 << " detail: " << (detail ? detail:"0x0" ) 1645 << " rect: " << Gtk::gdk_rectangle( x, y, w, h ) 1646 << " thickness: " << style->xthickness << "," << style->ythickness 1647 << std::endl; 1648 #endif 1649 1650 GtkWidget* parent( 0L ); 1651 const Gtk::Detail d( detail ); 1652 1653 // ugly Gnumeric header 1654 if( d.is("GnmItemBarCell") ) 1655 { return; } 1656 1657 // adjust shadow type for some known widgets 1658 if( d.isScrolledWindow() && GTK_IS_SCROLLED_WINDOW( widget ) ) 1659 { 1660 1661 // make sure that scrolled windows containing a treeView have sunken frame 1662 if( shadow != GTK_SHADOW_IN && Gtk::gtk_scrolled_window_force_sunken( widget ) ) 1663 { 1664 1665 shadow = GTK_SHADOW_IN; 1666 gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW( widget ), GTK_SHADOW_IN ); 1667 1668 } 1669 1670 // register to inner shadow engine 1671 if( 1672 shadow == GTK_SHADOW_IN && 1673 gtk_scrolled_window_get_shadow_type( GTK_SCROLLED_WINDOW( widget ) ) == GTK_SHADOW_IN && 1674 Style::instance().animations().innerShadowEngine().contains( widget ) ) 1675 { Style::instance().animations().innerShadowEngine().registerChild( widget, gtk_bin_get_child( GTK_BIN( widget ) ) ); } 1676 1677 } else if( 1678 d.isFrame() && 1679 ( shadow == GTK_SHADOW_ETCHED_IN || shadow == GTK_SHADOW_ETCHED_OUT ) && 1680 GTK_IS_FRAME( widget ) && 1681 Gtk::gtk_scrolled_window_force_sunken( widget ) 1682 ) 1683 { 1684 1685 // make sure that entry shadows are drawn 1686 shadow = GTK_SHADOW_IN; 1687 gtk_frame_set_shadow_type( GTK_FRAME( widget ), GTK_SHADOW_IN ); 1688 1689 } else if( d.isEntry() && shadow != GTK_SHADOW_IN ) { 1690 1691 // make sure that entry shadows are drawn 1692 shadow = GTK_SHADOW_IN; 1693 1694 } 1695 1696 // check if it's combobox list window 1697 if( Gtk::gtk_combobox_is_scrolled_window( widget ) && GTK_IS_WINDOW( parent = gtk_widget_get_parent( widget ) ) ) 1698 { 1699 1700 // setup options 1701 StyleOptions options( Round ); 1702 if( Gtk::gtk_widget_has_rgba(parent) ) options|=Alpha; 1703 const GtkAllocation allocation( Gtk::gtk_widget_get_allocation( parent ) ); 1704 1705 // always register to widget size engine 1706 WidgetSizeEngine& engine( Style::instance().animations().widgetSizeEngine() ); 1707 engine.registerWidget( parent ); 1708 const WidgetSizeData::ChangedFlags changedFlags( engine.update( parent ) ); 1709 if( changedFlags ) Style::instance().adjustMask( parent, engine.width( parent ), engine.height( parent ), engine.alpha( parent ) ); 1710 1711 #if !ENABLE_INNER_SHADOWS_HACK 1712 if( changedFlags & WidgetSizeData::SizeChanged ) 1713 { 1714 // also sets inner list mask 1715 if( GtkWidget* child = gtk_bin_get_child( GTK_BIN( widget ) ) ) 1716 { 1717 const GtkAllocation allocation( Gtk::gtk_widget_get_allocation( child ) ); 1718 1719 // offset is needed to make combobox list border 3px wide instead of default 2 1720 // additional pixel is for ugly shadow 1721 const gint offset( options&Alpha ? 0:1 ); 1722 GdkPixmap* mask( Style::instance().helper().roundMask( 1723 allocation.width - 2*offset, 1724 allocation.height - 2*offset, 1725 3 ) ); 1726 1727 gdk_window_shape_combine_mask( gtk_widget_get_window( child ), mask, offset, offset ); 1728 gdk_pixmap_unref( mask ); 1729 } 1730 } 1731 #endif 1732 1733 // menu background and float frame 1734 GdkWindow* parentWindow( gtk_widget_get_window( parent ) ); 1735 Style::instance().renderMenuBackground( parentWindow, clipRect, allocation.x, allocation.y, allocation.width, allocation.height, options ); 1736 Style::instance().drawFloatFrame( parentWindow, clipRect, allocation.x, allocation.y, allocation.width, allocation.height, options ); 1737 1738 return; 1739 1740 } else if( d.isBase() && GTK_IS_MENU( widget ) ) { 1741 1742 // this is to prevent mozilla to 1743 // draw yet another frame around menus 1744 return; 1745 1746 } else if( Gtk::gtk_combo_is_viewport( widget ) ) { 1747 1748 return; 1749 1750 } else if( Gtk::gtk_combo_is_frame( widget ) ) { 1751 1752 // make GtkCombo list look a bit better 1753 // retrieve proper parent and check 1754 GtkWidget* parent=gtk_widget_get_parent(widget); 1755 if( parent ) parent=gtk_widget_get_parent(parent); 1756 if( !( parent && GTK_IS_WINDOW(parent) ) ) return; 1757 1758 // setup options 1759 StyleOptions options( Round ); 1760 if( Gtk::gtk_widget_has_rgba(parent) ) options|=Alpha; 1761 1762 // make background window rounded 1763 WidgetSizeEngine& engine( Style::instance().animations().widgetSizeEngine() ); 1764 engine.registerWidget( parent ); 1765 if( engine.update(parent) ) 1766 { Style::instance().adjustMask( parent, engine.width( parent ), engine.height( parent ), engine.alpha( parent ) ); } 1767 1768 // menu background and float frame 1769 Style::instance().renderMenuBackground( window, clipRect, x, y, w, h, options ); 1770 Style::instance().drawFloatFrame( window, clipRect, x, y, w, h, options ); 1771 1772 return; 1773 1774 } else if( d.isSlider() || d.isRuler() || d.isDragAndDrop() ) { 1775 1776 return; 1777 1778 } else if( ( d.isEntry() || d.isViewport() || d.isScrolledWindow() ) && shadow == GTK_SHADOW_IN ) { 1779 1780 StyleOptions options( widget, state, shadow ); 1781 options |= NoFill; 1782 1783 if( GtkWidget* parent = Gtk::gtk_parent_combobox_entry( widget ) ) 1784 { 1785 1786 // check if parent is in style map 1787 Style::instance().animations().comboBoxEntryEngine().registerWidget( parent ); 1788 Style::instance().animations().comboBoxEntryEngine().setEntry( parent, widget ); 1789 Style::instance().animations().comboBoxEntryEngine().setEntryFocus( parent, options & Focus ); 1790 1791 if( Style::instance().animations().comboBoxEntryEngine().hasFocus( parent ) ) options |= Focus; 1792 else options &= ~Focus; 1793 1794 if( Style::instance().animations().comboBoxEntryEngine().hovered( parent ) ) options |= Hover; 1795 else options &= ~Hover; 1796 1797 // render 1798 TileSet::Tiles tiles( TileSet::Ring ); 1799 const AnimationData data( Style::instance().animations().widgetStateEngine().get( parent, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 1800 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 1801 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 1802 { 1803 1804 tiles &= ~TileSet::Left; 1805 Style::instance().renderHoleBackground( window, widget, clipRect, x-6, y, w+7, h, tiles, sideMargin ); 1806 1807 w -= sideMargin; 1808 Style::instance().renderHole( window, clipRect, x-8, y, w+9, h, options, data, tiles ); 1809 1810 } else { 1811 1812 tiles &= ~TileSet::Right; 1813 Style::instance().renderHoleBackground( window, widget, clipRect, x-1, y, w+7, h, tiles, sideMargin ); 1814 1815 x += sideMargin; 1816 w -= sideMargin; 1817 Style::instance().renderHole( window, clipRect, x-1, y, w+9, h, options, data, tiles ); 1818 1819 } 1820 1821 } else if( GTK_IS_SPIN_BUTTON( widget ) ) { 1822 1823 // register to hover engine 1824 Style::instance().animations().hoverEngine().registerWidget( widget, true ); 1825 if( Style::instance().animations().hoverEngine().hovered( widget ) ) 1826 { options |= Hover; } 1827 1828 if( !Style::instance().settings().applicationName().isXul( widget ) ) 1829 { 1830 1831 // fill the inside of the spinbox manually 1832 ColorUtils::Rgba background( Gtk::gdk_get_color( style->base[gtk_widget_get_state( widget )] ) ); 1833 if( Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1834 { 1835 1836 // for openoffice on has to properly round the corners 1837 Cairo::Context context( window, clipRect ); 1838 cairo_rounded_rectangle( context, x+1, y+1, w-1, h-3, 2, CornersLeft ); 1839 cairo_set_source( context, background ); 1840 cairo_fill( context ); 1841 1842 } else { 1843 1844 Style::instance().fill( window, clipRect, x, y, w, h, background ); 1845 1846 } 1847 1848 } 1849 1850 // vertical alignment 1851 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1852 { y-=1; h+=2; } 1853 1854 // basic adjustments 1855 x-=1; w+=2; 1856 1857 // animation data 1858 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 1859 1860 TileSet::Tiles tiles( TileSet::Ring ); 1861 1862 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 1863 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 1864 { 1865 1866 tiles &= ~TileSet::Left; 1867 1868 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1869 { 1870 Style::instance().renderHoleBackground( window, widget, clipRect, x, y, w, h, tiles, sideMargin ); 1871 w-= sideMargin; 1872 } 1873 1874 Style::instance().renderHole( window, clipRect, x-7, y, w+7, h, options, data, tiles ); 1875 1876 } else { 1877 1878 tiles &= ~TileSet::Right; 1879 1880 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1881 { 1882 Style::instance().renderHoleBackground( window, widget, clipRect, x, y, w, h, tiles, sideMargin ); 1883 x += sideMargin; 1884 w -= sideMargin; 1885 } 1886 1887 Style::instance().renderHole( window, clipRect, x, y, w+7, h, options, data, tiles ); 1888 1889 } 1890 1891 } else { 1892 1893 if( Style::instance().settings().applicationName().isGoogleChrome() && GTK_IS_HBOX( widget ) ) 1894 { options &= ~NoFill; } 1895 1896 // register to hover engine 1897 if( GTK_IS_ENTRY( widget ) && !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1898 { 1899 1900 Style::instance().animations().hoverEngine().registerWidget( widget, true ); 1901 if( Style::instance().animations().hoverEngine().hovered( widget ) ) 1902 { options |= Hover; } 1903 1904 } else if( GTK_IS_SCROLLED_WINDOW( widget ) ) { 1905 1906 Style::instance().animations().scrolledWindowEngine().registerWidget( widget ); 1907 1908 options &= ~(Hover|Focus); 1909 if( Style::instance().animations().scrolledWindowEngine().focused( widget ) ) options |= Focus; 1910 if( Style::instance().animations().scrolledWindowEngine().hovered( widget ) ) options |= Hover; 1911 1912 1913 } else { 1914 1915 options &= ~(Hover|Focus); 1916 1917 } 1918 1919 // Do nothing for OpenOffice 1920 if(d.isEntry() && Style::instance().settings().applicationName().isOpenOffice()) 1921 return; 1922 // OpenOffice or Chromium address bar 1923 if( (widget && GTK_IS_HBOX(widget) && Style::instance().settings().applicationName().isGoogleChrome()) || 1924 Style::instance().settings().applicationName().isOpenOffice() ) 1925 { 1926 1927 if( d.isEntry() ) 1928 { 1929 1930 options &= ~NoFill; 1931 Style::instance().renderHoleBackground( window, widget, clipRect, x-1, y-1, w+2, h+2 ); 1932 Style::instance().renderHole( window, clipRect, x-1, y-1, w+2, h+2, options ); 1933 1934 } else { 1935 1936 Style::instance().renderHole( window, clipRect, x, y, w, h, options ); 1937 1938 } 1939 1940 } else { 1941 1942 // basic adjustments 1943 x-=1; y-=1; 1944 w+=2; h+=2; 1945 1946 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 1947 if( !Style::instance().settings().applicationName().isXul( widget ) ) 1948 { Style::instance().renderHoleBackground( window, widget, clipRect, x, y, w, h, TileSet::Full, sideMargin ); } 1949 1950 // shrink entry by 3px at each side 1951 if( d.isEntry() ) 1952 { 1953 1954 x += sideMargin; 1955 w -= 2*sideMargin; 1956 1957 } 1958 1959 // animation 1960 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover|AnimationFocus, AnimationFocus ) ); 1961 if(!Style::instance().animations().innerShadowEngine().contains(widget) || shadow!=GTK_SHADOW_IN) 1962 { 1963 1964 Style::instance().renderHole( window, clipRect, x, y, w, h, options, data ); 1965 1966 } else { 1967 1968 Style::instance().renderHole( window, clipRect, x+1, y+1, w-2, h-2, options, data ); 1969 1970 } 1971 1972 } 1973 1974 } 1975 1976 return; 1977 1978 } else if( ( d.isTrough() || d.isBar() ) && GTK_IS_PROGRESS_BAR( widget ) ) { 1979 1980 return; 1981 1982 } else if (GTK_IS_NOTEBOOK(widget)) { 1983 1984 if( !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 1985 { 1986 Style::instance().renderWindowBackground( window, clipRect, x-4, y-4, w+8, h+8 ); 1987 draw_animated_button( window, clipRect, widget ); 1988 } 1989 1990 if( gtk_notebook_get_show_tabs( GTK_NOTEBOOK( widget ) ) ) 1991 { 1992 1993 Style::instance().renderSlab(window,clipRect,x-1,y-1,w+2,h+2,NoFill); 1994 1995 } 1996 1997 } else if( GTK_IS_CALENDAR( widget ) && shadow == GTK_SHADOW_OUT ) { 1998 1999 // calendar header 2000 if( style ) 2001 { 2002 Style::instance().fill( window,clipRect,x-2,y-2,w+4,h+4, Gtk::gdk_get_color( style->base[state] ) ); 2003 Style::instance().renderWindowBackground( window, widget, clipRect,x+2,y+2,w-4,h-6 ); 2004 } 2005 2006 StyleOptions options( NoFill ); 2007 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 2008 { options |= Blend; } 2009 2010 Style::instance().renderSlab(window,clipRect,x-2,y-2,w+4,h+2, options ); 2011 2012 } else if( 2013 (parent = Gtk::gtk_parent_combobox( widget )) && 2014 !GTK_IS_CELL_VIEW( widget ) && 2015 !Style::instance().settings().applicationName().isXul( widget ) ) { 2016 2017 Style::instance().animations().comboBoxEngine().registerWidget( parent ); 2018 Style::instance().animations().comboBoxEngine().registerChild( parent, widget ); 2019 GtkShadowType shadow( Style::instance().animations().comboBoxEngine().pressed( parent ) ? GTK_SHADOW_IN:GTK_SHADOW_OUT ); 2020 2021 StyleOptions options( widget, state, shadow ); 2022 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 2023 { options |= Blend; } 2024 2025 if( Style::instance().animations().comboBoxEngine().hasFocus( parent ) ) options |= Focus; 2026 else options &= ~Focus; 2027 2028 if( Style::instance().animations().comboBoxEngine().hovered( parent ) ) options |= Hover; 2029 else options &= ~Hover; 2030 2031 // animation state 2032 const AnimationData data( (options&Sunken) ? AnimationData():Style::instance().animations().widgetStateEngine().get( parent, options ) ); 2033 2034 // tiles 2035 TileSet::Tiles tiles( TileSet::Ring ); 2036 2037 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 2038 { 2039 2040 tiles &= ~TileSet::Left; 2041 Style::instance().renderButtonSlab( window, clipRect, x-10, y, w+10, h, options, data, tiles ); 2042 2043 } else { 2044 2045 tiles &= ~TileSet::Right; 2046 Style::instance().renderButtonSlab( window, clipRect, x, y, w+10, h, options, data, tiles ); 2047 2048 } 2049 2050 } else if( d.isNull() && (GTK_IS_TREE_VIEW(widget) || GTK_IS_CELL_VIEW(widget)) && shadow==GTK_SHADOW_IN ) { 2051 2052 // it's likely progressbar hole 2053 // FIXME: is it enough to check for TreeView? is shadow_in the only possible case? 2054 Style::instance().renderProgressBarHole( window, clipRect, x-2, y, w+3, h, StyleOptions() ); 2055 2056 } else if(Style::instance().settings().applicationName().isOpenOffice() && x==0 && y==0) 2057 { 2058 StyleOptions options(Blend); 2059 if( Gtk::gdk_default_screen_is_composited() ) options |= Alpha; 2060 Style::instance().drawFloatFrame( window, clipRect, x,y,w,h,options); 2061 return; 2062 } else if( shadow == GTK_SHADOW_IN && !Gtk::gtk_parent_statusbar( widget ) ) { 2063 2064 if( GTK_IS_FRAME( widget ) ) 2065 { 2066 2067 /* 2068 check for scrolled windows embedded in frames, that contain a treeview. 2069 if found, change the shadowtypes for consistency with normal -sunken- scrolled windows. 2070 this should improve rendering of most mandriva drake tools 2071 */ 2072 GtkWidget* child( gtk_bin_get_child( GTK_BIN( widget ) ) ); 2073 if( 2074 GTK_IS_SCROLLED_WINDOW( child ) && 2075 GTK_IS_TREE_VIEW( gtk_bin_get_child( GTK_BIN( child ) ) ) ) 2076 { 2077 gtk_frame_set_shadow_type( GTK_FRAME( widget ), GTK_SHADOW_NONE ); 2078 2079 // also change scrolled window shadow if needed 2080 GtkScrolledWindow* scrolledWindow(GTK_SCROLLED_WINDOW( child ) ); 2081 if( gtk_scrolled_window_get_shadow_type( scrolledWindow ) != GTK_SHADOW_IN ) 2082 { 2083 gtk_scrolled_window_set_shadow_type( scrolledWindow, GTK_SHADOW_IN ); 2084 if( Style::instance().animations().innerShadowEngine().contains( child ) ) 2085 { Style::instance().animations().innerShadowEngine().registerChild( child, gtk_bin_get_child( GTK_BIN( child ) ) ); } 2086 } 2087 2088 return; 2089 2090 } 2091 2092 } 2093 2094 // default shadow_in frame 2095 // hole background is needed for some special cases 2096 if( GTK_IS_CALENDAR( widget ) ) 2097 { 2098 2099 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 2100 Style::instance().renderHoleBackground( 2101 window, widget, clipRect, 2102 x-1-sideMargin, y-1, w+2+2*sideMargin, h+2, 2103 TileSet::Full, sideMargin ); 2104 } 2105 2106 // hole 2107 Style::instance().renderHole( window, clipRect, x-1, y-1, w+2, h+2, NoFill ); 2108 2109 } else if( (shadow == GTK_SHADOW_ETCHED_IN || shadow == GTK_SHADOW_ETCHED_OUT) && !Gtk::gtk_parent_button( widget )) { 2110 2111 // default etched frame 2112 Style::instance().renderDockFrame( window, clipRect, x, y+1, w, h-2, Blend ); 2113 2114 } else if( shadow == GTK_SHADOW_OUT ) { 2115 2116 if( d.isFrame() && Gtk::gtk_widget_is_groupbox( widget ) ) 2117 { 2118 2119 Style::instance().renderGroupBoxFrame( window, widget, clipRect, x-1, y-1, w+2, h+2, Blend ); 2120 2121 } else { 2122 2123 Style::instance().renderSlab( window, clipRect, x-1, y-1, w+2, h+2, NoFill ); 2124 2125 } 2126 2127 } 2128 2129 return; 2130 } 2131 2132 //___________________________________________________________________________________________________________ 2133 static void draw_check( GtkStyle* style, 2134 GdkWindow* window, 2135 GtkStateType state, 2136 GtkShadowType shadow, 2137 GdkRectangle* clipRect, 2138 GtkWidget* widget, 2139 const gchar* detail, 2140 gint x, 2141 gint y, 2142 gint w, 2143 gint h ) 2144 { 2145 g_return_if_fail( style && window ); 2146 2147 Style::instance().sanitizeSize( window, w, h ); 2148 2149 #if OXYGEN_DEBUG 2150 std::cerr 2151 << "Oxygen::draw_check -" 2152 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2153 << " state: " << Gtk::TypeNames::state( state ) 2154 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2155 << " detail: " << (detail ? detail:"0x0" ) 2156 << std::endl; 2157 #endif 2158 2159 const Gtk::Detail d( detail ); 2160 if( d.isCheckButton() || d.isCellCheck() ) 2161 { 2162 2163 StyleOptions options( widget, state, shadow ); 2164 2165 // this ensures that hover keeps precedence of focus for pressed down buttons 2166 if( state == GTK_STATE_ACTIVE ) options |= Hover; 2167 2168 // test whether blending should be enabled 2169 if( !( 2170 d.isCellCheck() || 2171 Gtk::gtk_parent_tree_view( widget ) || 2172 Gtk::gtk_widget_has_custom_background( widget ) || 2173 Style::instance().settings().applicationName().useFlatBackground( widget ) 2174 ) ) 2175 { options |= Blend; } 2176 2177 AnimationData data; 2178 if( d.isCellCheck() ) 2179 { 2180 2181 /* 2182 TODO: use dedicated engine to handle animations. 2183 It should use Widget and CellInfo for tagging, and work like 2184 TabWidgetState engine 2185 */ 2186 options &= ~(Focus|Hover); 2187 if( GTK_IS_TREE_VIEW( widget ) ) 2188 { 2189 GtkTreeView* treeView( GTK_TREE_VIEW( widget ) ); 2190 const Gtk::CellInfo cellInfo( treeView, x, y, w, h ); 2191 if( cellInfo.isValid() && 2192 Style::instance().animations().treeViewEngine().contains( widget ) && 2193 Style::instance().animations().treeViewEngine().isCellHovered( widget, cellInfo, false ) ) 2194 { options |= Hover; } 2195 2196 // disable active flag, which is not set properly for listviews 2197 options &= ~Active; 2198 2199 // retrieve animation state 2200 data = Style::instance().animations().treeViewStateEngine().get( widget, cellInfo, options ); 2201 2202 } 2203 2204 } else { 2205 2206 // retrieve animation state 2207 data = Style::instance().animations().widgetStateEngine().get( widget, options ); 2208 2209 } 2210 2211 if( Style::instance().settings().applicationName().isXul( widget ) ) 2212 { 2213 StyleWrapper::xulInfo().setType( XulInfo::CheckBox ); 2214 StyleWrapper::xulInfo().setRect( Gtk::gdk_rectangle( x, y, w, h ) ); 2215 } 2216 2217 Style::instance().renderCheckBox( window, clipRect, x, y, w, h, shadow, options, data ); 2218 2219 } else if( d.isCheck() && ( GTK_IS_CHECK_MENU_ITEM( widget ) || /* for LibreOffice */GTK_IS_MENU_ITEM( widget ) ) ) { 2220 2221 // Fix cliprect for LibreOffice 2222 if( clipRect && GTK_IS_MENU_ITEM(widget)) 2223 { ++clipRect->width; } 2224 2225 StyleOptions options( widget, state, shadow ); 2226 options |= (Blend|Flat|NoFill); 2227 Style::instance().renderCheckBox( window, clipRect, x, y, w, h, shadow, options ); 2228 2229 } else { 2230 2231 StyleWrapper::parentClass()->draw_check( style, window, state, 2232 shadow, clipRect, widget, detail, 2233 x, y, w, h ); 2234 } 2235 2236 } 2237 2238 //___________________________________________________________________________________________________________ 2239 static void draw_option( GtkStyle* style, 2240 GdkWindow* window, 2241 GtkStateType state, 2242 GtkShadowType shadow, 2243 GdkRectangle* clipRect, 2244 GtkWidget* widget, 2245 const gchar* detail, 2246 gint x, 2247 gint y, 2248 gint w, 2249 gint h ) 2250 { 2251 g_return_if_fail( style && window ); 2252 2253 Style::instance().sanitizeSize( window, w, h ); 2254 2255 #if OXYGEN_DEBUG 2256 std::cerr 2257 << "Oxygen::draw_option -" 2258 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2259 << " state: " << Gtk::TypeNames::state( state ) 2260 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2261 << " detail: " << (detail ? detail:"0x0" ) 2262 << std::endl; 2263 #endif 2264 2265 Gtk::Detail d( detail ); 2266 if( d.isRadioButton() ) 2267 { 2268 2269 StyleOptions options( widget, state, shadow ); 2270 2271 // this ensures that hover keeps precedence of focus for pressed down buttons 2272 if( state == GTK_STATE_ACTIVE ) options |= Hover; 2273 2274 if( !( 2275 Gtk::gtk_parent_tree_view( widget ) || 2276 Gtk::gtk_widget_has_custom_background( widget ) || 2277 Style::instance().settings().applicationName().useFlatBackground(widget) ) ) 2278 { options |= Blend; } 2279 2280 2281 2282 if( Style::instance().settings().applicationName().isXul( widget ) ) 2283 { 2284 StyleWrapper::xulInfo().setType( XulInfo::RadioButton ); 2285 StyleWrapper::xulInfo().setRect( Gtk::gdk_rectangle( x, y, w, h ) ); 2286 } 2287 2288 // retrieve animation state and render accordingly 2289 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options ) ); 2290 Style::instance().renderRadioButton( window, clipRect, x, y, w, h, shadow, options, data ); 2291 2292 } else if( d.isOption() || d.isCellRadio() ) { 2293 2294 // load options 2295 StyleOptions options( widget, state, shadow ); 2296 if( !( d.isCellRadio() || Gtk::gtk_parent_tree_view( widget ) ) ) 2297 { 2298 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 2299 { options |= Blend; } 2300 2301 if( Gtk::gtk_parent_menu( widget ) ) 2302 { 2303 2304 // add menu flag and disable Hover/Focus 2305 options|=Menu; 2306 options &= ~(Hover|Focus); 2307 x-=1; 2308 y-=1; 2309 if(Style::instance().settings().applicationName().isOpenOffice()) 2310 { 2311 // Override the sizes passed by LibreOffice and draw how we want it to look 2312 // Mostly works OK, but in scrollable menus results in glitches. But scrollable menus have 2313 // their own glitches, so this seems to be not much of a problem. 2314 clipRect=0; 2315 x-=(CheckBox_Size-w)/2; 2316 y-=(CheckBox_Size-h)/2-1; 2317 w=CheckBox_Size; 2318 h=CheckBox_Size; 2319 } 2320 } 2321 2322 } 2323 2324 AnimationData data; 2325 if( d.isCellRadio() ) 2326 { 2327 /* 2328 TODO: use dedicated engine to handle animations. 2329 It should use Widget and CellInfo for tagging, and work like 2330 TabWidgetState engine 2331 */ 2332 options &= ~(Focus|Hover); 2333 if( GTK_IS_TREE_VIEW( widget ) ) 2334 { 2335 2336 GtkTreeView* treeView( GTK_TREE_VIEW( widget ) ); 2337 Gtk::CellInfo cellInfo( treeView, x, y, w, h ); 2338 if( cellInfo.isValid() && 2339 Style::instance().animations().treeViewEngine().contains( widget ) && 2340 Style::instance().animations().treeViewEngine().isCellHovered( widget, cellInfo, false ) ) 2341 { options |= Hover; } 2342 2343 // disable active flag, which is not set properly for listviews 2344 options &= ~Active; 2345 2346 data = Style::instance().animations().treeViewStateEngine().get( widget, cellInfo, options ); 2347 2348 } 2349 2350 } 2351 2352 Style::instance().renderRadioButton( window, clipRect, x, y, w, h, shadow, options, data ); 2353 2354 } else { 2355 2356 StyleWrapper::parentClass()->draw_option( style, window, state, 2357 shadow, clipRect, widget, detail, 2358 x, y, w, h ); 2359 2360 } 2361 } 2362 2363 //___________________________________________________________________________________________________________ 2364 static void draw_hline( 2365 GtkStyle* style, 2366 GdkWindow* window, 2367 GtkStateType state, 2368 GdkRectangle* clipRect, 2369 GtkWidget* widget, 2370 const gchar* detail, 2371 gint x1, 2372 gint x2, 2373 gint y ) 2374 { 2375 g_return_if_fail( style && window ); 2376 2377 #if OXYGEN_DEBUG 2378 std::cerr 2379 << "Oxygen::draw_hline -" 2380 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2381 << " state: " << Gtk::TypeNames::state( state ) 2382 << " detail: " << (detail ? detail:"0x0" ) 2383 << std::endl; 2384 #endif 2385 2386 Gtk::Detail d( detail ); 2387 if( d.isVScale() ) 2388 { 2389 2390 return; 2391 2392 } else if( d.isToolBar() && !Style::instance().settings().toolBarDrawItemSeparator() ) { 2393 2394 return; 2395 2396 } else if( d.isTearOffMenuItem() ) { 2397 2398 if( widget && gtk_widget_get_state( widget ) != GTK_STATE_PRELIGHT ) 2399 { 2400 // render background, this is needed to prevent a plain rect to be rendered (by gtk) where the item is 2401 // rectangle is adjusted manually so that it matches 2402 if( 2403 widget && 2404 GTK_IS_MENU( gtk_widget_get_parent( widget ) ) && 2405 gtk_menu_get_tearoff_state( GTK_MENU( gtk_widget_get_parent( widget ) ) ) ) 2406 { 2407 2408 Style::instance().renderWindowBackground( window, widget, clipRect, x1-4, y-7, x2-x1+10, 20 ); 2409 2410 } else { 2411 2412 Style::instance().renderMenuBackground( window, clipRect, x1-4, y-7, x2-x1+8, 20, Menu ); 2413 } 2414 2415 } 2416 2417 // separators 2418 bool accepted( true ); 2419 if( widget ) 2420 { 2421 // do not draw side hlines because they conflict with selection rect 2422 const GtkAllocation allocation( Gtk::gtk_widget_get_allocation( widget ) ); 2423 if( x1 <= allocation.x + 5 || x2 >= allocation.x + allocation.width - 5 ) 2424 { accepted = false; } 2425 } 2426 2427 if( accepted ) 2428 { Style::instance().drawSeparator( window, clipRect, x1, y+1, x2-x1, 0, StyleOptions() ); } 2429 2430 } else { 2431 2432 StyleOptions options; 2433 if( !Gtk::gtk_parent_tree_view( widget ) ) 2434 { 2435 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 2436 { options |= Blend; } 2437 2438 if( Gtk::gtk_parent_menu( widget ) ) options |= Menu; 2439 } 2440 2441 Style::instance().drawSeparator( window, clipRect, x1, y, x2-x1, 0, options ); 2442 2443 } 2444 2445 } 2446 2447 //___________________________________________________________________________________________________________ 2448 static void draw_vline( GtkStyle* style, 2449 GdkWindow* window, 2450 GtkStateType state, 2451 GdkRectangle* clipRect, 2452 GtkWidget* widget, 2453 const gchar* detail, 2454 gint y1, 2455 gint y2, 2456 gint x ) 2457 { 2458 g_return_if_fail( style && window ); 2459 2460 #if OXYGEN_DEBUG 2461 std::cerr 2462 << "Oxygen::draw_vline -" 2463 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2464 << " state: " << Gtk::TypeNames::state( state ) 2465 << " detail: " << (detail ? detail:"0x0" ) 2466 << std::endl; 2467 #endif 2468 2469 // disable vline in buttons (should correspond to comboboxes) 2470 Gtk::Detail d( detail ); 2471 if( d.isHScale() || Gtk::gtk_parent_button( widget ) ) return; 2472 else if( d.isToolBar() && !Style::instance().settings().toolBarDrawItemSeparator() ) return; 2473 else { 2474 2475 StyleOptions options( Vertical ); 2476 if( !Gtk::gtk_parent_tree_view( widget ) ) 2477 { 2478 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 2479 { options |= Blend; } 2480 2481 if( Gtk::gtk_parent_menu( widget ) ) options |= Menu; 2482 2483 } 2484 Style::instance().drawSeparator( window, clipRect, x+1, y1, 0, y2-y1, options ); 2485 2486 } 2487 2488 } 2489 2490 //___________________________________________________________________________________________________________ 2491 static void draw_arrow( GtkStyle* style, 2492 GdkWindow* window, 2493 GtkStateType state, 2494 GtkShadowType shadow, 2495 GdkRectangle* clipRect, 2496 GtkWidget* widget, 2497 const gchar* detail, 2498 GtkArrowType arrow, 2499 gboolean fill, 2500 gint x, 2501 gint y, 2502 gint w, 2503 gint h ) 2504 { 2505 2506 g_return_if_fail( style && window ); 2507 Style::instance().sanitizeSize( window, w, h ); 2508 2509 #if OXYGEN_DEBUG 2510 std::cerr 2511 << "Oxygen::draw_arrow -" 2512 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2513 << " state: " << Gtk::TypeNames::state( state ) 2514 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2515 << " arrow: " << Gtk::TypeNames::arrow( arrow ) 2516 << " fill: " << (fill ? "true":"false") 2517 << " detail: " << (detail ? detail:"0x0" ) 2518 << std::endl; 2519 #endif 2520 2521 { 2522 // Deal with GimpScaleComboBox misplaced arrow because of entry shrinking 2523 GtkWidget* parent=gtk_widget_get_parent(widget); 2524 if(parent) parent=gtk_widget_get_parent(parent); 2525 if( parent && std::string(G_OBJECT_TYPE_NAME(parent)) == "GimpScaleComboBox") 2526 { x--; } 2527 2528 } 2529 2530 const Gtk::Detail d( detail ); 2531 2532 // by default all arrows are animated 2533 QtSettings::ArrowSize arrowSize( QtSettings::ArrowNormal ); 2534 if( d.isMenuItem() && Style::instance().settings().applicationName().isXul( widget ) ) 2535 { arrowSize = QtSettings::ArrowTiny; } 2536 2537 // define default color role 2538 Palette::Role role( Palette::ButtonText ); 2539 2540 // define options 2541 StyleOptions options( widget, state ); 2542 options |= Contrast; 2543 2544 // Arrows which are active are painted as hovered 2545 if( state == GTK_STATE_ACTIVE ) options |= Hover; 2546 2547 // animation data 2548 AnimationData data; 2549 2550 // if true, widgetStateEngine is used to decide on animation state 2551 // use either custom engine, or disable animation, otherwise 2552 bool useWidgetStateEngine( true ); 2553 2554 GtkWidget* parent( 0L ); 2555 if( d.isTearOffMenuItem() ) 2556 { 2557 if( widget && 2558 gtk_widget_get_state( widget ) != GTK_STATE_PRELIGHT && 2559 GTK_IS_MENU( gtk_widget_get_parent( widget ) ) && 2560 gtk_menu_get_tearoff_state( GTK_MENU( gtk_widget_get_parent( widget ) ) ) ) 2561 { Style::instance().renderWindowBackground( window, widget, clipRect, x-8, y-8, w+16, h+16); } 2562 2563 // disable highlight in menus, for consistancy with oxygen qt style 2564 options &= ~( Focus|Hover ); 2565 2566 useWidgetStateEngine = false; 2567 2568 } else if( d.isMenuItem() && !Gtk::gtk_parent_tree_view( widget ) ) { 2569 2570 // disable highlight in menus, for consistancy with oxygen qt style 2571 options &= ~( Focus|Hover ); 2572 role = Palette::WindowText; 2573 useWidgetStateEngine = false; 2574 2575 } else if( d.isSpinButton() ) { 2576 2577 // use dedicated engine to get animation state 2578 data = Style::instance().animations().arrowStateEngine().get( widget, arrow, options ); 2579 useWidgetStateEngine = false; 2580 2581 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) x+=1; 2582 else x-=1; 2583 2584 if( arrow == GTK_ARROW_UP && !Style::instance().settings().applicationName().isOpenOffice( widget ) ) 2585 { 2586 2587 y+= 1; 2588 2589 } 2590 2591 if( arrow == GTK_ARROW_DOWN && Style::instance().settings().applicationName().isOpenOffice( widget ) ) 2592 { 2593 2594 y-= 1; 2595 2596 } 2597 2598 // disable contrast 2599 options &= ~Contrast; 2600 2601 role = Palette::Text; 2602 2603 } else if( d.isNotebook() ) { 2604 2605 // use dedicated engine to get animation state 2606 data = Style::instance().animations().arrowStateEngine().get( widget, arrow, options ); 2607 useWidgetStateEngine = false; 2608 2609 if( GTK_IS_NOTEBOOK( widget ) ) 2610 { 2611 const int offset = 6; 2612 switch( gtk_notebook_get_tab_pos( GTK_NOTEBOOK( widget ) ) ) 2613 { 2614 default: 2615 case GTK_POS_TOP: h += offset; break; 2616 case GTK_POS_LEFT: w += offset; break; 2617 case GTK_POS_BOTTOM: y-=offset; h+=offset; break; 2618 case GTK_POS_RIGHT: x -= offset; w += offset; break; 2619 } 2620 } 2621 2622 role = Palette::WindowText; 2623 2624 } else if( Gtk::gtk_parent_combobox_entry( widget ) ) { 2625 2626 if( state != GTK_STATE_INSENSITIVE ) options &= ~Contrast; 2627 role = Palette::Text; 2628 2629 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 2630 { x+=2; } 2631 2632 } else if( Gtk::gtk_parent_combo( widget ) ) { 2633 2634 role = Palette::WindowText; 2635 2636 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 2637 { x+=2; } 2638 2639 } else if( ( parent = Gtk::gtk_parent_combobox( widget ) ) ) { 2640 2641 useWidgetStateEngine = false; 2642 2643 options &= ~( Focus|Hover ); 2644 role = Palette::ButtonText; 2645 2646 if( Gtk::gtk_widget_layout_is_reversed( widget ) ) 2647 { x+=2; } 2648 2649 } else if( ( parent = Gtk::gtk_parent_button( widget ) ) ) { 2650 2651 2652 if(!Gtk::gtk_parent_tree_view( widget ) && 2653 !Gtk::gtk_parent_combo( widget ) ) 2654 { 2655 2656 useWidgetStateEngine = false; 2657 options &= ~( Focus|Hover ); 2658 2659 if( d.isArrow() && GTK_IS_ARROW( widget ) ) 2660 { 2661 2662 x += 1; 2663 role = Palette::WindowText; 2664 } 2665 2666 } else if( Gtk::gtk_button_is_header( parent ) && Style::instance().settings().viewInvertSortIndicator() ) { 2667 2668 arrow = (arrow == GTK_ARROW_UP) ? GTK_ARROW_DOWN:GTK_ARROW_UP; 2669 2670 } 2671 2672 } else if( GTK_IS_CALENDAR( widget ) ) { 2673 2674 // FIXME: needs dedicated engine to 2675 // handle smooth animations 2676 useWidgetStateEngine = false; 2677 2678 if( !Gtk::gtk_widget_is_applet( widget ) ) 2679 { 2680 2681 // need to render background behind arrows from calendar 2682 // offsets are empirical 2683 Style::instance().renderWindowBackground( window, widget, clipRect, x-2, y-3, w+4, h+6 ); 2684 role = Palette::WindowText; 2685 2686 } 2687 2688 } else if( GTK_IS_SCROLLBAR( widget ) ) { 2689 2690 // use dedicated engine to get animation state 2691 useWidgetStateEngine = false; 2692 data = Style::instance().animations().scrollBarStateEngine().get( widget, Gtk::gdk_rectangle( x, y, w, h ), arrow, options ); 2693 role = Palette::WindowText; 2694 2695 } 2696 2697 // render arrow 2698 if( useWidgetStateEngine ) data = Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover ); 2699 Style::instance().renderArrow( window, clipRect, arrow, x, y, w, h, arrowSize, options, data, role ); 2700 2701 } 2702 2703 2704 //___________________________________________________________________________________________________________ 2705 static void draw_expander( 2706 GtkStyle* style, 2707 GdkWindow* window, 2708 GtkStateType state, 2709 GdkRectangle* clipRect, 2710 GtkWidget* widget, 2711 const char* detail, 2712 gint x, 2713 gint y, 2714 GtkExpanderStyle expanderStyle ) 2715 { 2716 g_return_if_fail( style && window ); 2717 2718 #if OXYGEN_DEBUG 2719 std::cerr 2720 << "Oxygen::draw_expander -" 2721 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2722 << " state: " << Gtk::TypeNames::state( state ) 2723 << " expander: " << Gtk::TypeNames::expanderStyle( expanderStyle ) 2724 << " detail: " << (detail ? detail:"0x0" ) 2725 << std::endl; 2726 #endif 2727 2728 StyleOptions options( widget, state ); 2729 const Gtk::Detail d( detail ); 2730 const Palette::Role role( d.isTreeView() ? Palette::Text : Palette::WindowText ); 2731 2732 /* 2733 TODO: For TreeViews, use dedicated engine to handle animations. 2734 It should use Widget and CellInfo for tagging, and work like 2735 TabWidgetState engine. 2736 */ 2737 AnimationData data; 2738 if( d.isTreeView() && GTK_IS_TREE_VIEW( widget ) ) 2739 { 2740 GtkTreeView* treeView( GTK_TREE_VIEW( widget ) ); 2741 const Gtk::CellInfo cellInfo( treeView, x-3, y-4, 10, 10 ); 2742 data = Style::instance().animations().treeViewStateEngine().get( widget, cellInfo, options ); 2743 } 2744 2745 if( Style::instance().settings().viewDrawTriangularExpander() ) 2746 { 2747 2748 GtkArrowType arrow; 2749 const bool isExpanded( expanderStyle !=GTK_EXPANDER_COLLAPSED && expanderStyle != GTK_EXPANDER_SEMI_COLLAPSED ); 2750 if( isExpanded ) arrow = GTK_ARROW_DOWN; 2751 else if( Gtk::gtk_widget_layout_is_reversed( widget ) ) arrow = GTK_ARROW_LEFT; 2752 else arrow = GTK_ARROW_RIGHT; 2753 2754 const Gtk::Detail d( detail ); 2755 if( d.isTreeView() ) 2756 { 2757 2758 const QtSettings::ArrowSize arrowSize = Style::instance().settings().viewTriangularExpanderSize(); 2759 Style::instance().renderArrow( window, clipRect, arrow, x-3, y-4, 10, 10, arrowSize, options, data, role ); 2760 2761 } else { 2762 2763 options |= Contrast; 2764 const QtSettings::ArrowSize arrowSize = QtSettings::ArrowNormal; 2765 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover ) ); 2766 Style::instance().renderArrow( window, clipRect, arrow, x-3, y-5, 10, 10, arrowSize, options, data, role ); 2767 2768 } 2769 2770 } else if( d.isTreeView() ) { 2771 2772 Style::instance().renderTreeExpander( window, clipRect, x-3, y-4, 10, 10, expanderStyle, options, data, role ); 2773 2774 } else { 2775 2776 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover ) ); 2777 Style::instance().renderTreeExpander( window, clipRect, x-3, y-5, 10, 10, expanderStyle, options, data, role ); 2778 2779 } 2780 2781 } 2782 2783 //___________________________________________________________________________________________________________ 2784 static void draw_diamond( GtkStyle* style, 2785 GdkWindow* window, 2786 GtkStateType state, 2787 GtkShadowType shadow, 2788 GdkRectangle* clipRect, 2789 GtkWidget* widget, 2790 const char* detail, 2791 gint x, 2792 gint y, 2793 gint w, 2794 gint h ) 2795 { 2796 g_return_if_fail( style && window ); 2797 Style::instance().sanitizeSize( window, w, h ); 2798 2799 #if OXYGEN_DEBUG 2800 std::cerr 2801 << "Oxygen::draw_diamond -" 2802 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2803 << " state: " << Gtk::TypeNames::state( state ) 2804 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2805 << " detail: " << (detail ? detail:"0x0" ) 2806 << std::endl; 2807 #endif 2808 2809 StyleWrapper::parentClass()->draw_diamond( style, window, state, 2810 shadow, clipRect, widget, detail, 2811 x, y, w, h ); 2812 } 2813 2814 //___________________________________________________________________________________________________________ 2815 static void draw_tab( GtkStyle* style, 2816 GdkWindow* window, 2817 GtkStateType state, 2818 GtkShadowType shadow, 2819 GdkRectangle* clipRect, 2820 GtkWidget* widget, 2821 const char* detail, 2822 gint x, 2823 gint y, 2824 gint w, 2825 gint h ) 2826 { 2827 g_return_if_fail( style && window ); 2828 2829 Style::instance().sanitizeSize( window, w, h ); 2830 2831 #if OXYGEN_DEBUG 2832 std::cerr 2833 << "Oxygen::draw_tab -" 2834 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2835 << " state: " << Gtk::TypeNames::state( state ) 2836 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2837 << " detail: " << (detail ? detail:"0x0" ) 2838 << std::endl; 2839 #endif 2840 2841 Gtk::Detail d( detail ); 2842 if( d.isOptionMenuTab() ) 2843 { 2844 2845 // render 2846 GtkArrowType arrow = GTK_ARROW_DOWN; 2847 QtSettings::ArrowSize arrowSize = QtSettings::ArrowNormal; 2848 StyleOptions options( widget, state, shadow ); 2849 options |= Contrast; 2850 2851 // disable hover and focus 2852 options &= ~(Hover|Focus); 2853 2854 Style::instance().renderArrow( window, clipRect, arrow, x, y, w, h, arrowSize, options ); 2855 return; 2856 2857 } else { 2858 2859 StyleWrapper::parentClass()->draw_tab( style, window, state, 2860 shadow, clipRect, widget, detail, 2861 x, y, w, h ); 2862 } 2863 2864 } 2865 2866 //___________________________________________________________________________________________________________ 2867 static void draw_shadow_gap( GtkStyle* style, 2868 GdkWindow* window, 2869 GtkStateType state, 2870 GtkShadowType shadow, 2871 GdkRectangle* clipRect, 2872 GtkWidget* widget, 2873 const gchar* detail, 2874 gint x, 2875 gint y, 2876 gint w, 2877 gint h, 2878 GtkPositionType position, 2879 gint gap_x, 2880 gint gap_w ) 2881 { 2882 g_return_if_fail( style && window ); 2883 2884 Style::instance().sanitizeSize( window, w, h ); 2885 2886 #if OXYGEN_DEBUG 2887 std::cerr 2888 << "Oxygen::draw_shadow_gap -" 2889 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2890 << " state: " << Gtk::TypeNames::state( state ) 2891 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2892 << " position: " << Gtk::TypeNames::position( position ) 2893 << " detail: " << (detail ? detail:"0x0" ) 2894 << std::endl; 2895 #endif 2896 2897 Gtk::Detail d( detail ); 2898 if( d.isFrame() ) 2899 { 2900 2901 const Gtk::Gap gap( gap_x, gap_w, position ); 2902 if( shadow == GTK_SHADOW_IN ) 2903 { 2904 2905 const int sideMargin( std::max( 0, style->xthickness - 2 ) ); 2906 Style::instance().renderHoleBackground( window, widget, clipRect, x-1-sideMargin, y-1, w+2+2*sideMargin, h+2, TileSet::Full, sideMargin ); 2907 Style::instance().renderHole( window, clipRect, x-1, y-1, w+2, h+1, gap, NoFill ); 2908 2909 } else if( shadow == GTK_SHADOW_OUT ) { 2910 2911 Style::instance().renderSlab( window, clipRect, x-1, y-4, w+2, h+4, gap, NoFill ); 2912 2913 } else if( shadow == GTK_SHADOW_ETCHED_IN || shadow == GTK_SHADOW_ETCHED_OUT ) { 2914 2915 Style::instance().renderDockFrame( window, clipRect, x, y-1, w, h+1, gap, Blend ); 2916 2917 } 2918 2919 return; 2920 2921 } else { 2922 2923 StyleWrapper::parentClass()->draw_shadow_gap( style, window, state, 2924 shadow, clipRect, widget, detail, 2925 x, y, w, h, 2926 position, gap_x, gap_w ); 2927 } 2928 2929 } 2930 2931 //___________________________________________________________________________________________________________ 2932 static void draw_box_gap( GtkStyle* style, 2933 GdkWindow* window, 2934 GtkStateType state, 2935 GtkShadowType shadow, 2936 GdkRectangle* clipRect, 2937 GtkWidget* widget, 2938 const gchar* detail, 2939 gint x, 2940 gint y, 2941 gint w, 2942 gint h, 2943 GtkPositionType position, 2944 gint gap_x, 2945 gint gap_w ) 2946 { 2947 g_return_if_fail( style && window ); 2948 2949 Style::instance().sanitizeSize( window, w, h ); 2950 2951 #if OXYGEN_DEBUG 2952 std::cerr 2953 << "Oxygen::draw_box_gap -" 2954 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 2955 << " state: " << Gtk::TypeNames::state( state ) 2956 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 2957 << " position: " << Gtk::TypeNames::position( position ) 2958 << " detail: " << (detail ? detail:"0x0" ) 2959 << std::endl; 2960 #endif 2961 2962 const Gtk::Detail d( detail ); 2963 if( d.isNotebook() ) 2964 { 2965 2966 // this might move to drawShadowGap 2967 StyleOptions options( widget, GTK_STATE_NORMAL, shadow ); 2968 options |= NoFill; 2969 options &= ~(Hover|Focus); 2970 2971 if( Style::instance().settings().applicationName().isXul( widget ) ) 2972 { 2973 2974 Gtk::Gap gap( gap_x, gap_w, position ); 2975 2976 /* 2977 firefox calls box_gap twice. Once for the main frame, once for the actual gap 2978 the second call must be discarded somehow 2979 */ 2980 if( h>12 ) 2981 { Style::instance().renderSlab( window, clipRect, x, y-3, w, h-4, gap, options ); } 2982 2983 } else { 2984 2985 if( GTK_IS_NOTEBOOK( widget ) && !Gtk::gdk_default_screen_is_composited() ) 2986 { 2987 2988 // this trick ensures that tabbar is always redrawn 2989 Style::instance().animations().tabWidgetEngine().registerWidget( widget ); 2990 Style::instance().animations().tabWidgetEngine().toggleDirty( widget ); 2991 2992 } 2993 2994 Gtk::Gap gap; 2995 2996 // need adjustment depending on gap side 2997 const int adjust = 2; 2998 switch( position ) 2999 { 3000 3001 case GTK_POS_TOP: 3002 gap = Gtk::Gap( 0, w+2, position ); 3003 y -= adjust; 3004 h += adjust; 3005 break; 3006 3007 case GTK_POS_BOTTOM: 3008 gap = Gtk::Gap( 0, w+2, position ); 3009 h += adjust; 3010 break; 3011 3012 case GTK_POS_LEFT: 3013 gap = Gtk::Gap( 0, h+2, position ); 3014 x -= adjust; 3015 w += adjust; 3016 break; 3017 3018 case GTK_POS_RIGHT: 3019 gap = Gtk::Gap( 0, h+2, position ); 3020 w += adjust; 3021 break; 3022 3023 default: return; 3024 3025 } 3026 3027 if(Style::instance().settings().applicationName().isOpenOffice()) 3028 gap.setHeight( 0 ); 3029 else 3030 gap.setHeight( 8 ); 3031 Style::instance().renderTabBarFrame( window, clipRect, x-1, y-1, w+2, h+2, gap, options ); 3032 3033 } 3034 3035 } else { 3036 3037 StyleWrapper::parentClass()->draw_box_gap( style, window, state, 3038 shadow, clipRect, widget, detail, 3039 x, y, w, h, 3040 position, gap_x, gap_w ); 3041 } 3042 3043 } 3044 3045 //___________________________________________________________________________________________________________ 3046 static void draw_slider( GtkStyle* style, 3047 GdkWindow* window, 3048 GtkStateType state, 3049 GtkShadowType shadow, 3050 GdkRectangle* clipRect, 3051 GtkWidget* widget, 3052 const gchar* detail, 3053 gint x, 3054 gint y, 3055 gint w, 3056 gint h, 3057 GtkOrientation orientation ) 3058 { 3059 g_return_if_fail( style && window ); 3060 Style::instance().sanitizeSize( window, w, h ); 3061 3062 #if OXYGEN_DEBUG 3063 std::cerr 3064 << "Oxygen::draw_slider -" 3065 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3066 << " state: " << Gtk::TypeNames::state( state ) 3067 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 3068 << " orientation: " << Gtk::TypeNames::orientation( orientation ) 3069 << " detail: " << (detail ? detail:"0x0" ) 3070 << std::endl; 3071 #endif 3072 3073 Gtk::Detail d( detail ); 3074 if( d.isScale() ) 3075 { 3076 3077 StyleOptions options( widget, state, shadow ); 3078 3079 if(!Style::instance().settings().applicationName().useFlatBackground( widget )) 3080 { options |= Blend; } 3081 3082 if( GTK_IS_VSCALE( widget ) ) options |= Vertical; 3083 3084 // retrieve animation state and render accordingly 3085 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options ) ); 3086 Style::instance().renderSliderHandle( window, clipRect, x, y, w, h, options, data ); 3087 3088 return; 3089 3090 } else if( GTK_IS_VSCROLLBAR( widget ) ) { 3091 3092 StyleOptions options( widget, state, shadow ); 3093 if( options&Sunken ) options |= Hover; 3094 options |= Vertical; 3095 3096 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover ) ); 3097 Style::instance().renderScrollBarHandle( window, clipRect, x, y, w-1, h, options, data ); 3098 3099 } else if( GTK_IS_HSCROLLBAR( widget ) ) { 3100 3101 StyleOptions options( widget, state, shadow ); 3102 if( options&Sunken ) options |= Hover; 3103 3104 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, options, AnimationHover ) ); 3105 Style::instance().renderScrollBarHandle( window, clipRect, x, y, w, h-1, options, data ); 3106 3107 } else { 3108 3109 StyleWrapper::parentClass()->draw_slider( style, window, state, 3110 shadow, clipRect, widget, detail, 3111 x, y, w, h, 3112 orientation ); 3113 } 3114 3115 } 3116 3117 //___________________________________________________________________________________________________________ 3118 static void draw_extension( GtkStyle* style, 3119 GdkWindow* window, 3120 GtkStateType state, 3121 GtkShadowType shadow, 3122 GdkRectangle* clipRect, 3123 GtkWidget* widget, 3124 const gchar* detail, 3125 gint x, 3126 gint y, 3127 gint w, 3128 gint h, 3129 GtkPositionType position ) 3130 { 3131 3132 g_return_if_fail( style && window ); 3133 3134 Style::instance().sanitizeSize( window, w, h ); 3135 3136 #if OXYGEN_DEBUG 3137 std::cerr 3138 << "Oxygen::draw_extension -" 3139 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3140 << " state: " << Gtk::TypeNames::state( state ) 3141 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 3142 << " position: " << Gtk::TypeNames::position( position ) 3143 << " detail: " << (detail ? detail:"0x0" ) 3144 << std::endl; 3145 #endif 3146 3147 Gtk::Detail d( detail ); 3148 3149 // Will be used for LibreOffice 3150 bool prelight(g_object_get_data(G_OBJECT(window),"libreoffice-tab-is-prelit")); 3151 3152 if( d.isTab() ) 3153 { 3154 StyleOptions options( widget, state, shadow ); 3155 if(prelight) 3156 options|=Hover; 3157 TabOptions tabOptions( widget, state, position, x, y, w, h ); 3158 3159 const bool isCurrentTab( tabOptions & CurrentTab ); 3160 bool drawTabBarBase( isCurrentTab ); 3161 bool dragInProgress( false ); 3162 3163 /* 3164 see if tab is hovered. This is only done if widget is notebook, and if not running a mozilla 3165 (or open office) app, because the latter do not pass the actual tab rect as argument 3166 */ 3167 const bool isXul( Style::instance().settings().applicationName().isXul( widget ) ); 3168 const bool isOpenOffice( Style::instance().settings().applicationName().isOpenOffice( widget ) ); 3169 3170 // if passed window is invalid, do not hover 3171 const bool disableHover( !GDK_IS_WINDOW( window ) ); 3172 3173 AnimationData data; 3174 if( GTK_IS_NOTEBOOK( widget ) && !( isXul || isOpenOffice || disableHover ) ) 3175 { 3176 3177 // make sure widget is registered 3178 Style::instance().animations().tabWidgetEngine().registerWidget( widget ); 3179 3180 // get current tab, update tabRect and see if current tab is hovered 3181 const int tabIndex( Gtk::gtk_notebook_find_tab( widget, x+w/2, y+h/2 ) ); 3182 Style::instance().animations().tabWidgetEngine().updateTabRect( widget, tabIndex, x, y, w, h ); 3183 if( tabIndex == Style::instance().animations().tabWidgetEngine().hoveredTab( widget ) ) 3184 { options |= Hover; } 3185 3186 // check tab position and add relevant option flags 3187 GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); 3188 if( tabIndex == 0 ) tabOptions |= FirstTab; 3189 if( tabIndex == gtk_notebook_get_n_pages( notebook ) - 1 ) tabOptions |= LastTab; 3190 3191 const int current( gtk_notebook_get_current_page( notebook ) ); 3192 if( tabIndex == current-1 ) tabOptions |= LeftOfSelected; 3193 else if( tabIndex == current+1 ) tabOptions |= RightOfSelected; 3194 3195 // update drag in progress flag 3196 if( isCurrentTab ) 3197 { 3198 bool drag( widget && (window != gtk_widget_get_window( widget ) ) ); 3199 Style::instance().animations().tabWidgetEngine().setDragInProgress( widget, drag ); 3200 } 3201 3202 dragInProgress = Style::instance().animations().tabWidgetEngine().dragInProgress( widget ); 3203 3204 // this does not work when the first tab is being grabbed 3205 if( dragInProgress ) 3206 { 3207 int firstTabIndex( Gtk::gtk_notebook_find_first_tab( widget ) ); 3208 int focusTabIndex( gtk_notebook_get_current_page( notebook ) ); 3209 drawTabBarBase = (tabIndex == firstTabIndex && !isCurrentTab ) || (firstTabIndex == focusTabIndex && tabIndex == firstTabIndex+1 ); 3210 } 3211 3212 if( !isCurrentTab ) 3213 { data = Style::instance().animations().tabWidgetStateEngine().get( widget, tabIndex, options ); } 3214 3215 } 3216 3217 if( isOpenOffice ) 3218 { x+=1; } 3219 3220 // render 3221 if( isXul ) tabOptions |= Xul; 3222 3223 Style::instance().renderTab( window, clipRect, x, y, w, h, position, options, tabOptions, data ); 3224 3225 // render tabbar base if current tab 3226 if( !isOpenOffice && drawTabBarBase ) 3227 { 3228 3229 const GtkAllocation allocation( Gtk::gtk_widget_get_allocation( widget ) ); 3230 int borderWidth( GTK_IS_CONTAINER( widget ) ? gtk_container_get_border_width( GTK_CONTAINER( widget ) ):0 ); 3231 int xBase( allocation.x + borderWidth ); 3232 int yBase( allocation.y + borderWidth ); 3233 int wBase( allocation.width - 2*borderWidth ); 3234 int hBase( allocation.height - 2*borderWidth ); 3235 3236 Gtk::Gap gap; 3237 switch( position ) 3238 { 3239 case GTK_POS_BOTTOM: 3240 case GTK_POS_TOP: 3241 if( !dragInProgress ) gap = Gtk::Gap( x - xBase + 5, w - 6, position ); 3242 yBase = y; 3243 hBase = h; 3244 break; 3245 3246 case GTK_POS_LEFT: 3247 case GTK_POS_RIGHT: 3248 if( !dragInProgress ) gap = Gtk::Gap( y - yBase + 5, h - 6, position ); 3249 xBase = x; 3250 wBase = w; 3251 break; 3252 3253 default: break; 3254 3255 } 3256 3257 gap.setHeight( 8 ); 3258 3259 Style::instance().renderTabBarBase( window, clipRect, xBase-1, yBase-1, wBase+2, hBase+2, position, gap, options, tabOptions ); 3260 3261 } 3262 else if(isOpenOffice && !clipRect ) 3263 { 3264 options&=~Hover; 3265 Cairo::Context context(window); 3266 const ColorUtils::Rgba base( Style::instance().settings().palette().color( Palette::Window ) ); 3267 3268 if(position==GTK_POS_BOTTOM) 3269 { 3270 if(isCurrentTab) 3271 { 3272 cairo_rectangle(context,x,y,w,h); 3273 cairo_rectangle_negative(context, x+4, y, w-8, h); 3274 cairo_clip(context); 3275 ++y; 3276 } 3277 Style::instance().helper().slab( base, 0 ).render( context, x-8, y+h-4, w+17, 15, TileSet::Top ); 3278 } 3279 else if(position==GTK_POS_TOP) 3280 { 3281 if(isCurrentTab) 3282 { 3283 cairo_rectangle(context,x-1,y,w+2,h); 3284 cairo_rectangle_negative(context, x+3, y, w-6, h); 3285 cairo_clip(context); 3286 y+=4; 3287 } 3288 Style::instance().helper().slab( base, 0 ).render( context, x-8, y-15, w+17, 16, TileSet::Bottom ); 3289 } 3290 } 3291 3292 if( GTK_IS_NOTEBOOK( widget ) ) 3293 { Gtk::gtk_notebook_update_close_buttons(GTK_NOTEBOOK(widget)); } 3294 3295 } 3296 3297 } 3298 3299 //___________________________________________________________________________________________________________ 3300 static void draw_focus( 3301 GtkStyle* style, 3302 GdkWindow* window, 3303 GtkStateType state, 3304 GdkRectangle* clipRect, 3305 GtkWidget* widget, 3306 const char* detail, 3307 gint x, 3308 gint y, 3309 gint w, 3310 gint h ) 3311 { 3312 3313 g_return_if_fail( style && window ); 3314 3315 Style::instance().sanitizeSize( window, w, h ); 3316 3317 #if OXYGEN_DEBUG 3318 std::cerr 3319 << "Oxygen::draw_focus -" 3320 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3321 << " state: " << Gtk::TypeNames::state( state ) 3322 << " detail: " << (detail ? detail:"0x0" ) 3323 << std::endl; 3324 #endif 3325 3326 Gtk::Detail d( detail ); 3327 3328 // special handling of Xul checkboxes and radio buttons 3329 if( Style::instance().settings().applicationName().isXul() && (d.isCheckButton() || d.isRadioButton() ) && !gtk_widget_has_focus( widget ) ) 3330 { 3331 3332 // try set correct rectangle based on last call to either draw_check or draw_option 3333 bool forceRadioButton( false ); 3334 if( StyleWrapper::xulInfo().isValid() ) 3335 { 3336 3337 forceRadioButton = StyleWrapper::xulInfo().type() == XulInfo::RadioButton; 3338 3339 x = StyleWrapper::xulInfo().rect().x; 3340 y = StyleWrapper::xulInfo().rect().y; 3341 w = StyleWrapper::xulInfo().rect().width; 3342 h = StyleWrapper::xulInfo().rect().height; 3343 clipRect = 0L; 3344 3345 // clear Xul info 3346 StyleWrapper::xulInfo().clear(); 3347 3348 } else { 3349 3350 return; 3351 3352 } 3353 3354 // Render focus here, since XUL apps don't let us figure out focused state in draw_box() etc. 3355 if( ( d.isRadioButton() && GTK_IS_RADIO_BUTTON(widget) ) || ( d.isCheckButton() && GTK_IS_CHECK_BUTTON(widget) && forceRadioButton ) ) 3356 { 3357 3358 Style::instance().renderRadioButton(window,clipRect, x, y, w, h, GTK_SHADOW_NONE,Focus|NoFill,AnimationData()); 3359 return; 3360 3361 } else if( d.isCheckButton() && GTK_IS_CHECK_BUTTON(widget) ) { 3362 3363 Style::instance().renderSlab(window,clipRect, x-1, y-1 ,w+3, h+3, Focus|NoFill,AnimationData()); 3364 return; 3365 3366 } 3367 3368 } 3369 3370 if( d.isNull() && GTK_IS_WINDOW( widget ) ) 3371 { 3372 3373 // TODO: implement something better 3374 return StyleWrapper::parentClass()->draw_focus( style, window, state, 3375 clipRect, widget, detail, 3376 x, y, w, h ); 3377 3378 } 3379 3380 return; 3381 3382 } 3383 3384 3385 //___________________________________________________________________________________________________________ 3386 static void draw_handle( GtkStyle* style, 3387 GdkWindow* window, 3388 GtkStateType state, 3389 GtkShadowType shadow, 3390 GdkRectangle* clipRect, 3391 GtkWidget* widget, 3392 const gchar* detail, 3393 gint x, 3394 gint y, 3395 gint w, 3396 gint h, 3397 GtkOrientation orientation ) 3398 { 3399 g_return_if_fail( style && window ); 3400 3401 Style::instance().sanitizeSize( window, w, h ); 3402 3403 #if OXYGEN_DEBUG 3404 std::cerr 3405 << "Oxygen::draw_handle -" 3406 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3407 << " state: " << Gtk::TypeNames::state( state ) 3408 << " shadow: " << Gtk::TypeNames::shadow( shadow ) 3409 << " orientation: " << Gtk::TypeNames::orientation( orientation ) 3410 << " detail: " << (detail ? detail:"0x0" ) 3411 << std::endl; 3412 #endif 3413 3414 Gtk::Detail d( detail ); 3415 if( d.isPaned() ) 3416 { 3417 3418 Style::instance().animations().panedEngine().registerWidget( widget ); 3419 3420 StyleOptions options( widget, state, shadow ); 3421 if( GTK_IS_VPANED( widget ) ) 3422 { 3423 options |= Vertical; 3424 3425 } else if( Gtk::g_object_is_a( G_OBJECT( widget ), "GtkPizza" ) ) { 3426 3427 Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h ); 3428 if( w>h ) options |= Vertical; 3429 3430 } 3431 3432 const AnimationData data( Style::instance().animations().widgetStateEngine().get( widget, Gtk::gdk_rectangle( x, y, w, h ), options, AnimationHover ) ); 3433 Style::instance().renderSplitter( window, 0L, x, y, w, h, options, data ); 3434 3435 } else if( d.isHandleBox() ) { 3436 3437 if( !Gtk::gtk_widget_is_applet( widget ) ) 3438 { 3439 Style::instance().renderWindowBackground( window, widget, clipRect, x, y, w, h ); 3440 } 3441 3442 StyleOptions options( widget, state, shadow ); 3443 if( orientation == GTK_ORIENTATION_VERTICAL ) options |= Vertical; 3444 Style::instance().renderToolBarHandle( window, clipRect, x, y, w, h, options ); 3445 3446 } else { 3447 3448 StyleWrapper::parentClass()->draw_handle( style, window, state, 3449 shadow, clipRect, widget, detail, 3450 x, y, w, h, 3451 orientation ); 3452 } 3453 3454 } 3455 3456 //___________________________________________________________________________________________________________ 3457 static void draw_resize_grip( 3458 GtkStyle* style, 3459 GdkWindow* window, 3460 GtkStateType state, 3461 GdkRectangle* clipRect, 3462 GtkWidget* widget, 3463 const char* detail, 3464 GdkWindowEdge edge, 3465 gint x, 3466 gint y, 3467 gint w, 3468 gint h ) 3469 { 3470 g_return_if_fail( style && window ); 3471 3472 #if OXYGEN_DEBUG 3473 std::cerr 3474 << "Oxygen::draw_resize_grip -" 3475 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3476 << " state: " << Gtk::TypeNames::state( state ) 3477 << " edge: " << Gtk::TypeNames::windowEdge( edge ) 3478 << " detail: " << (detail ? detail:"0x0" ) 3479 << std::endl; 3480 #endif 3481 3482 // no resize grip in oxygen no matter what 3483 return; 3484 } 3485 3486 //___________________________________________________________ 3487 static GdkPixbuf* render_stated_pixbuf( GdkPixbuf* source, GtkStateType state, bool useEffect ) 3488 { 3489 3490 #if OXYGEN_DEBUG 3491 std::cerr 3492 << "Oxygen::render_stated_pixbuf -" 3493 << " state: " << Gtk::TypeNames::state( state ) 3494 << " useEffect: " << useEffect 3495 << std::endl; 3496 #endif 3497 3498 // first make a copy 3499 GdkPixbuf* stated( source ); 3500 if( state == GTK_STATE_INSENSITIVE ) 3501 { 3502 3503 stated = Gtk::gdk_pixbuf_set_alpha( source, 0.3 ); 3504 gdk_pixbuf_saturate_and_pixelate( stated, stated, 0.1, false ); 3505 3506 } else if( useEffect && state == GTK_STATE_PRELIGHT ) { 3507 3508 stated = gdk_pixbuf_copy( source ); 3509 if(!Gtk::gdk_pixbuf_to_gamma( stated, 0.7 ) ) 3510 { 3511 // FIXME: correct the value to match KDE 3512 /* 3513 in fact KDE allows one to set many different effects on icon 3514 not sure we want to copy this code all over the place, especially since nobody changes the default settings, 3515 as far as I know */ 3516 gdk_pixbuf_saturate_and_pixelate( source, stated, 1.2, false ); 3517 } 3518 3519 } 3520 3521 return stated; 3522 } 3523 3524 //___________________________________________________________ 3525 static GdkPixbuf* render_icon( 3526 GtkStyle* style, 3527 const GtkIconSource* source, 3528 GtkTextDirection, 3529 GtkStateType state, 3530 GtkIconSize size, 3531 GtkWidget* widget, 3532 const char* detail ) 3533 { 3534 3535 #if OXYGEN_DEBUG 3536 const char* filename( source ? gtk_icon_source_get_filename( source ) : 0L ); 3537 const char* iconname( source ? gtk_icon_source_get_icon_name( source ) : 0L ); 3538 std::cerr 3539 << "Oxygen::render_icon -" 3540 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3541 << " state: " << Gtk::TypeNames::state( state ) 3542 << " file name: " << (filename ? filename:"0x0") 3543 << " icon name: " << (iconname ? iconname:"0x0") 3544 << " icon size: " << Gtk::TypeNames::iconSize( size ) 3545 << " detail: " << (detail ? detail:"0x0" ) 3546 << std::endl; 3547 #endif 3548 3549 GdkPixbuf* base_pixbuf( gtk_icon_source_get_pixbuf( source ) ); 3550 g_return_val_if_fail( base_pixbuf != 0L, 0L ); 3551 3552 // retrieve screen and settings 3553 GdkScreen *screen( 0L ); 3554 GtkSettings *settings( 0L ); 3555 if( widget && gtk_widget_has_screen( widget ) ) 3556 { 3557 3558 screen = gtk_widget_get_screen( widget ); 3559 settings = gtk_settings_get_for_screen( screen ); 3560 3561 } else if (style->colormap) { 3562 3563 screen = gdk_colormap_get_screen( style->colormap ); 3564 settings = gtk_settings_get_for_screen( screen ); 3565 3566 } else { 3567 3568 settings = gtk_settings_get_default(); 3569 3570 } 3571 3572 int width = 1; 3573 int height = 1; 3574 if( size != (GtkIconSize)-1 && !gtk_icon_size_lookup_for_settings( settings, size, &width, &height ) ) 3575 { 3576 g_warning (G_STRLOC ": invalid icon size '%d'", size); 3577 return 0L; 3578 } 3579 3580 /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise, 3581 * leave it alone. */ 3582 GdkPixbuf *scaled( 0L); 3583 if( size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded( source ) ) 3584 { 3585 3586 scaled = Gtk::gdk_pixbuf_resize( base_pixbuf, width, height ); 3587 3588 } else { 3589 3590 scaled = static_cast<GdkPixbuf*>( g_object_ref( base_pixbuf ) ); 3591 3592 } 3593 3594 if( !gtk_icon_source_get_state_wildcarded( source ) ) return scaled; 3595 else { 3596 3597 // non-flat pushbuttons don't have any icon effect 3598 const bool useEffect( Style::instance().settings().useIconEffect() && Gtk::gtk_button_is_flat( Gtk::gtk_parent_button( widget ) ) ); 3599 3600 /* If the state was wildcarded, then generate a state. */ 3601 GdkPixbuf *stated( render_stated_pixbuf( scaled, state, useEffect ) ); 3602 3603 // clean-up 3604 if( stated != scaled ) 3605 { g_object_unref( scaled ); } 3606 3607 // return 3608 return stated; 3609 3610 } 3611 3612 } 3613 3614 //___________________________________________________________________________________________________________ 3615 static void draw_layout( 3616 GtkStyle* style, 3617 GdkWindow* window, 3618 GtkStateType state, 3619 gboolean use_text, 3620 GdkRectangle* clipRect, 3621 GtkWidget* widget, 3622 const gchar* detail, 3623 gint x, gint y, 3624 PangoLayout* layout) 3625 { 3626 3627 #if OXYGEN_DEBUG 3628 std::cerr 3629 << "Oxygen::draw_layout -" 3630 << " widget: " << widget << " (" << (widget ? G_OBJECT_TYPE_NAME( widget ):"0x0") << ")" 3631 << " state: " << Gtk::TypeNames::state( state ) 3632 << " detail: " << (detail ? detail:"0x0" ) 3633 << std::endl; 3634 #endif 3635 3636 const Gtk::Detail d(detail); 3637 3638 // draw progressbar text white if above indicator, black if not 3639 if( GTK_IS_PROGRESS( widget ) || GTK_IS_PROGRESS_BAR( widget ) || d.isProgressBar() ) 3640 { 3641 Cairo::Context context( window,clipRect ); 3642 if(state==GTK_STATE_PRELIGHT) gdk_cairo_set_source_color(context, &style->text[GTK_STATE_SELECTED]); 3643 else gdk_cairo_set_source_color(context, &style->text[state]); 3644 cairo_translate(context,x,y); 3645 pango_cairo_show_layout(context,layout); 3646 return; 3647 } 3648 3649 if( state == GTK_STATE_INSENSITIVE ) 3650 { 3651 3652 // for inactive text, we do the painting ourselves 3653 // to prevent 'emboss' inactive text rendering from gtk 3654 Cairo::Context context( window, clipRect ); 3655 gdk_cairo_set_source_color( context, use_text ? &style->text[state] : &style->fg[state] ); 3656 const PangoMatrix* matrix( pango_context_get_matrix( pango_layout_get_context( layout ) ) ); 3657 if( matrix ) 3658 { 3659 cairo_matrix_t cairo_matrix; 3660 PangoRectangle rect; 3661 3662 cairo_matrix_init( &cairo_matrix, matrix->xx, matrix->yx, matrix->xy, matrix->yy, matrix->x0, matrix->y0 ); 3663 pango_layout_get_extents( layout, 0L, &rect ); 3664 pango_matrix_transform_rectangle( matrix, &rect ); 3665 pango_extents_to_pixels( &rect, 0L ); 3666 3667 cairo_matrix.x0 += x - rect.x; 3668 cairo_matrix.y0 += y - rect.y; 3669 3670 cairo_set_matrix( context, &cairo_matrix ); 3671 3672 } else cairo_translate( context, x, y ); 3673 3674 pango_cairo_show_layout( context, layout ); 3675 3676 } else if( GtkWidget* parent = Gtk::gtk_parent_button( widget ) ) { 3677 3678 // for flat buttons, do not use PRELIGHT color, since there is no PRELIGHT background rendered. 3679 if( Gtk::gtk_button_is_flat( parent ) && ( state == GTK_STATE_PRELIGHT || state == GTK_STATE_ACTIVE ) ) state = GTK_STATE_NORMAL; 3680 StyleWrapper::parentClass()->draw_layout( 3681 style, window, state, use_text, 3682 clipRect, widget, detail, x, y, layout ); 3683 3684 3685 } else { 3686 3687 // in all other cases, fallback on default rendering, for now 3688 StyleWrapper::parentClass()->draw_layout( 3689 style, window, state, use_text, 3690 clipRect, widget, detail, x, y, layout ); 3691 3692 } 3693 } 3694 3695 //_______________________________________________________________________________________________________________ 3696 void StyleWrapper::instanceInit( OxygenStyle* self ) 3697 { 3698 3699 #if OXYGEN_DEBUG 3700 std::cerr << "Oxygen::StyleWrapper::instanceInit" << std::endl; 3701 #endif 3702 3703 // style initialization 3704 /* 3705 this is normally achieved in theme_init, but is somehow not working with gnome shell 3706 so that it is redone here, since duplication is avoided when initialization is called twice without modifications 3707 */ 3708 Style::instance().initialize(); 3709 3710 // hooks 3711 Style::instance().animations().initializeHooks(); 3712 Style::instance().shadowHelper().initializeHooks(); 3713 Style::instance().widgetExplorer().initializeHooks(); 3714 3715 if( !Style::instance().settings().applicationName().isEclipse() ) 3716 { Style::instance().windowManager().initializeHooks(); } 3717 3718 if( Style::instance().settings().argbEnabled() && 3719 !Style::instance().settings().applicationName().isXul() ) 3720 { Style::instance().argbHelper().initializeHooks(); } 3721 3722 // disable all animations for openoffice 3723 // and re-enable combobox animations 3724 if( Oxygen::Style::instance().settings().applicationName().isOpenOffice() ) 3725 { 3726 Oxygen::Style::instance().animations().setEnabled( false ); 3727 Oxygen::Style::instance().animations().setInnerShadowsEnabled( false ); 3728 Oxygen::Style::instance().animations().comboBoxEngine().setEnabled( true ); 3729 Oxygen::Style::instance().animations().backgroundHintEngine().setEnabled( true ); 3730 } 3731 3732 } 3733 3734 //_______________________________________________________________________________________________________________ 3735 void StyleWrapper::classInit( OxygenStyleClass* klass ) 3736 { 3737 3738 #if OXYGEN_DEBUG 3739 std::cerr << "Oxygen::StyleWrapper::classInit" << std::endl; 3740 #endif 3741 3742 GtkStyleClass* style_class( GTK_STYLE_CLASS( klass ) ); 3743 3744 _parentClass = static_cast<GtkStyleClass*>( g_type_class_peek_parent( klass ) ); 3745 3746 style_class->draw_hline = draw_hline; 3747 style_class->draw_vline = draw_vline; 3748 style_class->draw_shadow = draw_shadow; 3749 style_class->draw_arrow = draw_arrow; 3750 3751 style_class->draw_diamond = draw_diamond; 3752 3753 style_class->draw_box = draw_box; 3754 style_class->draw_flat_box = draw_flat_box; 3755 style_class->draw_check = draw_check; 3756 style_class->draw_option = draw_option; 3757 style_class->draw_tab = draw_tab; 3758 style_class->draw_shadow_gap = draw_shadow_gap; 3759 style_class->draw_box_gap = draw_box_gap; 3760 style_class->draw_extension = draw_extension; 3761 style_class->draw_focus = draw_focus; 3762 style_class->draw_slider = draw_slider; 3763 style_class->draw_handle = draw_handle; 3764 style_class->draw_resize_grip = draw_resize_grip; 3765 style_class->draw_expander = draw_expander; 3766 3767 // icon rendering 3768 style_class->render_icon = render_icon; 3769 3770 // text rendering 3771 style_class->draw_layout = draw_layout; 3772 3773 } 3774 3775 //_______________________________________________________________________________________________________________ 3776 void StyleWrapper::registerType( GTypeModule* module ) 3777 { 3778 3779 #if OXYGEN_DEBUG 3780 std::cerr << "Oxygen::StyleWrapper::registerType" << std::endl; 3781 #endif 3782 3783 const GTypeInfo info = 3784 { 3785 (guint16)sizeof( OxygenStyleClass ), 3786 (GBaseInitFunc) NULL, 3787 (GBaseFinalizeFunc) NULL, 3788 (GClassInitFunc) classInit, 3789 (GClassFinalizeFunc) NULL, 3790 NULL, 3791 (guint16)sizeof( OxygenStyle ), 3792 0, 3793 (GInstanceInitFunc) instanceInit, 3794 NULL 3795 }; 3796 3797 _typeInfo = info; 3798 _type = g_type_module_register_type( module, GTK_TYPE_STYLE, "OxygenStyle", &_typeInfo, GTypeFlags(0 ) ); 3799 3800 #if OXYGEN_DEBUG 3801 std::cerr << "Oxygen::StyleWrapper::registerType - done" << std::endl; 3802 #endif 3803 3804 } 3805 3806 //_______________________________________________________________________________________________________________ 3807 void StyleWrapper::registerVersionType( void ) 3808 { 3809 3810 // register version type 3811 GType type( g_type_register_static_simple( 3812 G_TYPE_OBJECT, 3813 OXYGEN_VERSION_TYPE_NAME, 3814 (guint16)sizeof( GObjectClass ), 3815 (GClassInitFunc) NULL, 3816 (guint16)sizeof( GObject ), 3817 (GInstanceInitFunc) NULL, 3818 G_TYPE_FLAG_ABSTRACT ) ); 3819 3820 // quark 3821 GQuark quark( g_quark_from_string( OXYGEN_VERSION_QUARK_NAME ) ); 3822 g_type_set_qdata( type, quark, (gpointer) OXYGEN_VERSION ); 3823 3824 } 3825 3826 //_______________________________________________________________________________________________________________ 3827 GType StyleWrapper::type( void ) 3828 { return _type; } 3829 3830 }