diff options
Diffstat (limited to 'tdegtk/tdegtk-utils.cpp')
-rw-r--r-- | tdegtk/tdegtk-utils.cpp | 1064 |
1 files changed, 1064 insertions, 0 deletions
diff --git a/tdegtk/tdegtk-utils.cpp b/tdegtk/tdegtk-utils.cpp new file mode 100644 index 0000000..ad93793 --- /dev/null +++ b/tdegtk/tdegtk-utils.cpp @@ -0,0 +1,1064 @@ +/* +* this file was largely taken from the oxygen gtk engine +* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org> +* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com> +* +* GdkPixbuf modification code from Walmis +* <http://gnome-look.org/content/show.php?content=77783&forumpage=3> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or( at your option ) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free +* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#include "tdegtk-utils.h" +//#include "oxygengtktypenames.h" +#include "config.h" + +#include <cmath> +#include <cstring> +#include <gtk/gtk.h> +#include <iostream> +#include <set> + + //_____________________________________________________________________________ + std::ostream& operator << ( std::ostream& out, const GtkWidgetPath* path ) + { + if( !path ) + { + + out << " (null)"; + + } else { + + for( gint pos=0; pos<gtk_widget_path_length( path ); ++pos ) + { + const char* name( g_type_name( gtk_widget_path_iter_get_object_type( path, pos ) ) ); + if(!name) break; + out << "/" << name; + } + + } + + return out; + + } + + + + //____________________________________________________________ + void Gtk::gtk_container_adjust_buttons_state(GtkContainer* container,gpointer data) + { + if(GTK_IS_BUTTON(container)) + { + + int x(0),y(0); + GtkWidget* button=GTK_WIDGET(container); + GtkAllocation allocation( gtk_widget_get_allocation( button ) ); + + GdkDeviceManager* manager( gdk_display_get_device_manager( gtk_widget_get_display( button ) ) ); + GdkDevice* pointer( gdk_device_manager_get_client_pointer( manager ) ); + gdk_window_get_device_position( gtk_widget_get_window( button ), pointer, &x, &y, 0L); + + if( !(x>0 && y>0 && + x < allocation.width && + y < allocation.height) && gtk_widget_get_state(button)==GTK_STATE_ACTIVE ) + { gtk_widget_set_state(button,GTK_STATE_NORMAL); } + + gtk_button_set_relief(GTK_BUTTON(button),GTK_RELIEF_NORMAL); + gtk_widget_set_size_request(button,16,16); + + return; + + } + + if(GTK_IS_CONTAINER(container)) + { gtk_container_foreach(container,(GtkCallback)gtk_container_adjust_buttons_state,0L); } + + } + + //____________________________________________________________ + bool Gtk::gtk_widget_path_has_type( const GtkWidgetPath* path, GType type ) + { + + if( !path ) return false; + for( gint pos=0; pos<gtk_widget_path_length( path ); ++pos ) + { + const GType local( gtk_widget_path_iter_get_object_type( path, pos ) ); + if( local == type || g_type_is_a( local, type ) ) + { return true; } + } + + return false; + + } + + //____________________________________________________________ + bool Gtk::gtk_widget_is_applet( GtkWidget* widget ) + { + if( !widget ) return false; + + #if OXYGEN_DEBUG + std::cerr << "Gtk::gtk_widget_is_applet(): " << Gtk::gtk_widget_path(widget) << std::endl; + #endif + + static const char* names[] = + { + "Panel", + "PanelWidget", + "PanelApplet", + "XfcePanelWindow", + 0 + }; + + // check widget name + std::string name( G_OBJECT_TYPE_NAME( widget ) ); + for( unsigned int i = 0; names[i]; ++i ) + { if( g_object_is_a( G_OBJECT( widget ), names[i] ) || name.find( names[i] ) == 0 ) return true; } + + // also check parent + if( GtkWidget* parent = gtk_widget_get_parent( widget ) ) + { + name = G_OBJECT_TYPE_NAME( parent ); + for( unsigned int i = 0; names[i]; ++i ) + { if( g_object_is_a( G_OBJECT( parent ), names[i] ) || name.find( names[i] ) == 0 ) return true; } + + } + + // also check first widget path element (needed for xfce panel) + std::string widgetPath=Gtk::gtk_widget_path(widget); + { + for( unsigned int i = 0; names[i]; ++i ) + { + if( widgetPath.find(names[i]) != std::string::npos ) + return true; + } + } + + return false; + + } + + //____________________________________________________________ + void Gtk::gtk_widget_print_tree( GtkWidget* widget ) + { + + if( !widget ) return; + std::cerr << "Oxygen::Gtk::gtk_widget_print_tree - widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl; + while( ( widget = gtk_widget_get_parent( widget ) ) ) + { std::cerr << " parent: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl; } + + } + + //________________________________________________________ + bool Gtk::gdk_default_screen_is_composited( void ) + { + GdkScreen* screen( gdk_screen_get_default() ); + return (screen && gdk_screen_is_composited( screen ) ); + } + + //________________________________________________________ + bool Gtk::gtk_widget_has_rgba( GtkWidget* widget ) + { + + if( !widget ) return false; + if( !gdk_default_screen_is_composited() ) return false; + return gdk_visual_has_rgba( gtk_widget_get_visual (widget) ); + + } + + //________________________________________________________ + bool Gtk::gdk_window_is_base( GdkWindow* window ) + { + + if( !GDK_IS_WINDOW( window ) ) return false; + + GdkWindowTypeHint hint = gdk_window_get_type_hint( window ); + + #if OXYGEN_DEBUG + std::cerr << "Gtk::gdk_window_is_base - " << TypeNames::windowTypeHint( hint ) << std::endl; + #endif + + return( + hint == GDK_WINDOW_TYPE_HINT_NORMAL || + hint == GDK_WINDOW_TYPE_HINT_DIALOG || + hint == GDK_WINDOW_TYPE_HINT_UTILITY ); + } + + //________________________________________________________ + bool Gtk::gdk_window_nobackground( GdkWindow* window ) + { + if( !GDK_IS_WINDOW( window ) ) return false; + + GdkWindowTypeHint hint = gdk_window_get_type_hint( window ); + return( hint == GDK_WINDOW_TYPE_HINT_COMBO || hint == GDK_WINDOW_TYPE_HINT_TOOLTIP ); + + } + + //________________________________________________________ + bool Gtk::gdk_window_has_rgba( GdkWindow* window ) + { + + if( !window ) return false; + + if( !gdk_default_screen_is_composited() ) return false; + return gdk_visual_has_rgba( gdk_window_get_visual( window ) ); + + } + + //________________________________________________________ + bool Gtk::gdk_visual_has_rgba( GdkVisual* visual ) + { + // check depth + if( gdk_visual_get_depth( visual ) != 32 ) return false; + + // check red pixel + guint32 redMask; + gdk_visual_get_red_pixel_details( visual, &redMask, 0L, 0L ); + if( redMask != 0xff0000 ) return false; + + // check green pixel + guint32 greenMask; + gdk_visual_get_green_pixel_details( visual, &greenMask, 0L, 0L ); + if( greenMask != 0x00ff00 ) return false; + + // check blue pixel + guint32 blueMask; + gdk_visual_get_blue_pixel_details( visual, &blueMask, 0L, 0L ); + if( blueMask != 0x0000ff ) return false; + + return true; + + } + + //________________________________________________________ + bool Gtk::g_object_is_a( const GObject* object, const std::string& typeName ) + { + + if( object ) + { + const GType tmp( g_type_from_name( typeName.c_str() ) ); + if( tmp ) + { return g_type_check_instance_is_a( (GTypeInstance*) object, tmp ); } + } + + return false; + } + + //________________________________________________________ + std::string Gtk::gtk_widget_path( GtkWidget* widget ) + { + + if(GTK_IS_WIDGET(widget)) + { + gchar* widgetPath; + gtk_widget_path( widget, 0L, &widgetPath, 0L); + const std::string out( widgetPath ); + g_free( widgetPath ); + return out; + } + return std::string("not-widget"); + + } + + //________________________________________________________ + GtkWidget* Gtk::gtk_widget_find_parent( GtkWidget* widget, GType type ) + { + + for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) ) + { if( G_TYPE_CHECK_INSTANCE_TYPE( parent, type ) ) return parent; } + + return 0L; + } + + //________________________________________________________ + GtkWidget* Gtk::gtk_parent_groupbox( GtkWidget* widget ) + { + + for( GtkWidget* parent = widget; parent; parent = gtk_widget_get_parent( parent ) ) + { if( gtk_widget_is_groupbox( parent ) ) return parent; } + + return 0L; + } + + //________________________________________________________ + bool Gtk::gtk_widget_is_parent( GtkWidget* widget, GtkWidget* potentialParent ) + { + + for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) ) + { if( potentialParent==parent ) return true; } + + return false; + } + + //________________________________________________________ + bool Gtk::gtk_parent_is_shadow_in( GtkWidget* widget ) + { + for( GtkWidget* parent = gtk_widget_get_parent( widget ); parent; parent = gtk_widget_get_parent( parent ) ) + { + if( GTK_IS_FRAME( parent ) && gtk_frame_get_shadow_type( GTK_FRAME( parent ) ) == GTK_SHADOW_IN ) return true; + if( GTK_IS_SCROLLED_WINDOW( parent ) && gtk_scrolled_window_get_shadow_type( GTK_SCROLLED_WINDOW( parent ) ) == GTK_SHADOW_IN ) return true; + } + + return false; + } + + //________________________________________________________ + bool Gtk::gtk_button_is_flat( GtkWidget* widget ) + { + if( !GTK_IS_BUTTON( widget ) ) return false; + return ( gtk_button_get_relief( GTK_BUTTON( widget ) ) == GTK_RELIEF_NONE ); + } + + //________________________________________________________ + bool Gtk::gtk_button_is_header( GtkWidget* widget ) + { return GTK_IS_BUTTON( widget ) && gtk_parent_tree_view( widget ); } + + //________________________________________________________ + bool Gtk::gtk_button_is_in_path_bar( GtkWidget* widget ) + { + if( !( GTK_IS_BUTTON( widget ) && gtk_widget_get_parent( widget ) ) ) return false; + + std::string name(G_OBJECT_TYPE_NAME( gtk_widget_get_parent( widget ) ) ); + return name == "GtkPathBar" || name == "NautilusPathBar"; + } + + //________________________________________________________ + bool Gtk::gtk_path_bar_button_is_last( GtkWidget* widget ) + { + + GtkWidget* parent( gtk_widget_get_parent( widget ) ); + + // get parent and check type + if( !( parent && GTK_IS_CONTAINER( parent ) ) ) return false; + + // get children + GList* children( gtk_container_get_children( GTK_CONTAINER( parent ) ) ); + + /* + for some reason, pathbar buttons are ordered in the container in reverse order. + meaning that the last button (in the pathbar) is stored first in the list. + */ + bool result = (widget == g_list_first( children )->data ); + if( children ) g_list_free( children ); + return result; + + } + + //________________________________________________________ + GtkWidget* Gtk::gtk_button_find_image(GtkWidget* button) + { + + // check widget type + if(!GTK_IS_CONTAINER(button)) return 0L; + + GtkWidget* result( 0L ); + GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) ); + for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) + { + if( GTK_IS_IMAGE( child->data ) ) + { + result = GTK_WIDGET( child->data ); + break; + + } else if( GTK_IS_CONTAINER( child->data ) ) { + + result = gtk_button_find_image( GTK_WIDGET(child->data ) ); + break; + + } + + } + + if( children ) g_list_free( children ); + return result; + + } + + //________________________________________________________ + GtkWidget* Gtk::gtk_button_find_label(GtkWidget* button) + { + + // check widget type + if( !GTK_IS_CONTAINER(button) ) return 0L; + + GtkWidget* result( 0L ); + GList* children( gtk_container_get_children( GTK_CONTAINER( button ) ) ); + for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) + { + + if( GTK_IS_LABEL( child->data) ) + { + result = GTK_WIDGET( child->data ); + break; + + } else if( GTK_IS_CONTAINER( child->data ) ) { + + result = gtk_button_find_image(GTK_WIDGET(child->data)); + break; + + } + + } + + if( children ) g_list_free( children ); + return result; + + } + + //________________________________________________________ + bool Gtk::gtk_combobox_has_frame( GtkWidget* widget ) + { + + GValue val = { 0, }; + g_value_init(&val, G_TYPE_BOOLEAN); + g_object_get_property( G_OBJECT( widget ), "has-frame", &val ); + return (bool) g_value_get_boolean( &val ); + + } + + //________________________________________________________ + bool Gtk::gtk_combobox_is_tree_view( GtkWidget* widget ) + { + // check types and path + if( !widget && GTK_IS_TREE_VIEW( widget ) && GTK_IS_SCROLLED_WINDOW( gtk_widget_get_parent( widget ) ) ) return false; + return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow.GtkTreeView"; + } + + //________________________________________________________ + bool Gtk::gtk_combobox_is_scrolled_window( GtkWidget* widget ) + { + // check types and path + if( !GTK_IS_SCROLLED_WINDOW(widget) ) return false; + return Gtk::gtk_widget_path( widget ) == "gtk-combobox-popup-window.GtkScrolledWindow"; + } + + //________________________________________________________ + bool Gtk::gtk_combobox_is_viewport( GtkWidget* widget ) + { + if( !GTK_IS_VIEWPORT(widget) ) return false; + static const std::string match( "gtk-combo-popup-window" ); + return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match; + } + + //________________________________________________________ + bool Gtk::gtk_combobox_is_frame( GtkWidget* widget ) + { + if( !GTK_IS_FRAME(widget) ) return false; + static const std::string match( "gtk-combo-popup-window" ); + return Gtk::gtk_widget_path( widget ).substr( 0, match.size() ) == match; + } + + //________________________________________________________ + bool Gtk::gtk_combobox_appears_as_list( GtkWidget* widget ) + { + gboolean appearsAsList; + gtk_widget_style_get( widget, "appears-as-list", &appearsAsList, NULL ); + return (bool) appearsAsList; + } + + //________________________________________________________ + bool Gtk::gtk_notebook_tab_contains( GtkWidget* widget, int tab, int x, int y ) + { + + if( !( tab >= 0 && GTK_IS_NOTEBOOK( widget ) ) ) return false; + + // cast to notebook and check against number of pages + GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); + if( tab >= gtk_notebook_get_n_pages( notebook ) ) return false; + + // retrieve page and tab label + GtkWidget* page( gtk_notebook_get_nth_page( notebook, tab ) ); + GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); + + // get allocted size and compare to position + const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) ); + return Gtk::gdk_rectangle_contains( &allocation, x, y ); + + } + + //________________________________________________________ + int Gtk::gtk_notebook_find_tab( GtkWidget* widget, int x, int y ) + { + + if( !GTK_IS_NOTEBOOK( widget ) ) return -1; + + // cast to notebook and check against number of pages + GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); + int tab(-1); + int minDistance( -1 ); + for( int i = gtk_notebook_find_first_tab( widget ); i < gtk_notebook_get_n_pages( notebook ); ++i ) + { + + // retrieve page and tab label + GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); + if( !page ) continue; + + // get label + GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); + if(!tabLabel) continue; + + // get allocted size and compare to position + const GtkAllocation allocation( gtk_widget_get_allocation( tabLabel ) ); + + // get manhattan length + const int distance = int( + std::abs( double( allocation.x + allocation.width/2 - x ) ) + + std::abs( double( allocation.y + allocation.height/2 - y ) ) ); + if( minDistance < 0 || distance < minDistance ) + { + tab = i; + minDistance = distance; + } + } + + return tab; + + } + + //________________________________________________________ + int Gtk::gtk_notebook_find_first_tab( GtkWidget* widget ) + { + + // TODO: reimplement with gtk+3.0 + return 0; + +// if( !GTK_IS_NOTEBOOK( widget ) ) return 0; +// +// // cast to notebook +// GtkNotebook* notebook( GTK_NOTEBOOK( widget ) ); +// return g_list_position( notebook->children, notebook->first_tab ); + + } + + //____________________________________________________________ + bool Gtk::gtk_notebook_is_tab_label(GtkNotebook* notebook, GtkWidget* widget ) + { + + for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i ) + { + // retrieve page and tab label + GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); + if( !page ) continue; + + GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); + if( widget == tabLabel ) return true; + } + + return false; + + } + + + //____________________________________________________________ + void Gtk::gtk_notebook_get_tabbar_rect( GtkNotebook* notebook, GdkRectangle* rect ) + { + // check notebook and rect + if( !( notebook && rect ) ) return; + + // check tab visibility + GList* children( gtk_container_get_children( GTK_CONTAINER( notebook ) ) ); + if( !( gtk_notebook_get_show_tabs( notebook ) && children ) ) + { + if( children ) g_list_free( children ); + *rect = gdk_rectangle(); + return; + } + + // free children + if( children ) g_list_free( children ); + + // get full rect + gtk_widget_get_allocation( GTK_WIDGET( notebook ), rect ); + + // adjust to account for borderwidth + guint borderWidth( gtk_container_get_border_width( GTK_CONTAINER( notebook ) ) ); + rect->x += borderWidth; + rect->y += borderWidth; + rect->height -= 2*borderWidth; + rect->width -= 2*borderWidth; + + // get current page + int pageIndex( gtk_notebook_get_current_page( notebook ) ); + if( !( pageIndex >= 0 && pageIndex < gtk_notebook_get_n_pages( notebook ) ) ) + { + *rect = gdk_rectangle(); + return; + } + + GtkWidget* page( gtk_notebook_get_nth_page( notebook, pageIndex ) ); + if( !page ) + { + *rect = gdk_rectangle(); + return; + } + + // removes page allocated size from rect, based on tabwidget orientation + const GtkAllocation pageAllocation( gtk_widget_get_allocation( page ) ); + switch( gtk_notebook_get_tab_pos( notebook ) ) + { + case GTK_POS_BOTTOM: + rect->y += pageAllocation.height; + rect->height -= pageAllocation.height; + break; + + case GTK_POS_TOP: + rect->height -= pageAllocation.height; + break; + + case GTK_POS_RIGHT: + rect->x += pageAllocation.width; + rect->width -= pageAllocation.width; + break; + + case GTK_POS_LEFT: + rect->width -= pageAllocation.width; + break; + } + + return; + + } + + //____________________________________________________________ + bool Gtk::gtk_notebook_has_visible_arrows( GtkNotebook* notebook ) + { + + if( !gtk_notebook_get_show_tabs( notebook ) ) return false; + + // loop over pages + for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i ) + { + + // retrieve page and tab label + GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); + if( !page ) continue; + + GtkWidget* label( gtk_notebook_get_tab_label( notebook, page ) ); + if( label && !gtk_widget_get_mapped( label ) ) return true; + } + + return false; + + } + + //____________________________________________________________ + bool Gtk::gtk_notebook_update_close_buttons(GtkNotebook* notebook) + { + int numPages=gtk_notebook_get_n_pages( notebook ); + for( int i = 0; i < numPages; ++i ) + { + + // retrieve page + GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) ); + if( !page ) continue; + + // retrieve tab label + GtkWidget* tabLabel( gtk_notebook_get_tab_label( notebook, page ) ); + if( tabLabel && GTK_IS_CONTAINER( tabLabel ) ) + { gtk_container_adjust_buttons_state( GTK_CONTAINER( tabLabel ) ); } + + } + return FALSE; + } + + //________________________________________________________ + bool Gtk::gtk_notebook_is_close_button(GtkWidget* widget) + { + if( GtkNotebook* nb=GTK_NOTEBOOK(gtk_parent_notebook(widget) ) ) + { + // check if the button resides on tab label, not anywhere on the tab + bool tabLabelIsParent=false; + for( int i=0; i < gtk_notebook_get_n_pages(nb); ++i ) + { + GtkWidget* tabLabel( gtk_notebook_get_tab_label(nb,gtk_notebook_get_nth_page( nb, i ) ) ); + if( gtk_widget_is_parent( widget, GTK_WIDGET(tabLabel) ) ) + { tabLabelIsParent=true; } + } + + if( !tabLabelIsParent ) return false; + + // make sure button has no text and some image (for now, just hope it's a close icon) + if( gtk_button_find_image(widget) && !gtk_button_get_label( GTK_BUTTON(widget) ) ) + { return true; } + + // check for pidgin 'x' close button + if( GtkWidget* label = gtk_button_find_label(widget) ) + { + + const gchar* labelText=gtk_label_get_text( GTK_LABEL(label) ); + if(!strcmp(labelText,"×")) // It's not letter 'x' - it's a special symbol + { + gtk_widget_hide( label ); + return true; + } else return false; + + } else return false; + + } else return false; + + } + + //________________________________________________________ + bool Gtk::gtk_scrolled_window_force_sunken( GtkWidget* widget) + { + + // FMIconView (from nautilus) always get sunken + if( g_object_is_a( G_OBJECT( widget ), "FMIconView" ) ) return true; + + // other checks require widget to be of type GtkBin + if( !GTK_IS_BIN( widget ) ) return false; + + // retrieve child + GtkWidget* child( gtk_bin_get_child( GTK_BIN( widget ) ) ); + if( GTK_IS_TREE_VIEW( child ) || GTK_IS_ICON_VIEW( child ) ) return true; + else return false; + + } + + //________________________________________________________ + bool Gtk::gdk_window_map_to_toplevel( GdkWindow* window, gint* x, gint* y, gint* w, gint* h, bool frame ) + { + + // always initialize arguments (to invalid values) + if( x ) *x=0; + if( y ) *y=0; + if( w ) *w = -1; + if( h ) *h = -1; + + if( !( window && GDK_IS_WINDOW( window ) ) ) return false; + if( gdk_window_get_window_type( window ) == GDK_WINDOW_OFFSCREEN ) return false; + + // get window size and height + if( frame ) gdk_toplevel_get_frame_size( window, w, h ); + else gdk_toplevel_get_size( window, w, h ); + Gtk::gdk_window_get_toplevel_origin( window, x, y ); + return ((!w) || *w > 0) && ((!h) || *h>0); + + } + + //________________________________________________________ + bool Gtk::gtk_widget_map_to_toplevel( GtkWidget* widget, gint* x, gint* y, gint* w, gint* h, bool frame ) + { + + // always initialize arguments (to invalid values) + if( x ) *x=0; + if( y ) *y=0; + if( w ) *w = -1; + if( h ) *h = -1; + + if( !widget ) return false; + + // get window + GdkWindow* window( gtk_widget_get_parent_window( widget ) ); + if( !( window && GDK_IS_WINDOW( window ) ) ) return false; + if( gdk_window_get_window_type( window ) == GDK_WINDOW_OFFSCREEN ) return false; + + if( frame ) gdk_toplevel_get_frame_size( window, w, h ); + else gdk_toplevel_get_size( window, w, h ); + int xlocal, ylocal; + const bool success( gtk_widget_translate_coordinates( widget, gtk_widget_get_toplevel( widget ), 0, 0, &xlocal, &ylocal ) ); + if( success ) + { + + if( x ) *x=xlocal; + if( y ) *y=ylocal; + + } + + return success && ((!w) || *w > 0) && ((!h) || *h>0); + + } + + //________________________________________________________ + bool Gtk::gtk_widget_map_to_parent( GtkWidget* widget, GtkWidget* parent, gint* x, gint* y, gint* w, gint* h ) + { + + // always initialize arguments (to invalid values) + if( x ) *x=0; + if( y ) *y=0; + if( w ) *w = -1; + if( h ) *h = -1; + + if( !( widget && parent ) ) return false; + + const GtkAllocation allocation( gtk_widget_get_allocation( parent ) ); + if( w ) *w = allocation.width; + if( h ) *h = allocation.height; + + int xlocal, ylocal; + const bool success( gtk_widget_translate_coordinates( widget, parent, 0, 0, &xlocal, &ylocal ) ); + if( success ) + { + + if( x ) *x=xlocal; + if( y ) *y=ylocal; + + } + + return success && ((!w) || *w > 0) && ((!h) || *h>0); + + } + + //________________________________________________________ + bool Gtk::gdk_window_translate_origin( GdkWindow* parent, GdkWindow* child, gint* x, gint* y ) + { + if( x ) *x = 0; + if( y ) *y = 0; + if( !( parent && child ) ) return false; + while( child && GDK_IS_WINDOW( child ) && + child != parent && + gdk_window_get_window_type( child ) == GDK_WINDOW_CHILD ) + { + gint xloc; + gint yloc; + gdk_window_get_position( child, &xloc, &yloc ); + if( x ) *x += xloc; + if( y ) *y += yloc; + child = gdk_window_get_parent( child ); + } + + return( child == parent ); + + } + + //________________________________________________________ + void Gtk::gdk_toplevel_get_size( GdkWindow* window, gint* w, gint* h ) + { + + if( !( window && GDK_IS_WINDOW( window ) ) ) + { + if( w ) *w = -1; + if( h ) *h = -1; + return; + } + + if( GdkWindow* topLevel = gdk_window_get_toplevel( window ) ) + { + + if( w ) *w = gdk_window_get_width( topLevel ); + if( h ) *h = gdk_window_get_height( topLevel ); + + } else { + + if( w ) *w = gdk_window_get_width( window ); + if( h ) *h = gdk_window_get_height( window ); + + } + + return; + + } + + //________________________________________________________ + void Gtk::gdk_toplevel_get_frame_size( GdkWindow* window, gint* w, gint* h ) + { + + if( !( window && GDK_IS_WINDOW( window ) ) ) + { + if( w ) *w = -1; + if( h ) *h = -1; + return; + } + + GdkWindow* topLevel = gdk_window_get_toplevel( window ); + if( topLevel && GDK_IS_WINDOW( topLevel ) ) + { + if( gdk_window_get_window_type( topLevel ) == GDK_WINDOW_OFFSCREEN ) + { + + if( w ) *w = gdk_window_get_width(topLevel); + if( h ) *h = gdk_window_get_height(topLevel); + + } else { + + GdkRectangle rect = {0, 0, -1, -1}; + gdk_window_get_frame_extents( topLevel, &rect ); + + if( w ) *w = rect.width; + if( h ) *h = rect.height; + + } + } + + return; + + } + + //________________________________________________________ + void Gtk::gdk_window_get_toplevel_origin( GdkWindow* window, gint* x, gint* y ) + { + if( x ) *x = 0; + if( y ) *y = 0; + if( !window ) return; + while( window && GDK_IS_WINDOW( window ) && gdk_window_get_window_type( window ) == GDK_WINDOW_CHILD ) + { + gint xloc; + gint yloc; + gdk_window_get_position( window, &xloc, &yloc ); + if( x ) *x += xloc; + if( y ) *y += yloc; + window = gdk_window_get_parent( window ); + } + + return; + } + + //___________________________________________________________ + GdkPixbuf* Gtk::gdk_pixbuf_set_alpha( const GdkPixbuf *pixbuf, double alpha ) + { + + g_return_val_if_fail( pixbuf != 0L, 0L); + g_return_val_if_fail( GDK_IS_PIXBUF( pixbuf ), 0L ); + + /* Returns a copy of pixbuf with it's non-completely-transparent pixels to + have an alpha level "alpha" of their original value. */ + GdkPixbuf* target( gdk_pixbuf_add_alpha( pixbuf, false, 0, 0, 0 ) ); + if( alpha >= 1.0 ) return target; + if( alpha < 0 ) alpha = 0; + + const int width( gdk_pixbuf_get_width( target ) ); + const int height( gdk_pixbuf_get_height( target ) ); + const int rowstride( gdk_pixbuf_get_rowstride( target ) ); + unsigned char* data = gdk_pixbuf_get_pixels( target ); + + for( int y = 0; y < height; ++y ) + { + + for( int x = 0; x < width; ++x ) + { + /* The "4" is the number of chars per pixel, in this case, RGBA, + the 3 means "skip to the alpha" */ + unsigned char* current = data + ( y*rowstride ) + ( x*4 ) + 3; + *(current) = (unsigned char) ( *( current )*alpha ); + } + } + + return target; + } + + //_________________________________________________________ + bool Gtk::gdk_pixbuf_to_gamma(GdkPixbuf* pixbuf, double value) + { + if(gdk_pixbuf_get_colorspace(pixbuf)==GDK_COLORSPACE_RGB && + gdk_pixbuf_get_bits_per_sample(pixbuf)==8 && + gdk_pixbuf_get_has_alpha(pixbuf) && + gdk_pixbuf_get_n_channels(pixbuf)==4) + { + double gamma=1./(2.*value+0.5); + unsigned char* data=gdk_pixbuf_get_pixels(pixbuf); + const int height=gdk_pixbuf_get_height(pixbuf); + const int width=gdk_pixbuf_get_width(pixbuf); + const int rowstride=gdk_pixbuf_get_rowstride(pixbuf); + for(int x=0;x<width;++x) + { + for(int y=0; y<height; y++) + { + unsigned char* p=data + y*rowstride + x*4; + *p=(char)(pow((*p/255.),gamma)*255); ++p; + *p=(char)(pow((*p/255.),gamma)*255); ++p; + *p=(char)(pow((*p/255.),gamma)*255); + } + + } + + return true; + + } else return false; + + } + + //___________________________________________________________ + GdkPixbuf* Gtk::gdk_pixbuf_resize( GdkPixbuf* src, int width, int height ) + { + if( width == gdk_pixbuf_get_width( src ) && height == gdk_pixbuf_get_height( src ) ) + { + + return static_cast<GdkPixbuf*>(g_object_ref (src)); + + } else { + + return gdk_pixbuf_scale_simple( src, width, height, GDK_INTERP_BILINEAR ); + + } + + } + + //___________________________________________________________ + void Gtk::gtk_viewport_get_position( GtkViewport* viewport, gint* x, gint* y ) + { + + // initialize + if( x ) *x = 0; + if( y ) *y = 0; + + // get windows and derive offsets + gint xBin(0), yBin(0); + gdk_window_get_geometry( gtk_viewport_get_bin_window( viewport ), &xBin, &yBin, 0, 0 ); + + gint xView(0), yView(0); + gdk_window_get_geometry( gtk_viewport_get_view_window( viewport ), &xView, &yView, 0, 0 ); + + // calculate offsets + if( x ) *x = xView - xBin; + if( y ) *y = yView - yBin; + + // also correct from widget thickness + GtkStyle* style( gtk_widget_get_style( GTK_WIDGET( viewport ) ) ); + if( style ) + { + if( x ) *x -= style->xthickness; + if( y ) *y -= style->ythickness; + } + + return; + + } + + //___________________________________________________________ + GtkWidget* Gtk::gtk_dialog_find_button(GtkDialog* dialog,gint response_id) + { + + // get children of dialog's action area + GList* children( gtk_container_get_children( GTK_CONTAINER( gtk_dialog_get_action_area( dialog ) ) ) ); + + #if OXYGEN_DEBUG + std::cerr << "Oxygen::Gtk::gtk_dialog_find_button - buttons: "; + #endif + + for( GList *child = g_list_first( children ); child; child = g_list_next( child ) ) + { + + // check data + if( !GTK_IS_WIDGET( child->data ) ) continue; + GtkWidget* childWidget( GTK_WIDGET( child->data ) ); + + const gint id( gtk_dialog_get_response_for_widget(dialog, childWidget ) ); + + #if OXYGEN_DEBUG + std::cerr << Gtk::TypeNames::response( (GtkResponseType) id ) << ", "; + #endif + if( id == response_id ) return childWidget; + + } + + #if OXYGEN_DEBUG + std::cerr << std::endl; + #endif + + if( children ) g_list_free( children ); + return 0L; + + } + |