diff -u gparted-0.2.5/include/Win_GParted.h gparted-0.2.5/include/Win_GParted.h --- gparted-0.2.5/include/Win_GParted.h +++ gparted-0.2.5/include/Win_GParted.h @@ -161,4 +161,7 @@ bool stdin_event( Glib::IOCondition condition ); + void set_transient_for_this( Gtk::Window &dialog ); + void set_transient_for_xid( Gtk::Window *dialog, GdkNativeWindow xid ); + //private variables unsigned int current_device ; diff -u gparted-0.2.5/src/Win_GParted.cc gparted-0.2.5/src/Win_GParted.cc --- gparted-0.2.5/src/Win_GParted.cc +++ gparted-0.2.5/src/Win_GParted.cc @@ -35,7 +35,8 @@ #include #include -#define TRANSIENT_TARGET (*((installer_mode)?((Gtk::Window*)(this ->plug)):((Gtk::Window*)this))) +#include +#include namespace GParted { @@ -745,12 +746,12 @@ { if ( operations .size() ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - _("Quit GParted?"), + Gtk::MessageDialog dialog( _("Quit GParted?"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true ); + set_transient_for_this( dialog ); if ( operations .size() != 1 ) dialog .set_secondary_text( String::ucompose( _("%1 operations are currently pending."), @@ -1008,13 +1009,13 @@ if ( readonly_paths .size() > 0 ) { Gtk::MessageDialog dialog( - TRANSIENT_TARGET, _("The kernel is unable to re-read the partitiontables on the following devices:") + Glib::build_path( "", readonly_paths ), false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true ) ; + set_transient_for_this( dialog ); dialog .set_secondary_text( _("Because of this you will only have limited access to these devices. Unmount all mounted partitions on a device to get full access.") ) ; @@ -1083,7 +1084,7 @@ void Win_GParted::menu_gparted_features() { DialogFeatures dialog ; - dialog .set_transient_for( TRANSIENT_TARGET ) ; + set_transient_for_this( dialog ) ; dialog .load_filesystems( gparted_core .get_filesystems() ) ; while ( dialog .run() == Gtk::RESPONSE_OK ) @@ -1141,12 +1142,12 @@ void Win_GParted::menu_help_contents() { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - _("Sorry, not yet implemented."), + Gtk::MessageDialog dialog( _("Sorry, not yet implemented."), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true ); + set_transient_for_this( dialog ); dialog .set_secondary_text( _( "Please visit http://gparted.sf.net for more information and support.") ) ; @@ -1159,7 +1160,7 @@ std::vector strings ; Gtk::AboutDialog dialog ; - dialog .set_transient_for( TRANSIENT_TARGET ) ; + set_transient_for_this( dialog ) ; dialog .set_name( _("GParted") ) ; dialog .set_logo( this ->get_icon() ) ; @@ -1218,13 +1219,13 @@ if ( ! selected_partition .inside_extended && primary_count >= devices[ current_device ] .max_prims ) { Gtk::MessageDialog dialog( - TRANSIENT_TARGET, String::ucompose( _("It is not possible to create more than %1 primary partitions"), devices[ current_device ] .max_prims ), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ) ; + set_transient_for_this( dialog ); dialog .set_secondary_text( _( "If you want more partitions you should first create an extended partition. Such a partition can contain other partitions. Because an extended partition is also a primary partition it might be necessary to remove a primary partition first.") ) ; @@ -1258,7 +1259,7 @@ else dialog .Set_Data( selected_partition, partitions ); - dialog .set_transient_for( TRANSIENT_TARGET ) ; + set_transient_for_this( dialog ) ; if ( dialog .run() == Gtk::RESPONSE_OK ) { @@ -1310,7 +1311,7 @@ copied_partition .error .clear() ; copied_partition .clear_mountpoints() ; dialog .Set_Data( selected_partition, copied_partition ) ; - dialog .set_transient_for( TRANSIENT_TARGET ); + set_transient_for_this( dialog ); if ( dialog .run() == Gtk::RESPONSE_OK ) { @@ -1349,7 +1350,7 @@ devices[ current_device ] .readonly, devices[ current_device ] .cylsize ) ; - dialog .set_transient_for( TRANSIENT_TARGET ); + set_transient_for_this( dialog ); if ( dialog .run() == Gtk::RESPONSE_OK ) { @@ -1374,12 +1375,12 @@ selected_partition .status != GParted::STAT_NEW && selected_partition .partition_number < devices[ current_device ] .highest_busy ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - String::ucompose( _( "Unable to delete %1!"), selected_partition .get_path() ), + Gtk::MessageDialog dialog( String::ucompose( _( "Unable to delete %1!"), selected_partition .get_path() ), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ) ; + set_transient_for_this( dialog ); dialog .set_secondary_text( String::ucompose( _("Please unmount any logical partitions having a number higher than %1"), @@ -1392,13 +1393,13 @@ //if partition is on the clipboard...(NOTE: we can't use Partition::== here..) if ( selected_partition .get_path() == copied_partition .get_path() ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - String::ucompose( _( "Are you sure you want to delete %1?"), + Gtk::MessageDialog dialog( String::ucompose( _( "Are you sure you want to delete %1?"), selected_partition .get_path() ), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true ) ; + set_transient_for_this( dialog ); dialog .set_secondary_text( _("After deletion this partition is no longer available for copying.") ) ; @@ -1451,7 +1452,7 @@ void Win_GParted::activate_info() { Dialog_Partition_Info dialog( selected_partition ); - dialog .set_transient_for( TRANSIENT_TARGET ); + set_transient_for_this( dialog ); dialog .run(); } @@ -1463,13 +1464,13 @@ if ( selected_partition .get_length() < fs .MIN || fs .MAX && selected_partition .get_length() > fs .MAX ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - String::ucompose( _("Cannot format this filesystem to %1."), + Gtk::MessageDialog dialog( String::ucompose( _("Cannot format this filesystem to %1."), Utils::get_filesystem_string( new_fs ) ) , false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ); + set_transient_for_this( dialog ); if ( selected_partition .get_length() < fs .MIN ) dialog .set_secondary_text( String::ucompose( @@ -1609,12 +1610,12 @@ if ( ! succes ) { Gtk::MessageDialog dialog( - TRANSIENT_TARGET, selected_partition .busy ? _("Could not deactivate swap") : _("Could not activate swap"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ) ; + set_transient_for_this( dialog ); dialog .set_secondary_text( error ) ; @@ -1630,12 +1631,12 @@ if ( ! succes ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - String::ucompose( _("Could not unmount %1"), selected_partition .get_path() ), + Gtk::MessageDialog dialog( String::ucompose( _("Could not unmount %1"), selected_partition .get_path() ), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ); + set_transient_for_this( dialog ); dialog .set_secondary_text( error, true ) ; @@ -1666,14 +1667,14 @@ if ( ! succes ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - String::ucompose( _("Could not mount %1 on %2"), + Gtk::MessageDialog dialog( String::ucompose( _("Could not mount %1 on %2"), selected_partition .get_path(), selected_partition .get_mountpoints()[ index ] ), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ); + set_transient_for_this( dialog ); dialog .set_secondary_text( error, true ) ; @@ -1686,18 +1687,18 @@ void Win_GParted::activate_disklabel() { Dialog_Disklabel dialog( devices[ current_device ] .get_path(), gparted_core .get_disklabeltypes() ) ; - dialog .set_transient_for( TRANSIENT_TARGET ); + set_transient_for_this( dialog ); if ( dialog .run() == Gtk::RESPONSE_OK ) { - Gtk::MessageDialog m_dialog( TRANSIENT_TARGET, - String::ucompose( _("Are you sure you want to create a %1 disklabel on %2?"), + Gtk::MessageDialog m_dialog( String::ucompose( _("Are you sure you want to create a %1 disklabel on %2?"), dialog .Get_Disklabel(), devices[ current_device ] .get_path() ), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_CANCEL, true ) ; + set_transient_for_this( m_dialog ); m_dialog .set_secondary_text( String::ucompose( _("This operation will destroy all data on %1!"), devices[ current_device ] .get_path() ) ) ; @@ -1707,12 +1708,12 @@ if ( m_dialog .run() == Gtk::RESPONSE_OK && ! gparted_core .Set_Disklabel( devices[ current_device ] .get_path(), dialog .Get_Disklabel() ) ) { - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - _("Error while setting new disklabel"), + Gtk::MessageDialog dialog( _("Error while setting new disklabel"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true ) ; + set_transient_for_this( dialog ); dialog .run() ; } @@ -1730,7 +1731,7 @@ Gtk::Main::iteration() ; DialogManageFlags dialog( selected_partition, gparted_core .get_available_flags( selected_partition ) ) ; - dialog .set_transient_for( TRANSIENT_TARGET ) ; + set_transient_for_this( dialog ); dialog .signal_get_flags .connect( sigc::mem_fun( &gparted_core, &GParted_Core::get_available_flags ) ) ; dialog .signal_toggle_flag .connect( @@ -1785,12 +1786,12 @@ if ( ! operations .size( ) ) return true; - Gtk::MessageDialog dialog( TRANSIENT_TARGET, - _("Are you sure you want to apply the pending operations?"), + Gtk::MessageDialog dialog( _("Are you sure you want to apply the pending operations?"), false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, true ); + set_transient_for_this( dialog ); dialog .set_secondary_text( _( "It is recommended to backup valuable data before proceeding.") ) ; dialog .set_title( _( "Apply operations to harddisk" ) ); @@ -1803,7 +1804,7 @@ dialog .hide() ; //hide confirmationdialog Dialog_Progress dialog_progress( operations ) ; - dialog_progress .set_transient_for( TRANSIENT_TARGET ) ; + set_transient_for_this( dialog_progress ); dialog_progress .signal_apply_operation .connect( sigc::mem_fun(gparted_core, &GParted_Core::apply_operation_to_disk) ) ; @@ -1864,6 +1865,84 @@ return true; } +void Win_GParted::set_transient_for_this( Gtk::Window &dialog ) +{ + if ( installer_mode ) + { + GdkWindow *window = get_window() ->gobj(); + Display *xdisplay = GDK_WINDOW_XDISPLAY( window ); + // These should really be of type Window, but for some + // reason that clashes with Gdk::Window. + XID xid = installer_mode, root, parent, *children; + unsigned int nchildren; + + for ( ;; ) + { + static Atom WM_STATE = + XInternAtom( xdisplay, "WM_STATE", False ); + Atom type; + int format; + unsigned long nitems, after; + unsigned char *data = NULL; + + if ( XGetWindowProperty( xdisplay, xid, WM_STATE, 0, 0, + False, AnyPropertyType, &type, + &format, &nitems, &after, + &data) == Success ) + { + if ( data ) + XFree( (char *) data ); + if ( type ) + { + // Found a toplevel window + break; + } + } + + if ( XQueryTree( xdisplay, xid, &root, &parent, + &children, &nchildren ) == 0 ) + { + xid = 0; + break; + } + + XFree( children ); + + xid = parent; + } + + if ( xid ) + set_transient_for_xid( &dialog, xid ); + } + else + dialog .set_transient_for( *(Gtk::Window *) this ); +} + +void Win_GParted::set_transient_for_xid( Gtk::Window *dialog, GdkNativeWindow xid ) +{ + if ( ! dialog ->is_realized() ) + { + dialog ->signal_realize() .connect( + sigc::bind( + sigc::mem_fun( this, &Win_GParted::set_transient_for_xid ), + dialog, xid ) ); + return; + } + + GdkDisplay *display = + gdk_drawable_get_display( GDK_DRAWABLE( + get_window() -> gobj() ) ); + GdkWindow *transient_parent = + gdk_window_lookup_for_display( display, xid ); + if ( !transient_parent ) + transient_parent = + gdk_window_foreign_new_for_display( display, + xid ); + if ( transient_parent ) + gdk_window_set_transient_for( + dialog ->get_window() ->gobj(), transient_parent ); +} + Win_GParted::~Win_GParted( ) { delete plug; diff -u gparted-0.2.5/debian/changelog gparted-0.2.5/debian/changelog --- gparted-0.2.5/debian/changelog +++ gparted-0.2.5/debian/changelog @@ -1,3 +1,12 @@ +gparted (0.2.5-1.1ubuntu4) edgy; urgency=low + + * src/Win_GParted.cc: In installer mode, set dialogs transient for the + top-level parent of the socket, not the plug itself (closes: Malone + #54474; see http://bugzilla.gnome.org/show_bug.cgi?id=335524). Thanks to + Evolution for the idea behind Win_GParted::set_transient_for_this et al. + + -- Colin Watson Wed, 30 Aug 2006 20:46:37 +0100 + gparted (0.2.5-1.1ubuntu3) edgy; urgency=low * src/xfs.cc: Fix crash if xfs_db fails (closes: Malone #50909).