File indexing completed on 2024-04-28 05:32:12
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 GdkPixbuf modification code from Walmis 0007 <http://gnome-look.org/content/show.php?content=77783&forumpage=3> 0008 0009 SPDX-License-Identifier: LGPL-2.0-or-later 0010 */ 0011 0012 #include "oxygengtkutils.h" 0013 #include "oxygengtktypenames.h" 0014 #include "config.h" 0015 0016 #include <cmath> 0017 #include <cstring> 0018 #include <gtk/gtk.h> 0019 #include <iostream> 0020 #include <set> 0021 0022 namespace Oxygen 0023 { 0024 GQuark Gtk::Quarks::_rcStyle = 0L; 0025 0026 //____________________________________________________________ 0027 void Gtk::gtk_container_adjust_buttons_state(GtkContainer* container,gpointer data) 0028 { 0029 if(GTK_IS_BUTTON(container)) 0030 { 0031 int x,y; 0032 GtkWidget* button=GTK_WIDGET(container); 0033 GtkAllocation allocation( gtk_widget_get_allocation( button ) ); 0034 gtk_widget_get_pointer(button,&x,&y); 0035 if( !(x>0 && y>0 && 0036 x < allocation.width && 0037 y < allocation.height) && gtk_widget_get_state(button)==GTK_STATE_ACTIVE ) 0038 { gtk_widget_set_state(button,GTK_STATE_NORMAL); } 0039 0040 gtk_button_set_relief(GTK_BUTTON(button),GTK_RELIEF_NORMAL); 0041 gtk_widget_set_size_request(button,16,16); 0042 0043 return; 0044 0045 } 0046 0047 if(GTK_IS_CONTAINER(container)) 0048 { gtk_container_foreach(container,(GtkCallback)gtk_container_adjust_buttons_state,0L); } 0049 0050 } 0051 0052 //____________________________________________________________ 0053 bool Gtk::gtk_widget_has_custom_background( GtkWidget* widget, GtkStateType state ) 0054 { 0055 0056 // loop over all parents, recursively 0057 for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) ) 0058 { if( gtk_widget_get_modifier_style(parent)->color_flags[state]>K_RC_BG ) return true; } 0059 0060 return false; 0061 0062 } 0063 0064 //____________________________________________________________ 0065 bool Gtk::gtk_widget_is_applet( GtkWidget* widget ) 0066 { 0067 if( !widget ) return false; 0068 0069 #if OXYGEN_DEBUG 0070 std::cerr << "Gtk::gtk_widget_is_applet(): " << Gtk::gtk_widget_path(widget) << std::endl; 0071 #endif 0072 0073 static const char* names[] = 0074 { 0075 "Panel", 0076 "PanelWidget", 0077 "PanelApplet", 0078 "XfcePanelWindow", 0079 0 0080 }; 0081 0082 // check widget name 0083 std::string name( G_OBJECT_TYPE_NAME( widget ) ); 0084 for( unsigned int i = 0; names[i]; ++i ) 0085 { if( g_object_is_a( G_OBJECT( widget ), names[i] ) || name.find( names[i] ) == 0 ) return true; } 0086 0087 // also check parent 0088 if( GtkWidget* parent = gtk_widget_get_parent( widget ) ) 0089 { 0090 name = G_OBJECT_TYPE_NAME( parent ); 0091 for( unsigned int i = 0; names[i]; ++i ) 0092 { if( g_object_is_a( G_OBJECT( parent ), names[i] ) || name.find( names[i] ) == 0 ) return true; } 0093 0094 } 0095 0096 // also check first widget path element (needed for xfce panel) 0097 std::string widgetPath=Gtk::gtk_widget_path(widget); 0098 { 0099 for( unsigned int i = 0; names[i]; ++i ) 0100 { 0101 if( widgetPath.find(names[i]) != std::string::npos ) 0102 return true; 0103 } 0104 } 0105 0106 return false; 0107 0108 } 0109 0110 //____________________________________________________________ 0111 void Gtk::gtk_widget_print_tree( GtkWidget* widget ) 0112 { 0113 0114 if( !widget ) return; 0115 std::cerr << "Oxygen::Gtk::gtk_widget_print_tree - widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl; 0116 while( ( widget = gtk_widget_get_parent( widget ) ) ) 0117 { std::cerr << " parent: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl; } 0118 0119 } 0120 0121 //________________________________________________________ 0122 bool Gtk::gdk_default_screen_is_composited( void ) 0123 { 0124 GdkScreen* screen( gdk_screen_get_default() ); 0125 return (screen && gdk_screen_is_composited( screen ) ); 0126 } 0127 0128 //________________________________________________________ 0129 bool Gtk::gtk_widget_has_rgba( GtkWidget* widget ) 0130 { 0131 0132 if( !widget ) return false; 0133 if( !gdk_default_screen_is_composited() ) return false; 0134 return gdk_visual_has_rgba( gtk_widget_get_visual (widget) ); 0135 0136 } 0137 0138 //________________________________________________________ 0139 bool Gtk::gdk_window_is_base( GdkWindow* window ) 0140 { 0141 0142 if( !GDK_IS_WINDOW( window ) ) return false; 0143 0144 GdkWindowTypeHint hint = gdk_window_get_type_hint( window ); 0145 0146 #if OXYGEN_DEBUG 0147 std::cerr << "Gtk::gdk_window_is_base - " << TypeNames::windowTypeHint( hint ) << std::endl; 0148 #endif 0149 0150 return( 0151 hint == GDK_WINDOW_TYPE_HINT_NORMAL || 0152 hint == GDK_WINDOW_TYPE_HINT_DIALOG || 0153 hint == GDK_WINDOW_TYPE_HINT_UTILITY ); 0154 } 0155 0156 //________________________________________________________ 0157 bool Gtk::gdk_window_nobackground( GdkWindow* window ) 0158 { 0159 if( !GDK_IS_WINDOW( window ) ) return false; 0160 0161 GdkWindowTypeHint hint = gdk_window_get_type_hint( window ); 0162 return( hint == GDK_WINDOW_TYPE_HINT_COMBO || hint == GDK_WINDOW_TYPE_HINT_TOOLTIP ); 0163 0164 } 0165 0166 //________________________________________________________ 0167 bool Gtk::gdk_window_has_rgba( GdkWindow* window ) 0168 { 0169 0170 if( !window ) return false; 0171 0172 if( !gdk_default_screen_is_composited() ) return false; 0173 return gdk_visual_has_rgba( gdk_drawable_get_visual( GDK_DRAWABLE( window ) ) ); 0174 0175 } 0176 0177 //________________________________________________________ 0178 bool Gtk::gdk_visual_has_rgba( GdkVisual* visual ) 0179 { 0180 return 0181 visual->depth == 32 && 0182 visual->red_mask == 0xff0000 && 0183 visual->green_mask == 0x00ff00 && 0184 visual->blue_mask == 0x0000ff; 0185 0186 } 0187 0188 //________________________________________________________ 0189 bool Gtk::g_object_is_a( const GObject* object, const std::string& typeName ) 0190 { 0191 0192 if( object ) 0193 { 0194 const GType tmp( g_type_from_name( typeName.c_str() ) ); 0195 if( tmp ) 0196 { return g_type_check_instance_is_a( (GTypeInstance*) object, tmp ); } 0197 } 0198 0199 return false; 0200 } 0201 0202 //________________________________________________________ 0203 std::string Gtk::gtk_widget_path( GtkWidget* widget ) 0204 { 0205 0206 if(GTK_IS_WIDGET(widget)) 0207 { 0208 gchar* widgetPath; 0209 gtk_widget_path( widget, 0L, &widgetPath, 0L); 0210 const std::string out( widgetPath ); 0211 g_free( widgetPath ); 0212 return out; 0213 } 0214 return std::string("not-widget"); 0215 0216 } 0217 0218 //________________________________________________________ 0219 GtkWidget* Gtk::gtk_widget_find_parent( GtkWidget* widget, GType type ) 0220 { 0221 0222 for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) ) 0223 { if( G_TYPE_CHECK_INSTANCE_TYPE( parent, type ) ) return parent; } 0224 0225 return 0L; 0226 } 0227 0228 //________________________________________________________ 0229 GtkWidget* Gtk::gtk_parent_groupbox( GtkWidget* widget ) 0230 { 0231 0232 for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) ) 0233 { if( gtk_widget_is_groupbox( parent ) ) return parent; } 0234 0235 return 0L; 0236 } 0237 0238 //________________________________________________________ 0239 bool Gtk::gtk_widget_is_parent( GtkWidget* widget, GtkWidget* potentialParent ) 0240 { 0241 0242 for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) ) 0243 { if( potentialParent==parent ) return true; } 0244 0245 return false; 0246 } 0247 0248 //________________________________________________________ 0249 bool Gtk::gtk_parent_is_shadow_in( GtkWidget* widget ) 0250 { 0251 for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) ) 0252 { 0253 if( GTK_IS_FRAME( parent ) && gtk_frame_get_shadow_type( GTK_FRAME( parent ) ) == GTK_SHADOW_IN ) return true; 0254 if( GTK_IS_SCROLLED_WINDOW( parent ) && gtk_scrolled_window_get_shadow_type( GTK_SCROLLED_WINDOW( parent ) ) == GTK_SHADOW_IN ) return true; 0255 } 0256 0257 return false; 0258 } 0259 0260 //________________________________________________________ 0261 bool Gtk::gtk_button_is_flat( GtkWidget* widget ) 0262 { 0263 if( !GTK_IS_BUTTON( widget ) ) return false; 0264 return ( gtk_button_get_relief( GTK_BUTTON( widget ) ) == GTK_RELIEF_NONE ); 0265 } 0266 0267 //________________________________________________________ 0268 bool Gtk::gtk_button_is_header( GtkWidget* widget ) 0269 { 0270 if( !GTK_IS_BUTTON( widget ) ) return false; 0271 return gtk_parent_tree_view( widget ) || gtk_widget_find_parent( widget, "GimpThumbBox" ); 0272 } 0273 0274 //________________________________________________________ 0275 bool Gtk::gtk_button_is_in_path_bar( GtkWidget* widget ) 0276 { 0277 if( !( GTK_IS_BUTTON( widget ) && gtk_widget_get_parent( widget ) ) ) return false; 0278 0279 std::string name(G_OBJECT_TYPE_NAME( gtk_widget_get_parent( widget ) ) ); 0280 return name == "GtkPathBar" || name == "NautilusPathBar"; 0281 } 0282 0283 //________________________________________________________ 0284 bool Gtk::gtk_path_bar_button_is_last( GtkWidget* widget ) 0285 { 0286 0287 GtkWidget* parent( gtk_widget_get_parent( widget ) ); 0288 0289 // get parent and check type 0290 if( !( parent && GTK_IS_CONTAINER( parent ) ) ) return false; 0291 0292 // get children 0293 GList* children( gtk_container_get_children( GTK_CONTAINER( parent ) ) ); 0294 0295 /* 0296 for some reason, pathbar buttons are ordered in the container in reverse order. 0297 meaning that the last button (in the pathbar) is stored first in the list. 0298 */ 0299 bool result = (widget == g_list_first( children )->data ); 0300 if( children ) g_list_free( children ); 0301 return result; 0302 0303 } 0304 0305 //________________________________________________________ 0306 GtkWidget* Gtk::gtk_button_find_image(GtkWidget* button) 0307 { 0308 0309 // check widget type 0310 if(!GTK_IS_CONTAINER(button)) return 0L; 0311 0312 GtkWidget* result( 0L ); 0313 GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) ); 0314 for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) 0315 { 0316 if( GTK_IS_IMAGE( child->data ) ) 0317 { 0318 result = GTK_WIDGET( child->data ); 0319 break; 0320 0321 } else if( GTK_IS_CONTAINER( child->data ) ) { 0322 0323 result = gtk_button_find_image( GTK_WIDGET(child->data ) ); 0324 break; 0325 0326 } 0327 0328 } 0329 0330 if( children ) g_list_free( children ); 0331 return result; 0332 0333 } 0334 0335 //________________________________________________________ 0336 GtkWidget* Gtk::gtk_button_find_label(GtkWidget* button) 0337 { 0338 0339 // check widget type 0340 if( !GTK_IS_CONTAINER(button) ) return 0L; 0341 0342 GtkWidget* result( 0L ); 0343 GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) ); 0344 for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) 0345 { 0346 0347 if( GTK_IS_LABEL( child->data) ) 0348 { 0349 result = GTK_WIDGET( child->data ); 0350 break; 0351 0352 } else if( GTK_IS_CONTAINER( child->data ) ) { 0353 0354 result = gtk_button_find_image(GTK_WIDGET(child->data)); 0355 break; 0356 0357 } 0358 0359 } 0360 0361 if( children ) g_list_free( children ); 0362 return result; 0363 0364 } 0365 0366 //________________________________________________________ 0367 bool Gtk::gtk_combobox_has_frame( GtkWidget* widget ) 0368 { 0369 0370 GValue val = { 0, }; 0371 g_value_init(&val, G_TYPE_BOOLEAN); 0372 g_object_get_property( G_OBJECT( widget ), "has-frame", &val ); 0373 return (bool) g_value_get_boolean( &val ); 0374 0375 } 0376 0377 //________________________________________________________ 0378 bool Gtk::gtk_combobox_is_tree_view( GtkWidget* widget ) 0379 { 0380 // check types and path 0381 if( !widget && GTK_IS_TREE_VIEW( widget ) && GTK_IS_SCROLLED_WINDOW( gtk_widget_get_parent( widget ) ) ) return false; 0382 return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow.GtkTreeView"; 0383 } 0384 0385 //________________________________________________________ 0386 bool Gtk::gtk_combobox_is_scrolled_window( GtkWidget* widget ) 0387 { 0388 // check types and path 0389 if( !GTK_IS_SCROLLED_WINDOW(widget) ) return false; 0390 return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow"; 0391 } 0392 0393 //________________________________________________________ 0394 bool Gtk::gtk_combobox_is_popup( GtkWidget* widget ) 0395 { 0396 // check types and path 0397 if( !GTK_IS_WINDOW(widget) ) return false; 0398 return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window"; 0399 } 0400 0401 //________________________________________________________ 0402 bool Gtk::gtk_combo_is_viewport( GtkWidget* widget ) 0403 { 0404 if( !GTK_IS_VIEWPORT(widget) ) return false; 0405 static const std::string match( "gtk-combo-popup-window" ); 0406 return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match; 0407 } 0408 0409 //________________________________________________________ 0410 bool Gtk::gtk_combo_is_frame( GtkWidget* widget ) 0411 { 0412 if( !GTK_IS_FRAME(widget) ) return false; 0413 static const std::string match( "gtk-combo-popup-window" ); 0414 return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match; 0415 } 0416 0417 //________________________________________________________ 0418 bool Gtk::gtk_combo_is_popup( GtkWidget* widget ) 0419 { 0420 if( !GTK_IS_WINDOW(widget) ) return false; 0421 static const std::string match( "gtk-combo-popup-window" ); 0422 return Gtk::gtk_widget_path( widget ) == match; 0423 } 0424 0425 //________________________________________________________ 0426 bool Gtk::gtk_combobox_appears_as_list( GtkWidget* widget ) 0427 { 0428 gboolean appearsAsList; 0429 gtk_widget_style_get( widget, "appears-as-list", &appearsAsList, NULL ); 0430 return (bool) appearsAsList; 0431 } 0432 0433 //________________________________________________________ 0434 bool Gtk::gtk_is_tooltip( GtkWidget* widget ) 0435 { 0436 if( GTK_IS_TOOLTIP(widget) ) return true; 0437 const std::string path(Gtk::gtk_widget_path( widget )); 0438 return path == "gtk-tooltip" || path == "gtk-tooltips"; 0439 } 0440 0441 //________________________________________________________ 0442 bool Gtk::gtk_notebook_tab_contains( GtkWidget* widget, int tab, int x, int y ) 0443 { 0444 0445 if( !( tab >= 0 && GTK_IS_NOTEBOOK( widget ) ) ) return false; 0446 0447 // cast to notebook and check against number of pages 0448 GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); 0449 if( tab >= gtk_notebook_get_n_pages( notebook ) ) return false; 0450 0451 // retrieve page and tab label 0452 GtkWidget* page( gtk_notebook_get_nth_page( notebook, tab ) ); 0453 GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); 0454 0455 // get allocted size and compare to position 0456 const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) ); 0457 return Gtk::gdk_rectangle_contains( &allocation, x, y ); 0458 0459 } 0460 0461 //________________________________________________________ 0462 int Gtk::gtk_notebook_find_tab( GtkWidget* widget, int x, int y ) 0463 { 0464 0465 if( !GTK_IS_NOTEBOOK( widget ) ) return -1; 0466 0467 // cast to notebook and check against number of pages 0468 GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); 0469 int tab(-1); 0470 int minDistance( -1 ); 0471 for( int i = gtk_notebook_find_first_tab( widget ); i < gtk_notebook_get_n_pages( notebook ); ++i ) 0472 { 0473 0474 // retrieve page and tab label 0475 GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); 0476 if( !page ) continue; 0477 0478 // get label 0479 GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); 0480 if(!tabLabel) continue; 0481 0482 // get allocted size and compare to position 0483 const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) ); 0484 0485 // get manhattan length 0486 const int distance = int( 0487 std::abs( double( allocation.x + allocation.width/2 - x ) ) + 0488 std::abs( double( allocation.y + allocation.height/2 - y ) ) ); 0489 if( minDistance < 0 || distance < minDistance ) 0490 { 0491 tab = i; 0492 minDistance = distance; 0493 } 0494 } 0495 0496 return tab; 0497 0498 } 0499 0500 //________________________________________________________ 0501 int Gtk::gtk_notebook_find_first_tab( GtkWidget* widget ) 0502 { 0503 0504 if( !GTK_IS_NOTEBOOK( widget ) ) return 0; 0505 0506 // cast to notebook 0507 GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); 0508 return g_list_position( notebook->children, notebook->first_tab ); 0509 0510 } 0511 0512 //____________________________________________________________ 0513 bool Gtk::gtk_notebook_is_tab_label(GtkNotebook* notebook, GtkWidget* widget ) 0514 { 0515 0516 for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i ) 0517 { 0518 // retrieve page and tab label 0519 GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); 0520 if( !page ) continue; 0521 0522 GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); 0523 if( widget == tabLabel ) return true; 0524 } 0525 0526 return false; 0527 0528 } 0529 0530 0531 //____________________________________________________________ 0532 void Gtk::gtk_notebook_get_tabbar_rect( GtkNotebook* notebook, GdkRectangle* rect ) 0533 { 0534 // check notebook and rect 0535 if( !( notebook && rect ) ) return; 0536 0537 // check tab visibility 0538 GList* children( gtk_container_get_children( GTK_CONTAINER( notebook ) ) ); 0539 if( !( gtk_notebook_get_show_tabs( notebook ) && children ) ) 0540 { 0541 if( children ) g_list_free( children ); 0542 *rect = gdk_rectangle(); 0543 return; 0544 } 0545 0546 // free children 0547 if( children ) g_list_free( children ); 0548 0549 // get full rect 0550 gtk_widget_get_allocation( GTK_WIDGET( notebook ), rect ); 0551 0552 // adjust to account for borderwidth 0553 guint borderWidth( gtk_container_get_border_width( GTK_CONTAINER( notebook ) ) ); 0554 rect->x += borderWidth; 0555 rect->y += borderWidth; 0556 rect->height -= 2*borderWidth; 0557 rect->width -= 2*borderWidth; 0558 0559 // get current page 0560 int pageIndex( gtk_notebook_get_current_page( notebook ) ); 0561 if( !( pageIndex >= 0 && pageIndex < gtk_notebook_get_n_pages( notebook ) ) ) 0562 { 0563 *rect = gdk_rectangle(); 0564 return; 0565 } 0566 0567 GtkWidget* page( gtk_notebook_get_nth_page( notebook, pageIndex ) ); 0568 if( !page ) 0569 { 0570 *rect = gdk_rectangle(); 0571 return; 0572 } 0573 0574 // removes page allocated size from rect, based on tabwidget orientation 0575 const GtkAllocation pageAllocation( gtk_widget_get_allocation( page ) ); 0576 switch( gtk_notebook_get_tab_pos( notebook ) ) 0577 { 0578 case GTK_POS_BOTTOM: 0579 rect->height += rect->y - (pageAllocation.y + pageAllocation.height); 0580 rect->y = pageAllocation.y + pageAllocation.height; 0581 break; 0582 0583 case GTK_POS_TOP: 0584 rect->height = pageAllocation.y - rect->y; 0585 break; 0586 0587 case GTK_POS_RIGHT: 0588 rect->width += rect->x - (pageAllocation.x + pageAllocation.width); 0589 rect->x = pageAllocation.x + pageAllocation.width; 0590 break; 0591 0592 case GTK_POS_LEFT: 0593 rect->width = pageAllocation.x - rect->x; 0594 break; 0595 } 0596 0597 return; 0598 0599 } 0600 0601 //____________________________________________________________ 0602 bool Gtk::gtk_notebook_has_visible_arrows( GtkNotebook* notebook ) 0603 { 0604 0605 if( !gtk_notebook_get_show_tabs( notebook ) ) return false; 0606 0607 // loop over pages 0608 for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i ) 0609 { 0610 0611 // retrieve page and tab label 0612 GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); 0613 if( !page ) continue; 0614 0615 GtkWidget* label( gtk_notebook_get_tab_label( notebook, page ) ); 0616 0617 #if GTK_CHECK_VERSION(2, 20, 0) 0618 if( label && !gtk_widget_get_mapped( label ) ) return true; 0619 #else 0620 if( label && !GTK_WIDGET_MAPPED( label ) ) return true; 0621 #endif 0622 } 0623 0624 return false; 0625 0626 } 0627 0628 //____________________________________________________________ 0629 bool Gtk::gtk_notebook_update_close_buttons(GtkNotebook* notebook) 0630 { 0631 int numPages=gtk_notebook_get_n_pages( notebook ); 0632 for( int i = 0; i < numPages; ++i ) 0633 { 0634 0635 // retrieve page 0636 GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); 0637 if( !page ) continue; 0638 0639 // retrieve tab label 0640 GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); 0641 if( tabLabel && GTK_IS_CONTAINER( tabLabel ) ) 0642 { gtk_container_adjust_buttons_state( GTK_CONTAINER( tabLabel ) ); } 0643 0644 } 0645 return FALSE; 0646 } 0647 0648 //________________________________________________________ 0649 bool Gtk::gtk_notebook_is_close_button(GtkWidget* widget) 0650 { 0651 if( GtkNotebook* nb=GTK_NOTEBOOK(gtk_parent_notebook(widget) ) ) 0652 { 0653 // check if the button resides on tab label, not anywhere on the tab 0654 bool tabLabelIsParent=false; 0655 for( int i=0; i < gtk_notebook_get_n_pages(nb); ++i ) 0656 { 0657 GtkWidget* tabLabel( gtk_notebook_get_tab_label(nb,gtk_notebook_get_nth_page( nb, i ) ) ); 0658 if( gtk_widget_is_parent( widget, GTK_WIDGET(tabLabel) ) ) 0659 { tabLabelIsParent=true; } 0660 } 0661 0662 if( !tabLabelIsParent ) return false; 0663 0664 // make sure button has no text and some image (for now, just hope it's a close icon) 0665 if( gtk_button_find_image(widget) && !gtk_button_get_label( GTK_BUTTON(widget) ) ) 0666 { return true; } 0667 0668 // check for pidgin 'x' close button 0669 if( GtkWidget* label = gtk_button_find_label(widget) ) 0670 { 0671 0672 const gchar* labelText=gtk_label_get_text( GTK_LABEL(label) ); 0673 if(!strcmp(labelText,"×")) // It's not letter 'x' - it's a special symbol 0674 { 0675 gtk_widget_hide( label ); 0676 return true; 0677 } else return false; 0678 0679 } else return false; 0680 0681 } else return false; 0682 0683 } 0684 0685 //________________________________________________________ 0686 bool Gtk::gtk_scrolled_window_force_sunken( GtkWidget* widget) 0687 { 0688 0689 // FMIconView (from nautilus) always get sunken 0690 if( g_object_is_a( G_OBJECT( widget ), "FMIconView" ) ) return true; 0691 0692 // other checks require widget to be of type GtkBin 0693 if( !GTK_IS_BIN( widget ) ) return false; 0694 0695 // retrieve child 0696 GtkWidget* child( gtk_bin_get_child( GTK_BIN( widget ) ) ); 0697 if( GTK_IS_TREE_VIEW( child ) || GTK_IS_ICON_VIEW( child ) ) return true; 0698 else return false; 0699 0700 } 0701 0702 //________________________________________________________ 0703 bool Gtk::gdk_window_map_to_toplevel( GdkWindow* window, gint* x, gint* y, gint* w, gint* h, bool frame ) 0704 { 0705 0706 // always initialize arguments (to invalid values) 0707 if( x ) *x=0; 0708 if( y ) *y=0; 0709 if( w ) *w = -1; 0710 if( h ) *h = -1; 0711 0712 if( !( window && GDK_IS_WINDOW( window ) ) ) return false; 0713 0714 // get window size and height 0715 if( frame ) gdk_toplevel_get_frame_size( window, w, h ); 0716 else gdk_toplevel_get_size( window, w, h ); 0717 Gtk::gdk_window_get_toplevel_origin( window, x, y ); 0718 return ((!w) || *w > 0) && ((!h) || *h>0); 0719 0720 } 0721 0722 //________________________________________________________ 0723 bool Gtk::gtk_widget_map_to_toplevel( GtkWidget* widget, gint* x, gint* y, gint* w, gint* h, bool frame ) 0724 { 0725 0726 // always initialize arguments (to invalid values) 0727 if( x ) *x=0; 0728 if( y ) *y=0; 0729 if( w ) *w = -1; 0730 if( h ) *h = -1; 0731 0732 if( !widget ) return false; 0733 0734 // get window 0735 GdkWindow* window( gtk_widget_get_parent_window( widget ) ); 0736 if( !( window && GDK_IS_WINDOW( window ) ) ) return false; 0737 0738 if( frame ) gdk_toplevel_get_frame_size( window, w, h ); 0739 else gdk_toplevel_get_size( window, w, h ); 0740 int xlocal, ylocal; 0741 const bool success( gtk_widget_translate_coordinates( widget, gtk_widget_get_toplevel( widget ), 0, 0, &xlocal, &ylocal ) ); 0742 if( success ) 0743 { 0744 0745 if( x ) *x=xlocal; 0746 if( y ) *y=ylocal; 0747 0748 } 0749 0750 return success && ((!w) || *w > 0) && ((!h) || *h>0); 0751 0752 } 0753 0754 //________________________________________________________ 0755 bool Gtk::gtk_widget_map_to_parent( GtkWidget* widget, GtkWidget* parent, gint* x, gint* y, gint* w, gint* h ) 0756 { 0757 0758 // always initialize arguments (to invalid values) 0759 if( x ) *x=0; 0760 if( y ) *y=0; 0761 if( w ) *w = -1; 0762 if( h ) *h = -1; 0763 0764 if( !( widget && parent ) ) return false; 0765 0766 const GtkAllocation allocation( gtk_widget_get_allocation( parent ) ); 0767 if( w ) *w = allocation.width; 0768 if( h ) *h = allocation.height; 0769 0770 int xlocal, ylocal; 0771 const bool success( gtk_widget_translate_coordinates( widget, parent, 0, 0, &xlocal, &ylocal ) ); 0772 if( success ) 0773 { 0774 0775 if( x ) *x=xlocal; 0776 if( y ) *y=ylocal; 0777 0778 } 0779 0780 return success && ((!w) || *w > 0) && ((!h) || *h>0); 0781 0782 } 0783 0784 //________________________________________________________ 0785 bool Gtk::gdk_window_translate_origin( GdkWindow* parent, GdkWindow* child, gint* x, gint* y ) 0786 { 0787 if( x ) *x = 0; 0788 if( y ) *y = 0; 0789 if( !( parent && child ) ) return false; 0790 while( child && GDK_IS_WINDOW( child ) && 0791 child != parent && 0792 gdk_window_get_window_type( child ) == GDK_WINDOW_CHILD ) 0793 { 0794 gint xloc; 0795 gint yloc; 0796 gdk_window_get_position( child, &xloc, &yloc ); 0797 if( x ) *x += xloc; 0798 if( y ) *y += yloc; 0799 child = gdk_window_get_parent( child ); 0800 } 0801 0802 return( child == parent ); 0803 0804 } 0805 0806 //________________________________________________________ 0807 void Gtk::gdk_toplevel_get_size( GdkWindow* window, gint* w, gint* h ) 0808 { 0809 0810 if( !( window && GDK_IS_WINDOW( window ) ) ) 0811 { 0812 if( w ) *w = -1; 0813 if( h ) *h = -1; 0814 return; 0815 } 0816 0817 if( GdkWindow* topLevel = gdk_window_get_toplevel( window ) ) 0818 { 0819 gdk_drawable_get_size( topLevel, w, h ); 0820 } else gdk_drawable_get_size( window, w, h ); 0821 0822 return; 0823 0824 } 0825 0826 //________________________________________________________ 0827 void Gtk::gdk_toplevel_get_frame_size( GdkWindow* window, gint* w, gint* h ) 0828 { 0829 0830 if( !( window && GDK_IS_WINDOW( window ) ) ) 0831 { 0832 if( w ) *w = -1; 0833 if( h ) *h = -1; 0834 return; 0835 } 0836 0837 if( GdkWindow* topLevel = gdk_window_get_toplevel( window ) ) 0838 { 0839 GdkRectangle rect = {0, 0, -1, -1}; 0840 gdk_window_get_frame_extents( topLevel, &rect ); 0841 if( w ) *w = rect.width; 0842 if( h ) *h = rect.height; 0843 } 0844 0845 return; 0846 0847 } 0848 0849 //________________________________________________________ 0850 void Gtk::gdk_window_get_toplevel_origin( GdkWindow* window, gint* x, gint* y ) 0851 { 0852 if( x ) *x = 0; 0853 if( y ) *y = 0; 0854 if( !window ) return; 0855 while( window && GDK_IS_WINDOW( window ) && gdk_window_get_window_type( window ) == GDK_WINDOW_CHILD ) 0856 { 0857 gint xloc; 0858 gint yloc; 0859 gdk_window_get_position( window, &xloc, &yloc ); 0860 if( x ) *x += xloc; 0861 if( y ) *y += yloc; 0862 window = gdk_window_get_parent( window ); 0863 } 0864 0865 return; 0866 } 0867 0868 //___________________________________________________________ 0869 GdkPixbuf* Gtk::gdk_pixbuf_set_alpha( const GdkPixbuf *pixbuf, double alpha ) 0870 { 0871 0872 g_return_val_if_fail( pixbuf != 0L, 0L); 0873 g_return_val_if_fail( GDK_IS_PIXBUF( pixbuf ), 0L ); 0874 0875 /* Returns a copy of pixbuf with it's non-completely-transparent pixels to 0876 have an alpha level "alpha" of their original value. */ 0877 GdkPixbuf* target( gdk_pixbuf_add_alpha( pixbuf, false, 0, 0, 0 ) ); 0878 if( alpha >= 1.0 ) return target; 0879 if( alpha < 0 ) alpha = 0; 0880 0881 const int width( gdk_pixbuf_get_width( target ) ); 0882 const int height( gdk_pixbuf_get_height( target ) ); 0883 const int rowstride( gdk_pixbuf_get_rowstride( target ) ); 0884 unsigned char* data = gdk_pixbuf_get_pixels( target ); 0885 0886 for( int y = 0; y < height; ++y ) 0887 { 0888 0889 for( int x = 0; x < width; ++x ) 0890 { 0891 /* The "4" is the number of chars per pixel, in this case, RGBA, 0892 the 3 means "skip to the alpha" */ 0893 unsigned char* current = data + ( y*rowstride ) + ( x*4 ) + 3; 0894 *(current) = (unsigned char) ( *( current )*alpha ); 0895 } 0896 } 0897 0898 return target; 0899 } 0900 0901 //_________________________________________________________ 0902 bool Gtk::gdk_pixbuf_to_gamma(GdkPixbuf* pixbuf, double value) 0903 { 0904 if(gdk_pixbuf_get_colorspace(pixbuf)==GDK_COLORSPACE_RGB && 0905 gdk_pixbuf_get_bits_per_sample(pixbuf)==8 && 0906 gdk_pixbuf_get_has_alpha(pixbuf) && 0907 gdk_pixbuf_get_n_channels(pixbuf)==4) 0908 { 0909 double gamma=1./(2.*value+0.5); 0910 unsigned char* data=gdk_pixbuf_get_pixels(pixbuf); 0911 const int height=gdk_pixbuf_get_height(pixbuf); 0912 const int width=gdk_pixbuf_get_width(pixbuf); 0913 const int rowstride=gdk_pixbuf_get_rowstride(pixbuf); 0914 for(int x=0;x<width;++x) 0915 { 0916 for(int y=0; y<height; y++) 0917 { 0918 unsigned char* p=data + y*rowstride + x*4; 0919 *p=(char)(pow((*p/255.),gamma)*255); ++p; 0920 *p=(char)(pow((*p/255.),gamma)*255); ++p; 0921 *p=(char)(pow((*p/255.),gamma)*255); 0922 } 0923 0924 } 0925 0926 return true; 0927 0928 } else return false; 0929 0930 } 0931 0932 //___________________________________________________________ 0933 GdkPixbuf* Gtk::gdk_pixbuf_resize( GdkPixbuf* src, int width, int height ) 0934 { 0935 if( width == gdk_pixbuf_get_width( src ) && height == gdk_pixbuf_get_height( src ) ) 0936 { 0937 0938 return static_cast<GdkPixbuf*>(g_object_ref (src)); 0939 0940 } else { 0941 0942 return gdk_pixbuf_scale_simple( src, width, height, GDK_INTERP_BILINEAR ); 0943 0944 } 0945 0946 } 0947 0948 //___________________________________________________________ 0949 void Gtk::gtk_viewport_get_position( GtkViewport* viewport, gint* x, gint* y ) 0950 { 0951 0952 // initialize 0953 if( x ) *x = 0; 0954 if( y ) *y = 0; 0955 0956 // get bin window 0957 #if GTK_CHECK_VERSION( 2, 20, 0 ) 0958 GdkWindow* binWindow( gtk_viewport_get_bin_window( viewport ) ); 0959 #else 0960 GdkWindow* binWindow( viewport->bin_window ); 0961 #endif 0962 0963 gint xBin(0), yBin(0); 0964 gdk_window_get_geometry( binWindow, &xBin, &yBin, 0, 0, 0 ); 0965 0966 // get view window 0967 #if GTK_CHECK_VERSION( 2, 22, 0 ) 0968 GdkWindow* viewWindow( gtk_viewport_get_view_window( viewport ) ); 0969 #else 0970 GdkWindow* viewWindow( viewport->view_window ); 0971 #endif 0972 0973 gint xView(0), yView(0); 0974 gdk_window_get_geometry( viewWindow, &xView, &yView, 0, 0, 0 ); 0975 0976 // calculate offsets 0977 if( x ) *x = xView - xBin; 0978 if( y ) *y = yView - yBin; 0979 0980 // also correct from widget thickness 0981 GtkStyle* style( gtk_widget_get_style( GTK_WIDGET( viewport ) ) ); 0982 if( style ) 0983 { 0984 if( x ) *x -= style->xthickness; 0985 if( y ) *y -= style->ythickness; 0986 } 0987 0988 return; 0989 0990 } 0991 0992 //___________________________________________________________ 0993 GtkWidget* Gtk::gtk_dialog_find_button(GtkDialog* dialog,gint response_id) 0994 { 0995 0996 // get children of dialog's action area 0997 GList* children( gtk_container_get_children( GTK_CONTAINER( gtk_dialog_get_action_area( dialog ) ) ) ); 0998 0999 #if OXYGEN_DEBUG 1000 std::cerr << "Oxygen::Gtk::gtk_dialog_find_button - buttons: "; 1001 #endif 1002 1003 for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) 1004 { 1005 1006 // check data 1007 if( !GTK_IS_WIDGET( child->data ) ) continue; 1008 GtkWidget* childWidget( GTK_WIDGET( child->data ) ); 1009 1010 const gint id( gtk_dialog_get_response_for_widget(dialog, childWidget ) ); 1011 1012 #if OXYGEN_DEBUG 1013 std::cerr << Gtk::TypeNames::response( (GtkResponseType) id ) << ", "; 1014 #endif 1015 if( id == response_id ) return childWidget; 1016 1017 } 1018 1019 #if OXYGEN_DEBUG 1020 std::cerr << std::endl; 1021 #endif 1022 1023 if( children ) g_list_free( children ); 1024 return 0L; 1025 1026 } 1027 1028 1029 }