File indexing completed on 2024-04-28 05:32:12
0001 #ifndef oxygengtkutils_h 0002 #define oxygengtkutils_h 0003 /* 0004 * this file is part of the oxygen gtk engine 0005 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0006 * SPDX-FileCopyrightText: 2010 Ruslan Kabatsayev <b7.10110111@gmail.com> 0007 * 0008 * GdkPixbuf modification code from Walmis 0009 * <http://gnome-look.org/content/show.php?content=77783&forumpage=3> 0010 * 0011 * SPDX-License-Identifier: LGPL-2.0-or-later 0012 */ 0013 0014 #include <gdk/gdk.h> 0015 #include <gtk/gtk.h> 0016 #include <string> 0017 0018 #include "oxygenrgba.h" 0019 0020 namespace Oxygen 0021 { 0022 0023 //! GdkRectangle streamer 0024 inline std::ostream& operator << (std::ostream& out, const GdkRectangle& rect ) 0025 { 0026 out << "( " << rect.x << "," << rect.y << "," << rect.width << "," << rect.height << ")"; 0027 return out; 0028 } 0029 0030 //! GtkBorder streamer 0031 inline std::ostream& operator << (std::ostream& out, const GtkBorder& border ) 0032 { 0033 out << "( " << border.left << "," << border.right << "," << border.top << "," << border.bottom << ")"; 0034 return out; 0035 } 0036 0037 //! GtkContainer streamer 0038 inline std::ostream& operator << (std::ostream& out, GtkContainer* container) 0039 { 0040 GList* children=gtk_container_get_children(container); 0041 for(GList* child=g_list_first(children); child; child=g_list_next(child)) 0042 { 0043 out << G_OBJECT_TYPE_NAME(child->data) << " "; 0044 } 0045 g_list_free(children); 0046 return out; 0047 } 0048 0049 namespace Gtk 0050 { 0051 0052 //! mouse button enumeration 0053 enum MouseButton 0054 { 0055 NoButton = 0, 0056 LeftButton = 1, 0057 RightButton = 2, 0058 MidButton = 3 0059 }; 0060 0061 //@!name gdk utilities 0062 //@{ 0063 0064 //! returns OxygenRgba color from GdkColor 0065 inline ColorUtils::Rgba gdk_get_color( const GdkColor& color ) 0066 { 0067 return ColorUtils::Rgba( 0068 double(color.red)/0xffff, 0069 double(color.green)/0xffff, 0070 double(color.blue)/0xffff ); 0071 } 0072 0073 //! map window origin to top level 0074 /*! 0075 x and y correspond to (0,0) maped to toplevel window; 0076 w and h correspond to toplevel window frame size 0077 */ 0078 bool gdk_window_map_to_toplevel( GdkWindow*, gint*, gint*, gint*, gint*, bool frame = false ); 0079 0080 //! map widget origin to top level 0081 /*! 0082 x and y correspond to (0,0) maped to toplevel window; 0083 w and h correspond to toplevel window frame size 0084 */ 0085 bool gtk_widget_map_to_toplevel( GtkWidget*, gint*, gint*, gint*, gint*, bool frame = false ); 0086 0087 //! map widget onto another (parent) widget 0088 /*! second argument can be any parent in widget's ancestry tree */ 0089 bool gtk_widget_map_to_parent( GtkWidget*, GtkWidget*, gint*, gint*, gint*, gint* ); 0090 0091 //! map window/widget origin to top level 0092 inline bool gdk_map_to_toplevel( GdkWindow* window, GtkWidget* widget, gint* x, gint* y, gint* w, gint* h, bool frame = false ) 0093 { 0094 if( window && GDK_IS_WINDOW( window ) ) return gdk_window_map_to_toplevel( window, x, y, w, h, frame ); 0095 else return gtk_widget_map_to_toplevel( widget, x, y, w, h, frame ); 0096 } 0097 0098 //! map window origin to top level 0099 inline bool gdk_map_to_toplevel( GdkWindow* window, gint* x, gint* y, gint* w, gint* h, bool frame = false ) 0100 { return gdk_window_map_to_toplevel( window, x, y, w, h, frame ); } 0101 0102 //! translate origin of child window into parent 0103 /*! returns true on success */ 0104 bool gdk_window_translate_origin( GdkWindow*, GdkWindow*, gint*, gint* ); 0105 0106 //! get top level windows dimension 0107 void gdk_toplevel_get_size( GdkWindow*, gint*, gint* ); 0108 0109 //! get top level windows dimension 0110 void gdk_toplevel_get_frame_size( GdkWindow*, gint*, gint* ); 0111 0112 //! get position relatve to toplevel 0113 void gdk_window_get_toplevel_origin( GdkWindow*, gint*, gint* ); 0114 0115 //! add alpha channel to pixbuf 0116 GdkPixbuf* gdk_pixbuf_set_alpha( const GdkPixbuf*, double ); 0117 0118 //! changes the gamma value of an image 0119 bool gdk_pixbuf_to_gamma( GdkPixbuf* pixbuf, double value ); 0120 0121 //! resize pixbuf 0122 GdkPixbuf* gdk_pixbuf_resize( GdkPixbuf* src, int width, int height ); 0123 0124 //! returns initialized GdkRectangle 0125 inline GdkRectangle gdk_rectangle( int x = 0, int y = 0, int w = -1, int h = -1 ) 0126 { 0127 GdkRectangle out = {x, y, w, h}; 0128 return out; 0129 } 0130 0131 //! returns true if rectangle is valid 0132 inline bool gdk_rectangle_is_valid( const GdkRectangle* rect ) 0133 { return rect && rect->width > 0 && rect->height > 0; } 0134 0135 //! performs union of two rectangle, properly accounting for their validity 0136 inline void gdk_rectangle_union( const GdkRectangle* first, const GdkRectangle* second, GdkRectangle* out ) 0137 { 0138 if( !out ) return; 0139 const bool firstIsValid( Gtk::gdk_rectangle_is_valid( first ) ); 0140 const bool secondIsValid( Gtk::gdk_rectangle_is_valid( second ) ); 0141 if( firstIsValid && secondIsValid ) ::gdk_rectangle_union( first, second, out ); 0142 else if( secondIsValid ) *out = *second; 0143 else *out = *first; 0144 } 0145 0146 //! returns true if given rectangle contains point 0147 inline bool gdk_rectangle_contains( const GdkRectangle* rect, int x, int y ) 0148 { 0149 return 0150 rect && 0151 ( rect->x <= x && (rect->x + rect->width) > x ) && 0152 ( rect->y <= y && (rect->y + rect->height) > y ); 0153 } 0154 0155 //@} 0156 0157 //! returns true if widget's layout is reversed 0158 inline bool gtk_widget_layout_is_reversed( GtkWidget* widget ) 0159 { return widget ? gtk_widget_get_direction( widget ) == GTK_TEXT_DIR_RTL : false; } 0160 0161 //! set all buttons in the container to state NORMAL 0162 void gtk_container_adjust_buttons_state( GtkContainer*, gpointer=0L ); 0163 0164 //! returns widget allocation 0165 inline GtkAllocation gtk_widget_get_allocation( GtkWidget* widget ) 0166 { 0167 #if GTK_CHECK_VERSION(2, 18, 0) 0168 GtkAllocation allocation = { 0, 0, -1, -1 }; 0169 ::gtk_widget_get_allocation( widget, &allocation ); 0170 return allocation; 0171 #else 0172 assert( widget ); 0173 return widget->allocation; 0174 #endif 0175 0176 } 0177 0178 //! returns true if widget is a groupbox (a la Qt) 0179 inline bool gtk_widget_is_groupbox( GtkWidget* widget ) 0180 { 0181 return 0182 GTK_IS_FRAME( widget ) && 0183 gtk_frame_get_label_widget( GTK_FRAME( widget ) ) && 0184 gtk_frame_get_shadow_type( GTK_FRAME( widget ) ) == GTK_SHADOW_OUT; 0185 } 0186 0187 //! returns true if widget (or one of its parent) has a custom background 0188 bool gtk_widget_has_custom_background( GtkWidget*, GtkStateType = GTK_STATE_NORMAL ); 0189 0190 //! returns true if is an Gnome applet 0191 bool gtk_widget_is_applet( GtkWidget* ); 0192 0193 //! print some widget information 0194 void gtk_widget_print_tree( GtkWidget* ); 0195 0196 //! returns true if widget supports rgba 0197 bool gtk_widget_has_rgba( GtkWidget* ); 0198 0199 //! returns true if default screen is composited 0200 bool gdk_default_screen_is_composited( void ); 0201 0202 //! returns true if window supports rgba 0203 bool gdk_window_has_rgba( GdkWindow* ); 0204 0205 //! true if visual supports rgba 0206 bool gdk_visual_has_rgba( GdkVisual* ); 0207 0208 //! returns true if window is a base window 0209 bool gdk_window_is_base( GdkWindow* ); 0210 0211 //! returns true if window is a base window that do not need painting 0212 bool gdk_window_nobackground( GdkWindow* ); 0213 0214 //! true if object match a given type 0215 bool g_object_is_a( const GObject*, const std::string& ); 0216 0217 //! trigger area update using GdkRectangle 0218 inline void gtk_widget_queue_draw( GtkWidget* widget, const GdkRectangle* rect = 0L ) 0219 { 0220 if( !gdk_rectangle_is_valid( rect ) ) ::gtk_widget_queue_draw( widget ); 0221 else ::gtk_widget_queue_draw_area( widget, rect->x, rect->y, rect->width, rect->height ); 0222 } 0223 0224 //!@name check parent type 0225 //@{ 0226 0227 //! returns widget path as a string 0228 std::string gtk_widget_path( GtkWidget* ); 0229 0230 //! return parent of given type if any 0231 GtkWidget* gtk_widget_find_parent( GtkWidget*, GType ); 0232 0233 //! return parent of given type 0234 inline GtkWidget* gtk_widget_find_parent( GtkWidget* widget, const std::string& typeName ) 0235 { 0236 const GType tmp( g_type_from_name( typeName.c_str() ) ); 0237 return tmp ? gtk_widget_find_parent( widget, tmp ): 0L; 0238 } 0239 0240 //! return parent "group box" if any. 0241 GtkWidget* gtk_parent_groupbox( GtkWidget* widget ); 0242 0243 //! return parent button if any. 0244 inline GtkWidget* gtk_parent_button( GtkWidget* widget ) 0245 { return gtk_widget_find_parent( widget, GTK_TYPE_BUTTON ); } 0246 0247 //! return parent menu if any 0248 inline GtkWidget* gtk_parent_menubar( GtkWidget* widget ) 0249 { return gtk_widget_find_parent( widget, GTK_TYPE_MENU_BAR ); } 0250 0251 //! return parent menu if any 0252 inline GtkWidget* gtk_parent_menu( GtkWidget* widget ) 0253 { return gtk_widget_find_parent( widget, GTK_TYPE_MENU ); } 0254 0255 //! return parent treeview if any. 0256 inline GtkWidget* gtk_parent_tree_view( GtkWidget* widget ) 0257 { return gtk_widget_find_parent( widget, GTK_TYPE_TREE_VIEW ); } 0258 0259 //! return parent combobox if any. 0260 inline GtkWidget* gtk_parent_combo( GtkWidget* widget ) 0261 { return gtk_widget_find_parent( widget, GTK_TYPE_COMBO ); } 0262 0263 //! return parent combobox if any. 0264 inline GtkWidget* gtk_parent_combobox( GtkWidget* widget ) 0265 { return gtk_widget_find_parent( widget, GTK_TYPE_COMBO_BOX ); } 0266 0267 //! return parent combobox if any. 0268 inline GtkWidget* gtk_parent_combobox_entry( GtkWidget* widget ) 0269 { 0270 // try get parent combobox entry 0271 GtkWidget* out(0L); 0272 if( ( out = gtk_widget_find_parent( widget, GTK_TYPE_COMBO_BOX_ENTRY ) ) ) return out; 0273 0274 // if not found, get parent combobox and check if it has an entry 0275 if( !(out = gtk_widget_find_parent( widget, GTK_TYPE_COMBO_BOX ) ) ) return 0L; 0276 0277 #if GTK_CHECK_VERSION(2, 24, 0) 0278 return gtk_combo_box_get_has_entry( GTK_COMBO_BOX( out ) ) ? out:0L; 0279 #else 0280 return GTK_IS_ENTRY( gtk_bin_get_child( GTK_BIN( out ) ) ) ? out:0L; 0281 #endif 0282 0283 } 0284 0285 //! return parent scrolled window if any. 0286 inline GtkWidget* gtk_parent_scrolled_window( GtkWidget* widget ) 0287 { return gtk_widget_find_parent( widget, GTK_TYPE_SCROLLED_WINDOW ); } 0288 0289 //! return parent statusbar if any. 0290 inline GtkWidget* gtk_parent_statusbar( GtkWidget* widget ) 0291 { return gtk_widget_find_parent( widget, GTK_TYPE_STATUSBAR ); } 0292 0293 //! return parent combobox if any. 0294 inline GtkWidget* gtk_parent_notebook( GtkWidget* widget ) 0295 { return gtk_widget_find_parent( widget, GTK_TYPE_NOTEBOOK ); } 0296 0297 //! returns true if potentialParent is (maybe indirect) parent of widget 0298 bool gtk_widget_is_parent( GtkWidget*, GtkWidget* potentialParent ); 0299 0300 //! returns true if one of the parent widgets has a sunken shadow 0301 bool gtk_parent_is_shadow_in( GtkWidget* ); 0302 0303 //@} 0304 0305 //! true if a widget (orientable) is horizontal 0306 inline bool gtk_widget_is_horizontal( GtkWidget* widget ) 0307 { 0308 if( !GTK_IS_ORIENTABLE( widget ) ) return true; 0309 return gtk_orientable_get_orientation( GTK_ORIENTABLE( widget ) ) == GTK_ORIENTATION_HORIZONTAL; 0310 } 0311 0312 0313 //! true if a widget (orientable) is vertical 0314 inline bool gtk_widget_is_vertical( GtkWidget* widget ) 0315 { 0316 if( !GTK_IS_ORIENTABLE( widget ) ) return false; 0317 return gtk_orientable_get_orientation( GTK_ORIENTABLE( widget ) ) == GTK_ORIENTATION_VERTICAL; 0318 } 0319 0320 //! true if scrolled window must be forced to have a sunken frame 0321 bool gtk_scrolled_window_force_sunken( GtkWidget* ); 0322 0323 //! returns true if widget is a tooltip, useful when GTK_IS_TOOLTIP() gives false for real tooltip 0324 bool gtk_is_tooltip( GtkWidget* widget ); 0325 0326 //!@name button utilities 0327 //@{ 0328 0329 //! true for 'flat' buttons (e.g. toolbuttons) 0330 bool gtk_button_is_flat( GtkWidget* ); 0331 0332 //! true for treeview headers and affiliated 0333 bool gtk_button_is_header( GtkWidget* ); 0334 0335 //! true for buttons in path bars 0336 bool gtk_button_is_in_path_bar( GtkWidget* widget ); 0337 0338 //! true if widget is last in path bar 0339 bool gtk_path_bar_button_is_last( GtkWidget* widget ); 0340 0341 //! returns an image on button-container 0342 GtkWidget* gtk_button_find_image( GtkWidget* ); 0343 0344 //! returns an image on button-container 0345 GtkWidget* gtk_button_find_label( GtkWidget* ); 0346 0347 //@} 0348 0349 //!@name combobox utilities 0350 //@{ 0351 0352 //! returns true if combobox has frame 0353 bool gtk_combobox_has_frame( GtkWidget* ); 0354 0355 //! true if widget is the treeview of a combobox 0356 bool gtk_combobox_is_tree_view( GtkWidget* ); 0357 0358 //! true if widget is the scrolled window of a combobox 0359 bool gtk_combobox_is_scrolled_window( GtkWidget* ); 0360 0361 //! true if widget is the viewport of a combo 0362 bool gtk_combo_is_viewport( GtkWidget* ); 0363 0364 //! true if widget is the frame of a combo 0365 bool gtk_combo_is_frame( GtkWidget* ); 0366 0367 //! true if widget is the popup window of a combobox 0368 bool gtk_combobox_is_popup( GtkWidget* ); 0369 0370 //! true if widget is the popup window of a combo 0371 bool gtk_combo_is_popup( GtkWidget* ); 0372 0373 //! true if combobox must appear as list 0374 bool gtk_combobox_appears_as_list( GtkWidget* ); 0375 0376 //@} 0377 0378 //!@name notebook utilities 0379 //@{ 0380 0381 //! returns true if position is in hovered tab 0382 //* this should move to OxygenTabWidgetData 0383 bool gtk_notebook_tab_contains( GtkWidget*, int tab, int x, int y ); 0384 0385 //! returns tab matching position or -1 if none 0386 int gtk_notebook_find_tab( GtkWidget*, int x, int y ); 0387 0388 //! returns index of first visible tab 0389 int gtk_notebook_find_first_tab( GtkWidget* ); 0390 0391 //! returns true if widget is one of the notebook's tab labels 0392 bool gtk_notebook_is_tab_label( GtkNotebook*, GtkWidget* ); 0393 0394 //! returns tabbar rect in notebook 0395 void gtk_notebook_get_tabbar_rect( GtkNotebook*, GdkRectangle* ); 0396 0397 //! returns true if notebook has visible scrollbar arrows 0398 /*! arrows are dimmed visible if at least one of the child tab_labels is unmapped */ 0399 bool gtk_notebook_has_visible_arrows( GtkNotebook* ); 0400 0401 // make all the buttons on the tabs normal 0402 bool gtk_notebook_update_close_buttons( GtkNotebook*); 0403 0404 //! returns true if widget is a notebook close button 0405 bool gtk_notebook_is_close_button( GtkWidget* ); 0406 0407 //@} 0408 0409 //! calculates viewport offsets (between view window and bin window 0410 void gtk_viewport_get_position( GtkViewport*, gint*, gint* ); 0411 0412 //! returns a widget which has response_id as response id for dialog 0413 GtkWidget* gtk_dialog_find_button( GtkDialog*, gint ); 0414 0415 //! store quarks 0416 class Quarks 0417 { 0418 public: 0419 0420 //! parent class 0421 inline static GQuark rcStyle( void ) 0422 { 0423 0424 // try initialize 0425 if( !_rcStyle ) 0426 { _rcStyle = g_quark_try_string( "gtk-rc-style" ); } 0427 0428 return _rcStyle; 0429 0430 } 0431 0432 0433 private: 0434 0435 //! RC style quark 0436 /*! 0437 used to check whether an RCStyle was installed on a given widget or not. 0438 See gtkwidet::gtk_widget_get_modifier_style() 0439 */ 0440 static GQuark _rcStyle; 0441 0442 }; 0443 0444 //! returns true if widget style color is modified 0445 inline bool gtk_widget_style_is_modified( GtkWidget* widget, GtkStateType state, GtkRcFlags flag ) 0446 { 0447 const bool hasRCStyle( g_object_get_qdata (G_OBJECT (widget), Quarks::rcStyle() ) ); 0448 return ( hasRCStyle && gtk_widget_get_modifier_style(widget)->color_flags[state]&flag ); 0449 } 0450 0451 0452 } 0453 0454 } 0455 #endif