can_change_screen property for GtkWindow



[ Continuing the "simple bug turns into thousand line patch" saga... ]

It appears that we need a way to know whether or not it is 
safe for GTK+ to move a widget between screens.

Use cases for this:

 A) For drag-and-drop, GTK+ needs to know whether the icon set using
    gtk_drag_set_icon_window() can be used across multiple screens.

 B) We eventually want the ability for window managers to migrate
    windows across screens, and for users to migrate applications
    between different displays. GTK+ needs a way to know whether it
    should advertise support for such capabilities.

The attached patch adds the GtkWindow API:

 void     gtk_window_set_can_change_screen         (GtkWindow *window,
						   gboolean   can_change_screen);
 void     gtk_window_unset_can_change_screen       (GtkWindow *window);
 gboolean gtk_window_get_can_change_screen         (GtkWindow *window);
 void     gtk_window_set_default_can_change_screen (gboolean   can_change_screen);
 gboolean gtk_window_get_default_can_change_screen (GtkWindow *window);

And properties "can_change_screen" and "can_change_screen_set".

Regards,
                                        Owen

Thought: 

  Though I did the API on GtkWindow, perhaps it should
  be on GtkWidget instead. The primary reason for this is
  GtkMenu, which isn't a toplevel window, but which needs
  to propagate ability-to-change screen to the toplevels
  it creates. 
 
  (A secondary use would be GtkHandlebox - is it OK for 
  GtkHandleBox to allow the torn off contents to be 
  dragged between screens.)

  Another formulation would be a GtkMigratable interface
  that GtkInvisible, GtkWindow, and GtkMenu - all the
  widgets that currently have _set_screen() functions -
  implement. That would be a lot of code churn at this
  point in the process. 

  (And doesn't solve the GtkHandleBox situation, if we
  think that that matters)

  Sort of a mess...

Index: gtk/gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.218
diff -u -p -r1.218 gtkwindow.c
--- gtk/gtkwindow.c	30 Sep 2002 18:58:27 -0000	1.218
+++ gtk/gtkwindow.c	1 Oct 2002 18:50:13 -0000
@@ -73,6 +73,8 @@ enum {
   PROP_TYPE_HINT,
   PROP_SKIP_TASKBAR_HINT,
   PROP_SKIP_PAGER_HINT,
+  PROP_CAN_CHANGE_SCREEN,
+  PROP_CAN_CHANGE_SCREEN_SET,
   
   /* Readonly properties */
   PROP_IS_ACTIVE,
@@ -153,6 +155,8 @@ struct _GtkWindowPrivate
   guint fullscreen_initially : 1;
   guint skips_taskbar : 1;
   guint skips_pager : 1;
+  guint can_change_screen : 1;
+  guint can_change_screen_set : 1;
 };
 
 static void gtk_window_class_init         (GtkWindowClass    *klass);
