]>
Commit | Line | Data |
---|---|---|
c67daf87 | 1 | /* /////////////////////////////////////////////////////////////////////////// |
0ba6a836 | 2 | // Name: src/gtk/win_gtk.c |
77ffb593 | 3 | // Purpose: Native GTK+ widget for wxWidgets, based on GtkLayout and |
ed673c6a RR |
4 | // GtkFixed. It makes use of the gravity window property and |
5 | // therefore does not work with GTK 1.0. | |
c801d85f | 6 | // Author: Robert Roebling |
c67d8618 | 7 | // Id: $Id$ |
01111366 | 8 | // Copyright: (c) 1998 Robert Roebling |
77ffb593 | 9 | // Licence: wxWidgets licence |
c67daf87 | 10 | /////////////////////////////////////////////////////////////////////////// */ |
c801d85f | 11 | |
d02af7bb JJ |
12 | #ifdef VMS |
13 | #define XCheckIfEvent XCHECKIFEVENT | |
3fa056ab | 14 | #endif |
27df579a | 15 | |
79918119 | 16 | #include "wx/platform.h" |
27df579a | 17 | #include "wx/gtk/win_gtk.h" |
034be888 | 18 | #include "gtk/gtksignal.h" |
ed673c6a RR |
19 | #include "gtk/gtkprivate.h" |
20 | #include "gdk/gdkx.h" | |
38c7b3d3 | 21 | |
c801d85f KB |
22 | #ifdef __cplusplus |
23 | extern "C" { | |
24 | #endif /* __cplusplus */ | |
25 | ||
da048e3d | 26 | typedef struct _GtkPizzaAdjData GtkPizzaAdjData; |
ed673c6a | 27 | |
bf3dab48 | 28 | struct _GtkPizzaAdjData |
ed673c6a RR |
29 | { |
30 | gint dx; | |
31 | gint dy; | |
32 | }; | |
33 | ||
b6fa52db RR |
34 | static void gtk_pizza_class_init (GtkPizzaClass *klass); |
35 | static void gtk_pizza_init (GtkPizza *pizza); | |
ed673c6a | 36 | |
b6fa52db RR |
37 | static void gtk_pizza_realize (GtkWidget *widget); |
38 | static void gtk_pizza_unrealize (GtkWidget *widget); | |
ed673c6a | 39 | |
b6fa52db | 40 | static void gtk_pizza_map (GtkWidget *widget); |
ed673c6a | 41 | |
da048e3d | 42 | static void gtk_pizza_size_request (GtkWidget *widget, |
bf3dab48 | 43 | GtkRequisition *requisition); |
da048e3d | 44 | static void gtk_pizza_size_allocate (GtkWidget *widget, |
bf3dab48 | 45 | GtkAllocation *allocation); |
da048e3d | 46 | static gint gtk_pizza_expose (GtkWidget *widget, |
bf3dab48 | 47 | GdkEventExpose *event); |
22aff579 VS |
48 | static void gtk_pizza_style_set (GtkWidget *widget, |
49 | GtkStyle *previous_style); | |
da048e3d | 50 | static void gtk_pizza_add (GtkContainer *container, |
bf3dab48 | 51 | GtkWidget *widget); |
da048e3d | 52 | static void gtk_pizza_remove (GtkContainer *container, |
bf3dab48 | 53 | GtkWidget *widget); |
b6fa52db RR |
54 | static void gtk_pizza_forall (GtkContainer *container, |
55 | gboolean include_internals, | |
56 | GtkCallback callback, | |
57 | gpointer callback_data); | |
17a1ebd1 | 58 | |
67d78217 RR |
59 | static void gtk_pizza_allocate_child (GtkPizza *pizza, |
60 | GtkPizzaChild *child); | |
3fc6e5fa RR |
61 | static void gtk_pizza_adjust_allocations_recurse (GtkWidget *widget, |
62 | gpointer cb_data); | |
ed673c6a | 63 | |
da048e3d | 64 | static GtkType gtk_pizza_child_type (GtkContainer *container); |
c801d85f | 65 | |
b6fa52db | 66 | static void gtk_pizza_scroll_set_adjustments (GtkPizza *pizza, |
bf3dab48 VZ |
67 | GtkAdjustment *hadj, |
68 | GtkAdjustment *vadj); | |
c801d85f | 69 | |
68567a96 MR |
70 | /* static */ |
71 | GtkContainerClass *pizza_parent_class = NULL; | |
034be888 | 72 | |
e1ff9329 | 73 | GtkType |
da048e3d | 74 | gtk_pizza_get_type () |
c801d85f | 75 | { |
e1ff9329 | 76 | static GtkType pizza_type = 0; |
c801d85f | 77 | |
da048e3d | 78 | if (!pizza_type) |
c801d85f | 79 | { |
67d78217 RR |
80 | static const GTypeInfo pizza_info = |
81 | { | |
82 | sizeof (GtkPizzaClass), | |
83 | NULL, /* base_init */ | |
84 | NULL, /* base_finalize */ | |
85 | (GClassInitFunc) gtk_pizza_class_init, | |
86 | NULL, /* class_finalize */ | |
87 | NULL, /* class_data */ | |
88 | sizeof (GtkPizza), | |
89 | 16, /* n_preallocs */ | |
90 | (GInstanceInitFunc) gtk_pizza_init, | |
91 | }; | |
17a1ebd1 | 92 | pizza_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkPizza", &pizza_info, (GTypeFlags)0); |
c801d85f | 93 | } |
bf3dab48 | 94 | |
da048e3d | 95 | return pizza_type; |
c801d85f KB |
96 | } |
97 | ||
02a525b3 VZ |
98 | /* Marshaller needed for set_scroll_adjustments signal, |
99 | generated with GLib-2.4.6 glib-genmarshal */ | |
143318dd RR |
100 | #define g_marshal_value_peek_object(v) g_value_get_object (v) |
101 | static void | |
102 | g_cclosure_user_marshal_VOID__OBJECT_OBJECT (GClosure *closure, | |
103 | GValue *return_value, | |
104 | guint n_param_values, | |
105 | const GValue *param_values, | |
106 | gpointer invocation_hint, | |
107 | gpointer marshal_data) | |
108 | { | |
109 | typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1, | |
110 | gpointer arg_1, | |
111 | gpointer arg_2, | |
112 | gpointer data2); | |
113 | register GMarshalFunc_VOID__OBJECT_OBJECT callback; | |
114 | register GCClosure *cc = (GCClosure*) closure; | |
115 | register gpointer data1, data2; | |
116 | ||
117 | g_return_if_fail (n_param_values == 3); | |
118 | ||
119 | if (G_CCLOSURE_SWAP_DATA (closure)) | |
120 | { | |
121 | data1 = closure->data; | |
122 | data2 = g_value_peek_pointer (param_values + 0); | |
123 | } | |
124 | else | |
125 | { | |
126 | data1 = g_value_peek_pointer (param_values + 0); | |
127 | data2 = closure->data; | |
128 | } | |
129 | callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); | |
130 | ||
131 | callback (data1, | |
132 | g_marshal_value_peek_object (param_values + 1), | |
133 | g_marshal_value_peek_object (param_values + 2), | |
134 | data2); | |
135 | } | |
143318dd | 136 | |
c801d85f | 137 | static void |
da048e3d | 138 | gtk_pizza_class_init (GtkPizzaClass *klass) |
c801d85f | 139 | { |
053f9cc1 RR |
140 | GtkObjectClass *object_class; |
141 | GtkWidgetClass *widget_class; | |
142 | GtkContainerClass *container_class; | |
c801d85f | 143 | |
053f9cc1 RR |
144 | object_class = (GtkObjectClass*) klass; |
145 | widget_class = (GtkWidgetClass*) klass; | |
146 | container_class = (GtkContainerClass*) klass; | |
67d78217 | 147 | pizza_parent_class = gtk_type_class (GTK_TYPE_CONTAINER); |
c801d85f | 148 | |
da048e3d RR |
149 | widget_class->map = gtk_pizza_map; |
150 | widget_class->realize = gtk_pizza_realize; | |
151 | widget_class->unrealize = gtk_pizza_unrealize; | |
152 | widget_class->size_request = gtk_pizza_size_request; | |
153 | widget_class->size_allocate = gtk_pizza_size_allocate; | |
da048e3d | 154 | widget_class->expose_event = gtk_pizza_expose; |
22aff579 | 155 | widget_class->style_set = gtk_pizza_style_set; |
053f9cc1 | 156 | |
da048e3d RR |
157 | container_class->add = gtk_pizza_add; |
158 | container_class->remove = gtk_pizza_remove; | |
159 | container_class->forall = gtk_pizza_forall; | |
38c7b3d3 | 160 | |
da048e3d | 161 | container_class->child_type = gtk_pizza_child_type; |
034be888 | 162 | |
da048e3d | 163 | klass->set_scroll_adjustments = gtk_pizza_scroll_set_adjustments; |
034be888 | 164 | |
053f9cc1 | 165 | widget_class->set_scroll_adjustments_signal = |
143318dd RR |
166 | g_signal_new( |
167 | "set_scroll_adjustments", | |
168 | G_TYPE_FROM_CLASS(object_class), | |
169 | G_SIGNAL_RUN_LAST, | |
170 | G_STRUCT_OFFSET(GtkPizzaClass, set_scroll_adjustments), | |
171 | NULL, | |
172 | NULL, | |
173 | g_cclosure_user_marshal_VOID__OBJECT_OBJECT, | |
174 | G_TYPE_NONE, | |
175 | 2, | |
176 | GTK_TYPE_ADJUSTMENT, | |
177 | GTK_TYPE_ADJUSTMENT); | |
38c7b3d3 RR |
178 | } |
179 | ||
38c7b3d3 | 180 | static GtkType |
da048e3d | 181 | gtk_pizza_child_type (GtkContainer *container) |
38c7b3d3 | 182 | { |
053f9cc1 | 183 | return GTK_TYPE_WIDGET; |
c801d85f KB |
184 | } |
185 | ||
186 | static void | |
da048e3d | 187 | gtk_pizza_init (GtkPizza *pizza) |
c801d85f | 188 | { |
da048e3d | 189 | GTK_WIDGET_UNSET_FLAGS (pizza, GTK_NO_WINDOW); |
bf3dab48 | 190 | |
da048e3d | 191 | pizza->shadow_type = GTK_MYSHADOW_NONE; |
034be888 | 192 | |
da048e3d | 193 | pizza->children = NULL; |
bf3dab48 | 194 | |
da048e3d RR |
195 | pizza->width = 20; |
196 | pizza->height = 20; | |
ed673c6a | 197 | |
da048e3d | 198 | pizza->bin_window = NULL; |
3dd9b88a | 199 | |
8e217128 RR |
200 | pizza->xoffset = 0; |
201 | pizza->yoffset = 0; | |
ed673c6a | 202 | |
da048e3d RR |
203 | pizza->configure_serial = 0; |
204 | pizza->scroll_x = 0; | |
205 | pizza->scroll_y = 0; | |
206 | pizza->visibility = GDK_VISIBILITY_PARTIAL; | |
bf3dab48 | 207 | |
da048e3d | 208 | pizza->clear_on_draw = TRUE; |
b6fa52db | 209 | pizza->use_filter = TRUE; |
b420fb6a | 210 | pizza->external_expose = FALSE; |
c801d85f KB |
211 | } |
212 | ||
213 | GtkWidget* | |
da048e3d | 214 | gtk_pizza_new () |
c801d85f | 215 | { |
da048e3d | 216 | GtkPizza *pizza; |
c801d85f | 217 | |
da048e3d | 218 | pizza = gtk_type_new (gtk_pizza_get_type ()); |
bf3dab48 | 219 | |
da048e3d | 220 | return GTK_WIDGET (pizza); |
c801d85f KB |
221 | } |
222 | ||
bf3dab48 | 223 | static void |
da048e3d | 224 | gtk_pizza_scroll_set_adjustments (GtkPizza *pizza, |
bf3dab48 VZ |
225 | GtkAdjustment *hadj, |
226 | GtkAdjustment *vadj) | |
034be888 | 227 | { |
ed673c6a | 228 | /* We handle scrolling in the wxScrolledWindow, not here. */ |
034be888 RR |
229 | } |
230 | ||
bf3dab48 | 231 | void |
b6fa52db | 232 | gtk_pizza_set_shadow_type (GtkPizza *pizza, |
0e09f76e | 233 | GtkMyShadowType type) |
034be888 | 234 | { |
da048e3d RR |
235 | g_return_if_fail (pizza != NULL); |
236 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
034be888 | 237 | |
da048e3d | 238 | if ((GtkMyShadowType) pizza->shadow_type != type) |
034be888 | 239 | { |
da048e3d | 240 | pizza->shadow_type = type; |
034be888 | 241 | |
da048e3d | 242 | if (GTK_WIDGET_VISIBLE (pizza)) |
bf3dab48 VZ |
243 | { |
244 | gtk_widget_size_allocate (GTK_WIDGET (pizza), &(GTK_WIDGET (pizza)->allocation)); | |
245 | gtk_widget_queue_draw (GTK_WIDGET (pizza)); | |
246 | } | |
034be888 RR |
247 | } |
248 | } | |
034be888 | 249 | |
bf3dab48 | 250 | void |
b6fa52db RR |
251 | gtk_pizza_set_clear (GtkPizza *pizza, |
252 | gboolean clear) | |
147bc491 | 253 | { |
da048e3d RR |
254 | g_return_if_fail (pizza != NULL); |
255 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
bf3dab48 | 256 | |
da048e3d | 257 | pizza->clear_on_draw = clear; |
bf3dab48 VZ |
258 | } |
259 | ||
3dd9b88a | 260 | void |
b6fa52db RR |
261 | gtk_pizza_set_filter (GtkPizza *pizza, |
262 | gboolean use) | |
0e09f76e RR |
263 | { |
264 | g_return_if_fail (pizza != NULL); | |
265 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
266 | ||
267 | pizza->use_filter = use; | |
3dd9b88a VZ |
268 | } |
269 | ||
270 | void | |
b420fb6a RR |
271 | gtk_pizza_set_external (GtkPizza *pizza, |
272 | gboolean expose) | |
273 | { | |
274 | g_return_if_fail (pizza != NULL); | |
275 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
276 | ||
277 | pizza->external_expose = expose; | |
278 | } | |
279 | ||
c801d85f | 280 | void |
b6fa52db RR |
281 | gtk_pizza_put (GtkPizza *pizza, |
282 | GtkWidget *widget, | |
283 | gint x, | |
284 | gint y, | |
285 | gint width, | |
286 | gint height) | |
c801d85f | 287 | { |
da048e3d | 288 | GtkPizzaChild *child_info; |
053f9cc1 | 289 | |
da048e3d RR |
290 | g_return_if_fail (pizza != NULL); |
291 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
053f9cc1 RR |
292 | g_return_if_fail (widget != NULL); |
293 | ||
da048e3d | 294 | child_info = g_new (GtkPizzaChild, 1); |
bf3dab48 | 295 | |
053f9cc1 RR |
296 | child_info->widget = widget; |
297 | child_info->x = x; | |
298 | child_info->y = y; | |
299 | child_info->width = width; | |
300 | child_info->height = height; | |
bf3dab48 VZ |
301 | |
302 | pizza->children = g_list_append (pizza->children, child_info); | |
ed673c6a | 303 | |
da048e3d RR |
304 | if (GTK_WIDGET_REALIZED (pizza)) |
305 | gtk_widget_set_parent_window (widget, pizza->bin_window); | |
bf3dab48 | 306 | |
2b5f62a0 VZ |
307 | gtk_widget_set_parent (widget, GTK_WIDGET (pizza)); |
308 | ||
370dc79c | 309 | gtk_widget_set_size_request (widget, width, height); |
c801d85f KB |
310 | } |
311 | ||
312 | void | |
b6fa52db RR |
313 | gtk_pizza_move (GtkPizza *pizza, |
314 | GtkWidget *widget, | |
315 | gint x, | |
316 | gint y) | |
c801d85f | 317 | { |
da048e3d | 318 | GtkPizzaChild *child; |
053f9cc1 | 319 | GList *children; |
c801d85f | 320 | |
da048e3d RR |
321 | g_return_if_fail (pizza != NULL); |
322 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
053f9cc1 | 323 | g_return_if_fail (widget != NULL); |
c801d85f | 324 | |
da048e3d | 325 | children = pizza->children; |
053f9cc1 | 326 | while (children) |
fdd3ed7a | 327 | { |
053f9cc1 RR |
328 | child = children->data; |
329 | children = children->next; | |
bf3dab48 | 330 | |
053f9cc1 | 331 | if (child->widget == widget) |
fdd3ed7a | 332 | { |
bf3dab48 VZ |
333 | if ((child->x == x) && (child->y == y)) |
334 | break; | |
335 | ||
ed673c6a RR |
336 | child->x = x; |
337 | child->y = y; | |
17a1ebd1 | 338 | |
bf3dab48 VZ |
339 | if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza)) |
340 | gtk_widget_queue_resize (widget); | |
341 | break; | |
342 | } | |
fdd3ed7a RR |
343 | } |
344 | } | |
345 | ||
346 | void | |
b6fa52db RR |
347 | gtk_pizza_resize (GtkPizza *pizza, |
348 | GtkWidget *widget, | |
349 | gint width, | |
350 | gint height) | |
fdd3ed7a | 351 | { |
da048e3d | 352 | GtkPizzaChild *child; |
053f9cc1 | 353 | GList *children; |
fdd3ed7a | 354 | |
da048e3d RR |
355 | g_return_if_fail (pizza != NULL); |
356 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
053f9cc1 | 357 | g_return_if_fail (widget != NULL); |
fdd3ed7a | 358 | |
da048e3d | 359 | children = pizza->children; |
053f9cc1 | 360 | while (children) |
fdd3ed7a | 361 | { |
053f9cc1 RR |
362 | child = children->data; |
363 | children = children->next; | |
bf3dab48 | 364 | |
053f9cc1 | 365 | if (child->widget == widget) |
fdd3ed7a | 366 | { |
bf3dab48 VZ |
367 | if ((child->width == width) && (child->height == height)) |
368 | break; | |
369 | ||
ed673c6a RR |
370 | child->width = width; |
371 | child->height = height; | |
bf3dab48 | 372 | |
370dc79c | 373 | gtk_widget_set_size_request (widget, width, height); |
bf3dab48 | 374 | |
da048e3d | 375 | if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza)) |
bf3dab48 VZ |
376 | gtk_widget_queue_resize (widget); |
377 | break; | |
378 | } | |
fdd3ed7a RR |
379 | } |
380 | } | |
381 | ||
382 | void | |
b6fa52db RR |
383 | gtk_pizza_set_size (GtkPizza *pizza, |
384 | GtkWidget *widget, | |
385 | gint x, | |
386 | gint y, | |
387 | gint width, | |
388 | gint height) | |
fdd3ed7a | 389 | { |
da048e3d | 390 | GtkPizzaChild *child; |
053f9cc1 | 391 | GList *children; |
fdd3ed7a | 392 | |
da048e3d RR |
393 | g_return_if_fail (pizza != NULL); |
394 | g_return_if_fail (GTK_IS_PIZZA (pizza)); | |
053f9cc1 | 395 | g_return_if_fail (widget != NULL); |
fdd3ed7a | 396 | |
aaf53059 | 397 | #ifndef WX_WARN_ILLEGAL_SETSIZE |
6b71411a | 398 | /* this really shouldn't happen -- but it does, a lot, right now and we |
aaf53059 MR |
399 | can't pass negative values to gtk_widget_set_size_request() without getting |
400 | a warning printed out, so filter them out here */ | |
6b71411a VZ |
401 | if ( width < 0 ) |
402 | width = 0; | |
403 | if ( height < 0 ) | |
404 | height = 0; | |
aaf53059 | 405 | #endif |
6b71411a | 406 | |
da048e3d | 407 | children = pizza->children; |
053f9cc1 | 408 | while (children) |
c801d85f | 409 | { |
053f9cc1 RR |
410 | child = children->data; |
411 | children = children->next; | |
c801d85f | 412 | |
053f9cc1 | 413 | if (child->widget == widget) |
c801d85f | 414 | { |
bf3dab48 VZ |
415 | if ((child->x == x) && |
416 | (child->y == y) && | |
417 | (child->width == width) && | |
418 | (child->height == height)) return; | |
419 | ||
053f9cc1 RR |
420 | child->x = x; |
421 | child->y = y; | |
422 | child->width = width; | |
423 | child->height = height; | |
bf3dab48 | 424 | |
370dc79c | 425 | gtk_widget_set_size_request (widget, width, height); |
bf3dab48 | 426 | |
da048e3d | 427 | if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza)) |
bf3dab48 VZ |
428 | gtk_widget_queue_resize (widget); |
429 | ||
6d693bb4 | 430 | return; |
c801d85f KB |
431 | } |
432 | } | |
433 | } | |
434 | ||
3dd9b88a | 435 | gint |
8cb9f0d0 RR |
436 | gtk_pizza_child_resized (GtkPizza *pizza, |
437 | GtkWidget *widget) | |
438 | { | |
439 | GtkPizzaChild *child; | |
440 | GList *children; | |
441 | ||
442 | g_return_val_if_fail (pizza != NULL, FALSE); | |
443 | g_return_val_if_fail (GTK_IS_PIZZA (pizza), FALSE); | |
444 | g_return_val_if_fail (widget != NULL, FALSE); | |
445 | ||
446 | children = pizza->children; | |
447 | while (children) | |
448 | { | |
449 | child = children->data; | |
450 | children = children->next; | |
451 | ||
452 | if (child->widget == widget) | |
453 | { | |
454 | return ((child->width == widget->allocation.width) && | |
455 | (child->height == widget->allocation.height)); | |
456 | } | |
457 | } | |
3dd9b88a | 458 | |
8cb9f0d0 RR |
459 | return FALSE; |
460 | } | |
3dd9b88a | 461 | |
c801d85f | 462 | static void |
da048e3d | 463 | gtk_pizza_map (GtkWidget *widget) |
c801d85f | 464 | { |
da048e3d RR |
465 | GtkPizza *pizza; |
466 | GtkPizzaChild *child; | |
053f9cc1 | 467 | GList *children; |
c801d85f | 468 | |
053f9cc1 | 469 | g_return_if_fail (widget != NULL); |
da048e3d | 470 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
c801d85f | 471 | |
053f9cc1 | 472 | GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); |
da048e3d | 473 | pizza = GTK_PIZZA (widget); |
c801d85f | 474 | |
da048e3d | 475 | children = pizza->children; |
053f9cc1 | 476 | while (children) |
c801d85f | 477 | { |
053f9cc1 RR |
478 | child = children->data; |
479 | children = children->next; | |
c801d85f | 480 | |
bf3dab48 VZ |
481 | if ( GTK_WIDGET_VISIBLE (child->widget) && |
482 | !GTK_WIDGET_MAPPED (child->widget) && | |
a2d8ce85 | 483 | TRUE) |
bf3dab48 VZ |
484 | { |
485 | gtk_widget_map (child->widget); | |
486 | } | |
c801d85f | 487 | } |
bf3dab48 | 488 | |
053f9cc1 | 489 | gdk_window_show (widget->window); |
da048e3d | 490 | gdk_window_show (pizza->bin_window); |
c801d85f KB |
491 | } |
492 | ||
c801d85f | 493 | static void |
da048e3d | 494 | gtk_pizza_realize (GtkWidget *widget) |
c801d85f | 495 | { |
da048e3d | 496 | GtkPizza *pizza; |
053f9cc1 RR |
497 | GdkWindowAttr attributes; |
498 | gint attributes_mask; | |
da048e3d | 499 | GtkPizzaChild *child; |
ed673c6a | 500 | GList *children; |
c801d85f | 501 | |
053f9cc1 | 502 | g_return_if_fail (widget != NULL); |
da048e3d | 503 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
c801d85f | 504 | |
da048e3d | 505 | pizza = GTK_PIZZA (widget); |
053f9cc1 | 506 | GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); |
c801d85f | 507 | |
053f9cc1 | 508 | attributes.window_type = GDK_WINDOW_CHILD; |
bf3dab48 | 509 | |
053f9cc1 RR |
510 | attributes.x = widget->allocation.x; |
511 | attributes.y = widget->allocation.y; | |
512 | attributes.width = widget->allocation.width; | |
513 | attributes.height = widget->allocation.height; | |
514 | ||
1e6feb95 | 515 | #ifndef __WXUNIVERSAL__ |
da048e3d | 516 | if (pizza->shadow_type == GTK_MYSHADOW_NONE) |
053f9cc1 | 517 | { |
5e014a0c | 518 | /* no border, no changes to sizes */ |
1e6feb95 VZ |
519 | } |
520 | else if (pizza->shadow_type == GTK_MYSHADOW_THIN) | |
5e014a0c RR |
521 | { |
522 | /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */ | |
523 | attributes.x += 1; | |
524 | attributes.y += 1; | |
525 | attributes.width -= 2; | |
526 | attributes.height -= 2; | |
1e6feb95 VZ |
527 | } |
528 | else | |
5e014a0c RR |
529 | { |
530 | /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */ | |
531 | /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */ | |
053f9cc1 RR |
532 | attributes.x += 2; |
533 | attributes.y += 2; | |
534 | attributes.width -= 4; | |
535 | attributes.height -= 4; | |
536 | } | |
1e6feb95 | 537 | #endif /* __WXUNIVERSAL__ */ |
bf3dab48 | 538 | |
ed673c6a | 539 | /* minimal size */ |
053f9cc1 RR |
540 | if (attributes.width < 2) attributes.width = 2; |
541 | if (attributes.height < 2) attributes.height = 2; | |
bf3dab48 | 542 | |
053f9cc1 RR |
543 | attributes.wclass = GDK_INPUT_OUTPUT; |
544 | attributes.visual = gtk_widget_get_visual (widget); | |
545 | attributes.colormap = gtk_widget_get_colormap (widget); | |
3dd9b88a | 546 | attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; |
ed673c6a | 547 | attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; |
bf3dab48 | 548 | |
c916e13b | 549 | widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), |
bf3dab48 | 550 | &attributes, attributes_mask); |
ed673c6a RR |
551 | gdk_window_set_user_data (widget->window, widget); |
552 | ||
553 | attributes.x = 0; | |
554 | attributes.y = 0; | |
bf3dab48 | 555 | |
053f9cc1 | 556 | attributes.event_mask = gtk_widget_get_events (widget); |
3dd9b88a | 557 | attributes.event_mask |= GDK_EXPOSURE_MASK | |
67d78217 | 558 | GDK_SCROLL_MASK | |
3dd9b88a VZ |
559 | GDK_POINTER_MOTION_MASK | |
560 | GDK_POINTER_MOTION_HINT_MASK | | |
561 | GDK_BUTTON_MOTION_MASK | | |
562 | GDK_BUTTON1_MOTION_MASK | | |
563 | GDK_BUTTON2_MOTION_MASK | | |
564 | GDK_BUTTON3_MOTION_MASK | | |
565 | GDK_BUTTON_PRESS_MASK | | |
566 | GDK_BUTTON_RELEASE_MASK | | |
567 | GDK_KEY_PRESS_MASK | | |
568 | GDK_KEY_RELEASE_MASK | | |
569 | GDK_ENTER_NOTIFY_MASK | | |
570 | GDK_LEAVE_NOTIFY_MASK | | |
571 | GDK_FOCUS_CHANGE_MASK; | |
053f9cc1 | 572 | |
c916e13b | 573 | pizza->bin_window = gdk_window_new(widget->window, |
bf3dab48 | 574 | &attributes, attributes_mask); |
da048e3d | 575 | gdk_window_set_user_data (pizza->bin_window, widget); |
bf3dab48 | 576 | |
053f9cc1 RR |
577 | widget->style = gtk_style_attach (widget->style, widget->window); |
578 | gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); | |
b6fa52db | 579 | gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL ); |
17a1ebd1 | 580 | |
33611ebb RR |
581 | /* |
582 | gdk_window_set_back_pixmap( widget->window, NULL, FALSE ); | |
583 | gdk_window_set_back_pixmap( pizza->bin_window, NULL, FALSE ); | |
584 | */ | |
bf3dab48 | 585 | |
ed673c6a | 586 | /* cannot be done before realisation */ |
da048e3d | 587 | children = pizza->children; |
ed673c6a RR |
588 | while (children) |
589 | { | |
590 | child = children->data; | |
591 | children = children->next; | |
592 | ||
da048e3d | 593 | gtk_widget_set_parent_window (child->widget, pizza->bin_window); |
ed673c6a RR |
594 | } |
595 | } | |
596 | ||
bf3dab48 | 597 | static void |
da048e3d | 598 | gtk_pizza_unrealize (GtkWidget *widget) |
ed673c6a | 599 | { |
d5ab387d | 600 | GtkPizza *pizza; |
ed673c6a | 601 | |
d5ab387d RR |
602 | g_return_if_fail (widget != NULL); |
603 | g_return_if_fail (GTK_IS_PIZZA (widget)); | |
ed673c6a | 604 | |
d5ab387d | 605 | pizza = GTK_PIZZA (widget); |
ed673c6a | 606 | |
d5ab387d RR |
607 | gdk_window_set_user_data (pizza->bin_window, NULL); |
608 | gdk_window_destroy (pizza->bin_window); | |
609 | pizza->bin_window = NULL; | |
ed673c6a | 610 | |
67d78217 RR |
611 | if (GTK_WIDGET_CLASS (pizza_parent_class)->unrealize) |
612 | (* GTK_WIDGET_CLASS (pizza_parent_class)->unrealize) (widget); | |
c801d85f KB |
613 | } |
614 | ||
615 | static void | |
da048e3d | 616 | gtk_pizza_size_request (GtkWidget *widget, |
b6fa52db | 617 | GtkRequisition *requisition) |
c801d85f | 618 | { |
da048e3d RR |
619 | GtkPizza *pizza; |
620 | GtkPizzaChild *child; | |
053f9cc1 RR |
621 | GList *children; |
622 | GtkRequisition child_requisition; | |
bf3dab48 | 623 | |
053f9cc1 | 624 | g_return_if_fail (widget != NULL); |
da048e3d | 625 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
053f9cc1 | 626 | g_return_if_fail (requisition != NULL); |
c801d85f | 627 | |
da048e3d | 628 | pizza = GTK_PIZZA (widget); |
bf3dab48 | 629 | |
da048e3d | 630 | children = pizza->children; |
053f9cc1 | 631 | while (children) |
c801d85f | 632 | { |
053f9cc1 RR |
633 | child = children->data; |
634 | children = children->next; | |
c801d85f | 635 | |
053f9cc1 | 636 | if (GTK_WIDGET_VISIBLE (child->widget)) |
bf3dab48 | 637 | { |
053f9cc1 | 638 | gtk_widget_size_request (child->widget, &child_requisition); |
bf3dab48 | 639 | } |
c801d85f | 640 | } |
bf3dab48 | 641 | |
053f9cc1 RR |
642 | /* request very little, I'm not sure if requesting nothing |
643 | will always have positive effects on stability... */ | |
644 | requisition->width = 2; | |
645 | requisition->height = 2; | |
c801d85f KB |
646 | } |
647 | ||
648 | static void | |
da048e3d | 649 | gtk_pizza_size_allocate (GtkWidget *widget, |
b6fa52db | 650 | GtkAllocation *allocation) |
c801d85f | 651 | { |
da048e3d | 652 | GtkPizza *pizza; |
053f9cc1 | 653 | gint border; |
ed673c6a | 654 | gint x,y,w,h; |
da048e3d | 655 | GtkPizzaChild *child; |
ed673c6a | 656 | GList *children; |
c801d85f | 657 | |
053f9cc1 | 658 | g_return_if_fail (widget != NULL); |
da048e3d | 659 | g_return_if_fail (GTK_IS_PIZZA(widget)); |
053f9cc1 | 660 | g_return_if_fail (allocation != NULL); |
c801d85f | 661 | |
da048e3d | 662 | pizza = GTK_PIZZA (widget); |
bf3dab48 | 663 | |
227e5e99 | 664 | widget->allocation = *allocation; |
bf3dab48 | 665 | |
da048e3d | 666 | if (pizza->shadow_type == GTK_MYSHADOW_NONE) |
053f9cc1 | 667 | border = 0; |
5e014a0c | 668 | else |
da048e3d | 669 | if (pizza->shadow_type == GTK_MYSHADOW_THIN) |
5e014a0c | 670 | border = 1; |
053f9cc1 RR |
671 | else |
672 | border = 2; | |
bf3dab48 | 673 | |
ed673c6a RR |
674 | x = allocation->x + border; |
675 | y = allocation->y + border; | |
676 | w = allocation->width - border*2; | |
677 | h = allocation->height - border*2; | |
034be888 | 678 | |
053f9cc1 RR |
679 | if (GTK_WIDGET_REALIZED (widget)) |
680 | { | |
ed673c6a | 681 | gdk_window_move_resize( widget->window, x, y, w, h ); |
da048e3d | 682 | gdk_window_move_resize( pizza->bin_window, 0, 0, w, h ); |
053f9cc1 | 683 | } |
bf3dab48 | 684 | |
da048e3d | 685 | children = pizza->children; |
6d693bb4 RR |
686 | while (children) |
687 | { | |
688 | child = children->data; | |
689 | children = children->next; | |
bf3dab48 | 690 | |
da048e3d | 691 | gtk_pizza_allocate_child (pizza, child); |
6d693bb4 | 692 | } |
c801d85f KB |
693 | } |
694 | ||
c801d85f | 695 | static gint |
da048e3d | 696 | gtk_pizza_expose (GtkWidget *widget, |
b6fa52db | 697 | GdkEventExpose *event) |
c801d85f | 698 | { |
b420fb6a | 699 | GtkPizza *pizza; |
b420fb6a RR |
700 | |
701 | g_return_val_if_fail (widget != NULL, FALSE); | |
702 | g_return_val_if_fail (GTK_IS_PIZZA (widget), FALSE); | |
703 | g_return_val_if_fail (event != NULL, FALSE); | |
704 | ||
705 | pizza = GTK_PIZZA (widget); | |
706 | ||
67d78217 RR |
707 | if (event->window != pizza->bin_window) |
708 | return FALSE; | |
4e5a4c69 | 709 | |
67d78217 | 710 | /* We handle all expose events in window.cpp now. */ |
b420fb6a | 711 | if (pizza->external_expose) |
d5ab387d | 712 | return FALSE; |
b420fb6a | 713 | |
67d78217 | 714 | (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, event); |
17a1ebd1 | 715 | |
67d78217 | 716 | return FALSE; |
c801d85f KB |
717 | } |
718 | ||
22aff579 VS |
719 | static void |
720 | gtk_pizza_style_set(GtkWidget *widget, GtkStyle *previous_style) | |
721 | { | |
722 | if (GTK_WIDGET_REALIZED(widget)) | |
723 | { | |
724 | gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); | |
725 | gtk_style_set_background(widget->style, GTK_PIZZA(widget)->bin_window, GTK_STATE_NORMAL ); | |
726 | } | |
727 | ||
728 | (* GTK_WIDGET_CLASS (pizza_parent_class)->style_set) (widget, previous_style); | |
729 | } | |
730 | ||
c801d85f | 731 | static void |
da048e3d | 732 | gtk_pizza_add (GtkContainer *container, |
bf3dab48 | 733 | GtkWidget *widget) |
c801d85f | 734 | { |
ed673c6a | 735 | g_return_if_fail (container != NULL); |
da048e3d | 736 | g_return_if_fail (GTK_IS_PIZZA (container)); |
ed673c6a | 737 | g_return_if_fail (widget != NULL); |
c801d85f | 738 | |
da048e3d | 739 | gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 ); |
c801d85f KB |
740 | } |
741 | ||
742 | static void | |
da048e3d | 743 | gtk_pizza_remove (GtkContainer *container, |
b6fa52db | 744 | GtkWidget *widget) |
c801d85f | 745 | { |
da048e3d RR |
746 | GtkPizza *pizza; |
747 | GtkPizzaChild *child; | |
ed673c6a | 748 | GList *children; |
c801d85f | 749 | |
ed673c6a | 750 | g_return_if_fail (container != NULL); |
da048e3d | 751 | g_return_if_fail (GTK_IS_PIZZA (container)); |
ed673c6a | 752 | g_return_if_fail (widget != NULL); |
c801d85f | 753 | |
da048e3d | 754 | pizza = GTK_PIZZA (container); |
c801d85f | 755 | |
da048e3d | 756 | children = pizza->children; |
ed673c6a | 757 | while (children) |
c801d85f | 758 | { |
ed673c6a | 759 | child = children->data; |
c801d85f | 760 | |
ed673c6a | 761 | if (child->widget == widget) |
bf3dab48 VZ |
762 | { |
763 | gtk_widget_unparent (widget); | |
c801d85f | 764 | |
ed673c6a RR |
765 | /* security checks */ |
766 | g_return_if_fail (GTK_IS_WIDGET (widget)); | |
bf3dab48 VZ |
767 | |
768 | pizza->children = g_list_remove_link (pizza->children, children); | |
769 | g_list_free (children); | |
770 | g_free (child); | |
c801d85f | 771 | |
ed673c6a | 772 | /* security checks */ |
bf3dab48 VZ |
773 | g_return_if_fail (GTK_IS_WIDGET (widget)); |
774 | ||
bf3dab48 VZ |
775 | break; |
776 | } | |
c801d85f | 777 | |
ed673c6a | 778 | children = children->next; |
c801d85f KB |
779 | } |
780 | } | |
781 | ||
782 | static void | |
da048e3d | 783 | gtk_pizza_forall (GtkContainer *container, |
b6fa52db RR |
784 | gboolean include_internals, |
785 | GtkCallback callback, | |
786 | gpointer callback_data) | |
c801d85f | 787 | { |
da048e3d RR |
788 | GtkPizza *pizza; |
789 | GtkPizzaChild *child; | |
6d693bb4 | 790 | GList *children; |
c801d85f | 791 | |
6d693bb4 | 792 | g_return_if_fail (container != NULL); |
da048e3d | 793 | g_return_if_fail (GTK_IS_PIZZA (container)); |
90350682 | 794 | g_return_if_fail (callback != (GtkCallback)NULL); |
c801d85f | 795 | |
da048e3d | 796 | pizza = GTK_PIZZA (container); |
c801d85f | 797 | |
da048e3d | 798 | children = pizza->children; |
6d693bb4 | 799 | while (children) |
c801d85f | 800 | { |
6d693bb4 RR |
801 | child = children->data; |
802 | children = children->next; | |
c801d85f | 803 | |
6d693bb4 | 804 | (* callback) (child->widget, callback_data); |
c801d85f KB |
805 | } |
806 | } | |
807 | ||
67d78217 RR |
808 | static void |
809 | gtk_pizza_allocate_child (GtkPizza *pizza, | |
810 | GtkPizzaChild *child) | |
811 | { | |
812 | GtkAllocation allocation; | |
813 | GtkRequisition requisition; | |
c801d85f | 814 | |
67d78217 RR |
815 | allocation.x = child->x - pizza->xoffset; |
816 | allocation.y = child->y - pizza->yoffset; | |
817 | gtk_widget_get_child_requisition (child->widget, &requisition); | |
818 | allocation.width = requisition.width; | |
819 | allocation.height = requisition.height; | |
820 | ||
821 | gtk_widget_size_allocate (child->widget, &allocation); | |
822 | } | |
ed673c6a | 823 | |
ed673c6a | 824 | static void |
da048e3d | 825 | gtk_pizza_adjust_allocations_recurse (GtkWidget *widget, |
bf3dab48 | 826 | gpointer cb_data) |
ed673c6a | 827 | { |
da048e3d | 828 | GtkPizzaAdjData *data = cb_data; |
ed673c6a | 829 | |
6d693bb4 RR |
830 | widget->allocation.x += data->dx; |
831 | widget->allocation.y += data->dy; | |
ed673c6a | 832 | |
6d693bb4 RR |
833 | if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget)) |
834 | { | |
bf3dab48 VZ |
835 | gtk_container_forall (GTK_CONTAINER (widget), |
836 | gtk_pizza_adjust_allocations_recurse, | |
837 | cb_data); | |
6d693bb4 | 838 | } |
ed673c6a RR |
839 | } |
840 | ||
841 | static void | |
da048e3d | 842 | gtk_pizza_adjust_allocations (GtkPizza *pizza, |
bf3dab48 VZ |
843 | gint dx, |
844 | gint dy) | |
ed673c6a | 845 | { |
0e09f76e RR |
846 | GList *tmp_list; |
847 | GtkPizzaAdjData data; | |
ed673c6a | 848 | |
0e09f76e RR |
849 | data.dx = dx; |
850 | data.dy = dy; | |
ed673c6a | 851 | |
0e09f76e RR |
852 | tmp_list = pizza->children; |
853 | while (tmp_list) | |
ed673c6a | 854 | { |
0e09f76e RR |
855 | GtkPizzaChild *child = tmp_list->data; |
856 | tmp_list = tmp_list->next; | |
bf3dab48 | 857 | |
0e09f76e RR |
858 | child->widget->allocation.x += dx; |
859 | child->widget->allocation.y += dy; | |
ed673c6a | 860 | |
0e09f76e RR |
861 | if (GTK_WIDGET_NO_WINDOW (child->widget) && |
862 | GTK_IS_CONTAINER (child->widget)) | |
863 | { | |
864 | gtk_container_forall (GTK_CONTAINER (child->widget), | |
865 | gtk_pizza_adjust_allocations_recurse, | |
866 | &data); | |
867 | } | |
ed673c6a RR |
868 | } |
869 | } | |
bf3dab48 | 870 | |
ed673c6a RR |
871 | |
872 | /* This is the main routine to do the scrolling. Scrolling is | |
873 | * done by "Guffaw" scrolling, as in the Mozilla XFE, with | |
874 | * a few modifications. | |
bf3dab48 | 875 | * |
ed673c6a RR |
876 | * The main improvement is that we keep track of whether we |
877 | * are obscured or not. If not, we ignore the generated expose | |
878 | * events and instead do the exposes ourself, without having | |
879 | * to wait for a roundtrip to the server. This also provides | |
880 | * a limited form of expose-event compression, since we do | |
881 | * the affected area as one big chunk. | |
882 | */ | |
883 | ||
884 | void | |
da048e3d | 885 | gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy) |
ed673c6a | 886 | { |
3fc6e5fa RR |
887 | pizza->xoffset += dx; |
888 | pizza->yoffset += dy; | |
889 | ||
890 | gtk_pizza_adjust_allocations (pizza, -dx, -dy); | |
891 | ||
892 | if (pizza->bin_window) | |
893 | gdk_window_scroll( pizza->bin_window, -dx, -dy ); | |
ed673c6a RR |
894 | } |
895 | ||
c801d85f KB |
896 | #ifdef __cplusplus |
897 | } | |
898 | #endif /* __cplusplus */ |