You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gtk3-tqt-engine/tdegtk/tdegtk-utils.cpp

1065 lines
34 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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;
}