]> Pileus Git - ~andy/gtk/blob - gtk/gtkinvisible.c
Fix the build
[~andy/gtk] / gtk / gtkinvisible.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 /*
19  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20  * file for a list of people on the GTK+ Team.  See the ChangeLog
21  * files for a list of changes.  These files are distributed with
22  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
23  */
24
25 #include "config.h"
26 #include <gdk/gdk.h>
27 #include "gtkinvisible.h"
28 #include "gtkwidgetprivate.h"
29 #include "gtkprivate.h"
30 #include "gtkintl.h"
31
32
33 /**
34  * SECTION:gtkinvisible
35  * @Short_description: A widget which is not displayed
36  * @Title: GtkInvisible
37  *
38  * The #GtkInvisible widget is used internally in GTK+, and is probably not
39  * very useful for application developers.
40  *
41  * It is used for reliable pointer grabs and selection handling in the code
42  * for drag-and-drop.
43  */
44
45
46 struct _GtkInvisiblePrivate
47 {
48   GdkScreen    *screen;
49   gboolean      has_user_ref_count;
50 };
51
52 enum {
53   PROP_0,
54   PROP_SCREEN,
55   LAST_ARG
56 };
57
58 static void gtk_invisible_destroy       (GtkWidget         *widget);
59 static void gtk_invisible_realize       (GtkWidget         *widget);
60 static void gtk_invisible_style_updated (GtkWidget         *widget);
61 static void gtk_invisible_show          (GtkWidget         *widget);
62 static void gtk_invisible_size_allocate (GtkWidget         *widget,
63                                          GtkAllocation     *allocation);
64 static void gtk_invisible_set_property  (GObject           *object,
65                                          guint              prop_id,
66                                          const GValue      *value,
67                                          GParamSpec        *pspec);
68 static void gtk_invisible_get_property  (GObject           *object,
69                                          guint              prop_id,
70                                          GValue            *value,
71                                          GParamSpec        *pspec);
72
73 static GObject *gtk_invisible_constructor (GType                  type,
74                                            guint                  n_construct_properties,
75                                            GObjectConstructParam *construct_params);
76
77 G_DEFINE_TYPE (GtkInvisible, gtk_invisible, GTK_TYPE_WIDGET)
78
79 static void
80 gtk_invisible_class_init (GtkInvisibleClass *class)
81 {
82   GObjectClass   *gobject_class;
83   GtkWidgetClass *widget_class;
84
85   widget_class = (GtkWidgetClass*) class;
86   gobject_class = (GObjectClass*) class;
87
88   widget_class->realize = gtk_invisible_realize;
89   widget_class->style_updated = gtk_invisible_style_updated;
90   widget_class->show = gtk_invisible_show;
91   widget_class->size_allocate = gtk_invisible_size_allocate;
92   widget_class->destroy = gtk_invisible_destroy;
93
94   gobject_class->set_property = gtk_invisible_set_property;
95   gobject_class->get_property = gtk_invisible_get_property;
96   gobject_class->constructor = gtk_invisible_constructor;
97
98   g_object_class_install_property (gobject_class,
99                                    PROP_SCREEN,
100                                    g_param_spec_object ("screen",
101                                                         P_("Screen"),
102                                                         P_("The screen where this window will be displayed"),
103                                                         GDK_TYPE_SCREEN,
104                                                         GTK_PARAM_READWRITE));
105
106   g_type_class_add_private (class, sizeof (GtkInvisiblePrivate));
107 }
108
109 static void
110 gtk_invisible_init (GtkInvisible *invisible)
111 {
112   GtkInvisiblePrivate *priv;
113
114   invisible->priv = G_TYPE_INSTANCE_GET_PRIVATE (invisible,
115                                                  GTK_TYPE_INVISIBLE,
116                                                  GtkInvisiblePrivate);
117   priv = invisible->priv;
118
119   gtk_widget_set_has_window (GTK_WIDGET (invisible), TRUE);
120   _gtk_widget_set_is_toplevel (GTK_WIDGET (invisible), TRUE);
121
122   g_object_ref_sink (invisible);
123
124   priv->has_user_ref_count = TRUE;
125   priv->screen = gdk_screen_get_default ();
126 }
127
128 static void
129 gtk_invisible_destroy (GtkWidget *widget)
130 {
131   GtkInvisible *invisible = GTK_INVISIBLE (widget);
132   GtkInvisiblePrivate *priv = invisible->priv;
133
134   if (priv->has_user_ref_count)
135     {
136       priv->has_user_ref_count = FALSE;
137       g_object_unref (invisible);
138     }
139
140   GTK_WIDGET_CLASS (gtk_invisible_parent_class)->destroy (widget);
141 }
142
143 /**
144  * gtk_invisible_new_for_screen:
145  * @screen: a #GdkScreen which identifies on which
146  *          the new #GtkInvisible will be created.
147  *
148  * Creates a new #GtkInvisible object for a specified screen
149  *
150  * Return value: a newly created #GtkInvisible object
151  *
152  * Since: 2.2
153  **/
154 GtkWidget* 
155 gtk_invisible_new_for_screen (GdkScreen *screen)
156 {
157   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
158   
159   return g_object_new (GTK_TYPE_INVISIBLE, "screen", screen, NULL);
160 }
161
162 /**
163  * gtk_invisible_new:
164  * 
165  * Creates a new #GtkInvisible.
166  * 
167  * Return value: a new #GtkInvisible.
168  **/
169 GtkWidget*
170 gtk_invisible_new (void)
171 {
172   return g_object_new (GTK_TYPE_INVISIBLE, NULL);
173 }
174
175 /**
176  * gtk_invisible_set_screen:
177  * @invisible: a #GtkInvisible.
178  * @screen: a #GdkScreen.
179  *
180  * Sets the #GdkScreen where the #GtkInvisible object will be displayed.
181  *
182  * Since: 2.2
183  **/ 
184 void
185 gtk_invisible_set_screen (GtkInvisible *invisible,
186                           GdkScreen    *screen)
187 {
188   GtkInvisiblePrivate *priv;
189   GtkWidget *widget;
190   GdkScreen *previous_screen;
191   gboolean was_realized;
192
193   g_return_if_fail (GTK_IS_INVISIBLE (invisible));
194   g_return_if_fail (GDK_IS_SCREEN (screen));
195
196   priv = invisible->priv;
197
198   if (screen == priv->screen)
199     return;
200
201   widget = GTK_WIDGET (invisible);
202
203   previous_screen = priv->screen;
204   was_realized = gtk_widget_get_realized (widget);
205
206   if (was_realized)
207     gtk_widget_unrealize (widget);
208
209   priv->screen = screen;
210   if (screen != previous_screen)
211     _gtk_widget_propagate_screen_changed (widget, previous_screen);
212   g_object_notify (G_OBJECT (invisible), "screen");
213   
214   if (was_realized)
215     gtk_widget_realize (widget);
216 }
217
218 /**
219  * gtk_invisible_get_screen:
220  * @invisible: a #GtkInvisible.
221  *
222  * Returns the #GdkScreen object associated with @invisible
223  *
224  * Return value: (transfer none): the associated #GdkScreen.
225  *
226  * Since: 2.2
227  **/
228 GdkScreen *
229 gtk_invisible_get_screen (GtkInvisible *invisible)
230 {
231   g_return_val_if_fail (GTK_IS_INVISIBLE (invisible), NULL);
232
233   return invisible->priv->screen;
234 }
235
236 static void
237 gtk_invisible_realize (GtkWidget *widget)
238 {
239   GdkWindow *parent;
240   GdkWindow *window;
241   GdkWindowAttr attributes;
242   gint attributes_mask;
243
244   gtk_widget_set_realized (widget, TRUE);
245
246   parent = gtk_widget_get_parent_window (widget);
247   if (parent == NULL)
248     parent = gtk_widget_get_root_window (widget);
249
250   attributes.x = -100;
251   attributes.y = -100;
252   attributes.width = 10;
253   attributes.height = 10;
254   attributes.window_type = GDK_WINDOW_TEMP;
255   attributes.wclass = GDK_INPUT_ONLY;
256   attributes.override_redirect = TRUE;
257   attributes.event_mask = gtk_widget_get_events (widget);
258
259   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
260
261   window = gdk_window_new (parent, &attributes, attributes_mask);
262   gtk_widget_set_window (widget, window);
263   gtk_widget_register_window (widget, window);
264 }
265
266 static void
267 gtk_invisible_style_updated (GtkWidget *widget)
268 {
269   /* Don't chain up to parent implementation */
270 }
271
272 static void
273 gtk_invisible_show (GtkWidget *widget)
274 {
275   _gtk_widget_set_visible_flag (widget, TRUE);
276   gtk_widget_map (widget);
277 }
278
279 static void
280 gtk_invisible_size_allocate (GtkWidget     *widget,
281                              GtkAllocation *allocation)
282 {
283   gtk_widget_set_allocation (widget, allocation);
284 }
285
286
287 static void 
288 gtk_invisible_set_property  (GObject      *object,
289                              guint         prop_id,
290                              const GValue *value,
291                              GParamSpec   *pspec)
292 {
293   GtkInvisible *invisible = GTK_INVISIBLE (object);
294   
295   switch (prop_id)
296     {
297     case PROP_SCREEN:
298       gtk_invisible_set_screen (invisible, g_value_get_object (value));
299       break;
300     default:
301       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
302       break;
303     }
304 }
305
306 static void 
307 gtk_invisible_get_property  (GObject      *object,
308                              guint         prop_id,
309                              GValue       *value,
310                              GParamSpec   *pspec)
311 {
312   GtkInvisible *invisible = GTK_INVISIBLE (object);
313   GtkInvisiblePrivate *priv = invisible->priv;
314
315   switch (prop_id)
316     {
317     case PROP_SCREEN:
318       g_value_set_object (value, priv->screen);
319       break;
320     default:
321       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
322       break;
323     }
324 }
325
326 /* We use a constructor here so that we can realize the invisible on
327  * the correct screen after the "screen" property has been set
328  */
329 static GObject*
330 gtk_invisible_constructor (GType                  type,
331                            guint                  n_construct_properties,
332                            GObjectConstructParam *construct_params)
333 {
334   GObject *object;
335
336   object = G_OBJECT_CLASS (gtk_invisible_parent_class)->constructor (type,
337                                                                      n_construct_properties,
338                                                                      construct_params);
339
340   gtk_widget_realize (GTK_WIDGET (object));
341
342   return object;
343 }