@@ -263,6 +267,8 @@ static guint        window_signals[LAST_
 static GList       *default_icon_list = NULL;
 static guint        default_icon_serial = 0;
 
+static gboolean     default_can_change_screen = FALSE;
+
 static void gtk_window_set_property (GObject         *object,
 				     guint            prop_id,
 				     const GValue    *value,
@@ -590,6 +596,22 @@ gtk_window_class_init (GtkWindowClass *k
                                                          FALSE,
                                                          G_PARAM_READWRITE));  
 
+  g_object_class_install_property (gobject_class,
+				   PROP_CAN_CHANGE_SCREEN,
+				   g_param_spec_boolean ("can_change_screen",
+                                                         _("Can change screen"),
+                                                         _("TRUE if it is safe to move the window between screens and displays"),
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));  
+
+  g_object_class_install_property (gobject_class,
+				   PROP_CAN_CHANGE_SCREEN_SET,
+				   g_param_spec_boolean ("can_change_screen_set",
+                                                         _("Can change screen set"),
+                                                         _("Whether to use the value from \"can_change_screen\" or the default value"),
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));  
+
   window_signals[SET_FOCUS] =
     g_signal_new ("set_focus",
                   G_TYPE_FROM_CLASS (object_class),
@@ -806,7 +828,15 @@ gtk_window_set_property (GObject      *o
       gtk_window_set_skip_pager_hint (window,
                                       g_value_get_boolean (value));
       break;
-      
+
+    case PROP_CAN_CHANGE_SCREEN:
+      gtk_window_set_can_change_screen (window,
+					g_value_get_boolean (value));
+      break;
+    case PROP_CAN_CHANGE_SCREEN_SET:
+      if (!g_value_get_boolean (value))
+	gtk_window_unset_can_change_screen (window);
+      break;
     default:
       break;
     }
@@ -887,6 +917,20 @@ gtk_window_get_property (GObject      *o
       g_value_set_boolean (value,
                            gtk_window_get_skip_pager_hint (window));
       break;
+    case PROP_CAN_CHANGE_SCREEN:
+      {
+	GtkWindowPrivate *priv = gtk_window_get_private (window);
+	g_value_set_boolean (value,
+			     priv->can_change_screen);
+      }
+      break;
+    case PROP_CAN_CHANGE_SCREEN_SET:
+      {
+	GtkWindowPrivate *priv = gtk_window_get_private (window);
+	g_value_set_boolean (value,
+			     priv->can_change_screen_set);
+      }
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -5614,8 +5658,8 @@ gtk_window_unfullscreen (GtkWindow *wind
   g_return_if_fail (GTK_IS_WINDOW (window));
 
   widget = GTK_WIDGET (window);
-  priv = gtk_window_get_private (window);
-  
+  priv = gtk_window_get_private (window); 
+ 
   priv->fullscreen_initially = FALSE;
 
   if (window->frame)
@@ -6583,4 +6627,137 @@ _gtk_window_set_has_toplevel_focus (GtkW
 
       g_object_notify (G_OBJECT (window), "has_toplevel_focus");
     }
+}
+
+/**
+ * gtk_window_set_can_change_screen:
+ * @window: a #GtkWindow
+ * @can_change_screen: %TRUE if changing the screen
+ *                     of the window is safe.
+ *
+ * Sets a flag as to whether it is safe to move this window
+ * between displays and screens with gtk_window_set_screen().
+ * In general, a window created using only non-deprecated
+ * features of GTK+ will be safe to move between screens without any
+ * additional intervention by the application programmer.
+ *
+ * If there are screen-specific resources associated with the
+ * window such as GdkPixmap or GdkGC objects, then special
+ * handling is required to make it safe to move the window
+ * between screens. You need create these resources in response
+ * to the ::realize signal on the window and destroy them in
+ * response to the ::unrealize signal rather than keeping them
+ * around permanently.
+ **/
+void
+gtk_window_set_can_change_screen (GtkWindow *window,
+				  gboolean   can_change_screen)
+{
+  GtkWindowPrivate *priv;
+  GObject *object;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  priv = gtk_window_get_private (window);
+  object = G_OBJECT (window);
+
+  can_change_screen = can_change_screen != FALSE;
+
+  priv->can_change_screen_set = TRUE;
+  priv->can_change_screen = can_change_screen;
+  
+  g_object_freeze_notify (object);
+  g_object_notify (object, "can_change_screen");
+  g_object_notify (object, "can_change_screen_set");
+  g_object_thaw_notify (object);
+}
+
+/**
+ * gtk_window_unset_can_change_screen:
+ * @window: a #GtkWindow
+ * 
+ * Unset a value previously set with
+ * gtk_window_set_can_change_screen() so that the
+ * window uses the default value from
+ * gtk_window_set_default_can_change_screen again.
+ **/
+void
+gtk_window_unset_can_change_screen (GtkWindow *window)
+{
+  GtkWindowPrivate *priv;
+  GObject *object;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  priv = gtk_window_get_private (window);
+  object = G_OBJECT (window);
+  
+  priv->can_change_screen_set = FALSE;
+
+  g_object_freeze_notify (object);
+  g_object_notify (object, "can_change_screen");
+  g_object_notify (object, "can_change_screen_set");
+  g_object_thaw_notify (object);
+}
+
+/**
+ * gtk_window_get_can_change_screen:
+ * @window: a #GtKWindow
+ * 
+ * Determines whether it is safe to move a window between
+ * different screens and displays.
+ * 
+ * Return value: %TRUE if it is safe to move the window
+ *  between screens and displays.
+ **/
+gboolean
+gtk_window_get_can_change_screen (GtkWindow *window)
+{
+  GtkWindowPrivate *priv;
+  
+  g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+  priv = gtk_window_get_private (window);
+
+  if (priv->can_change_screen_set)
+    return priv->can_change_screen;
+  else
+    return default_can_change_screen;
+}
+
+/**
+ * gtk_window_set_default_can_change_screen:
+ * @can_change_screen: %TRUE if changing the screen
+ *                     of windows in this application is safe.
+ * 
+ * Sets the default value for gtk_window_get_can_change_screen().
+ * All windows that GTK+ creates itself will be safe to move
+ * between screens, so if you know that this is also true of
+ * your application and any other libraries your application
+ * might use, you can turn this flag on to avoid having
+ * to call gtk_window_set_can_change_screen() on each window
+ * individually.
+ **/
+void
+gtk_window_set_default_can_change_screen (gboolean can_change_screen)
+{
+  can_change_screen = can_change_screen != FALSE;
+  
+  default_can_change_screen = can_change_screen;
+}
+
+
+/**
+ * gtk_window_set_default_can_change_screen:
+ * @window: a #GtkWindow
+ * 
+ * Gets the value set by gtk_window_set_default_can_change_screen()
+ * 
+ * Return value: %TRUE if changing the screen
+ *               of windows in this application is safe.
+ **/
+gboolean
+gtk_window_get_default_can_change_screen (GtkWindow *window)
+{
+  return default_can_change_screen;
 }
Index: gtk/gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.65
diff -u -p -r1.65 gtkwindow.h
--- gtk/gtkwindow.h	30 Sep 2002 18:58:27 -0000	1.65
+++ gtk/gtkwindow.h	1 Oct 2002 18:50:13 -0000
@@ -255,6 +255,12 @@ GList*     gtk_window_get_default_icon_l
 gboolean   gtk_window_set_default_icon_from_file   (const gchar *filename,
 						    GError     **err);
 
+void     gtk_window_set_can_change_screen         (GtkWindow *window,
+						   gboolean   can_change_screen);
+void     gtk_window_unset_can_change_screen       (GtkWindow *window);
+gboolean gtk_window_get_can_change_screen         (GtkWindow *window);
+void     gtk_window_set_default_can_change_screen (gboolean   can_change_screen);
+gboolean gtk_window_get_default_can_change_screen (GtkWindow *window);
 
 /* If window is set modal, input will be grabbed when show and released when hide */
 void       gtk_window_set_modal      (GtkWindow *window,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]