]>
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 | |
6b71411a VZ |
397 | /* this really shouldn't happen -- but it does, a lot, right now and we |
398 | can't pass negative values to gtk_widget_set_size_request(), so filter | |
399 | them out here */ | |
400 | if ( width < 0 ) | |
401 | width = 0; | |
402 | if ( height < 0 ) | |
403 | height = 0; | |
404 | ||
da048e3d | 405 | children = pizza->children; |
053f9cc1 | 406 | while (children) |
c801d85f | 407 | { |
053f9cc1 RR |
408 | child = children->data; |
409 | children = children->next; | |
c801d85f | 410 | |
053f9cc1 | 411 | if (child->widget == widget) |
c801d85f | 412 | { |
bf3dab48 VZ |
413 | if ((child->x == x) && |
414 | (child->y == y) && | |
415 | (child->width == width) && | |
416 | (child->height == height)) return; | |
417 | ||
053f9cc1 RR |
418 | child->x = x; |
419 | child->y = y; | |
420 | child->width = width; | |
421 | child->height = height; | |
bf3dab48 | 422 | |
370dc79c | 423 | gtk_widget_set_size_request (widget, width, height); |
bf3dab48 | 424 | |
da048e3d | 425 | if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (pizza)) |
bf3dab48 VZ |
426 | gtk_widget_queue_resize (widget); |
427 | ||
6d693bb4 | 428 | return; |
c801d85f KB |
429 | } |
430 | } | |
431 | } | |
432 | ||
3dd9b88a | 433 | gint |
8cb9f0d0 RR |
434 | gtk_pizza_child_resized (GtkPizza *pizza, |
435 | GtkWidget *widget) | |
436 | { | |
437 | GtkPizzaChild *child; | |
438 | GList *children; | |
439 | ||
440 | g_return_val_if_fail (pizza != NULL, FALSE); | |
441 | g_return_val_if_fail (GTK_IS_PIZZA (pizza), FALSE); | |
442 | g_return_val_if_fail (widget != NULL, FALSE); | |
443 | ||
444 | children = pizza->children; | |
445 | while (children) | |
446 | { | |
447 | child = children->data; | |
448 | children = children->next; | |
449 | ||
450 | if (child->widget == widget) | |
451 | { | |
452 | return ((child->width == widget->allocation.width) && | |
453 | (child->height == widget->allocation.height)); | |
454 | } | |
455 | } | |
3dd9b88a | 456 | |
8cb9f0d0 RR |
457 | return FALSE; |
458 | } | |
3dd9b88a | 459 | |
c801d85f | 460 | static void |
da048e3d | 461 | gtk_pizza_map (GtkWidget *widget) |
c801d85f | 462 | { |
da048e3d RR |
463 | GtkPizza *pizza; |
464 | GtkPizzaChild *child; | |
053f9cc1 | 465 | GList *children; |
c801d85f | 466 | |
053f9cc1 | 467 | g_return_if_fail (widget != NULL); |
da048e3d | 468 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
c801d85f | 469 | |
053f9cc1 | 470 | GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); |
da048e3d | 471 | pizza = GTK_PIZZA (widget); |
c801d85f | 472 | |
da048e3d | 473 | children = pizza->children; |
053f9cc1 | 474 | while (children) |
c801d85f | 475 | { |
053f9cc1 RR |
476 | child = children->data; |
477 | children = children->next; | |
c801d85f | 478 | |
bf3dab48 VZ |
479 | if ( GTK_WIDGET_VISIBLE (child->widget) && |
480 | !GTK_WIDGET_MAPPED (child->widget) && | |
a2d8ce85 | 481 | TRUE) |
bf3dab48 VZ |
482 | { |
483 | gtk_widget_map (child->widget); | |
484 | } | |
c801d85f | 485 | } |
bf3dab48 | 486 | |
053f9cc1 | 487 | gdk_window_show (widget->window); |
da048e3d | 488 | gdk_window_show (pizza->bin_window); |
c801d85f KB |
489 | } |
490 | ||
c801d85f | 491 | static void |
da048e3d | 492 | gtk_pizza_realize (GtkWidget *widget) |
c801d85f | 493 | { |
da048e3d | 494 | GtkPizza *pizza; |
053f9cc1 RR |
495 | GdkWindowAttr attributes; |
496 | gint attributes_mask; | |
da048e3d | 497 | GtkPizzaChild *child; |
ed673c6a | 498 | GList *children; |
c801d85f | 499 | |
053f9cc1 | 500 | g_return_if_fail (widget != NULL); |
da048e3d | 501 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
c801d85f | 502 | |
da048e3d | 503 | pizza = GTK_PIZZA (widget); |
053f9cc1 | 504 | GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); |
c801d85f | 505 | |
053f9cc1 | 506 | attributes.window_type = GDK_WINDOW_CHILD; |
bf3dab48 | 507 | |
053f9cc1 RR |
508 | attributes.x = widget->allocation.x; |
509 | attributes.y = widget->allocation.y; | |
510 | attributes.width = widget->allocation.width; | |
511 | attributes.height = widget->allocation.height; | |
512 | ||
1e6feb95 | 513 | #ifndef __WXUNIVERSAL__ |
da048e3d | 514 | if (pizza->shadow_type == GTK_MYSHADOW_NONE) |
053f9cc1 | 515 | { |
5e014a0c | 516 | /* no border, no changes to sizes */ |
1e6feb95 VZ |
517 | } |
518 | else if (pizza->shadow_type == GTK_MYSHADOW_THIN) | |
5e014a0c RR |
519 | { |
520 | /* GTK_MYSHADOW_THIN == wxSIMPLE_BORDER */ | |
521 | attributes.x += 1; | |
522 | attributes.y += 1; | |
523 | attributes.width -= 2; | |
524 | attributes.height -= 2; | |
1e6feb95 VZ |
525 | } |
526 | else | |
5e014a0c RR |
527 | { |
528 | /* GTK_MYSHADOW_IN == wxSUNKEN_BORDER */ | |
529 | /* GTK_MYSHADOW_OUT == wxRAISED_BORDER */ | |
053f9cc1 RR |
530 | attributes.x += 2; |
531 | attributes.y += 2; | |
532 | attributes.width -= 4; | |
533 | attributes.height -= 4; | |
534 | } | |
1e6feb95 | 535 | #endif /* __WXUNIVERSAL__ */ |
bf3dab48 | 536 | |
ed673c6a | 537 | /* minimal size */ |
053f9cc1 RR |
538 | if (attributes.width < 2) attributes.width = 2; |
539 | if (attributes.height < 2) attributes.height = 2; | |
bf3dab48 | 540 | |
053f9cc1 RR |
541 | attributes.wclass = GDK_INPUT_OUTPUT; |
542 | attributes.visual = gtk_widget_get_visual (widget); | |
543 | attributes.colormap = gtk_widget_get_colormap (widget); | |
3dd9b88a | 544 | attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; |
ed673c6a | 545 | attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; |
bf3dab48 | 546 | |
c916e13b | 547 | widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), |
bf3dab48 | 548 | &attributes, attributes_mask); |
ed673c6a RR |
549 | gdk_window_set_user_data (widget->window, widget); |
550 | ||
551 | attributes.x = 0; | |
552 | attributes.y = 0; | |
bf3dab48 | 553 | |
053f9cc1 | 554 | attributes.event_mask = gtk_widget_get_events (widget); |
3dd9b88a | 555 | attributes.event_mask |= GDK_EXPOSURE_MASK | |
67d78217 | 556 | GDK_SCROLL_MASK | |
3dd9b88a VZ |
557 | GDK_POINTER_MOTION_MASK | |
558 | GDK_POINTER_MOTION_HINT_MASK | | |
559 | GDK_BUTTON_MOTION_MASK | | |
560 | GDK_BUTTON1_MOTION_MASK | | |
561 | GDK_BUTTON2_MOTION_MASK | | |
562 | GDK_BUTTON3_MOTION_MASK | | |
563 | GDK_BUTTON_PRESS_MASK | | |
564 | GDK_BUTTON_RELEASE_MASK | | |
565 | GDK_KEY_PRESS_MASK | | |
566 | GDK_KEY_RELEASE_MASK | | |
567 | GDK_ENTER_NOTIFY_MASK | | |
568 | GDK_LEAVE_NOTIFY_MASK | | |
569 | GDK_FOCUS_CHANGE_MASK; | |
053f9cc1 | 570 | |
c916e13b | 571 | pizza->bin_window = gdk_window_new(widget->window, |
bf3dab48 | 572 | &attributes, attributes_mask); |
da048e3d | 573 | gdk_window_set_user_data (pizza->bin_window, widget); |
bf3dab48 | 574 | |
053f9cc1 RR |
575 | widget->style = gtk_style_attach (widget->style, widget->window); |
576 | gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); | |
b6fa52db | 577 | gtk_style_set_background (widget->style, pizza->bin_window, GTK_STATE_NORMAL ); |
17a1ebd1 | 578 | |
33611ebb RR |
579 | /* |
580 | gdk_window_set_back_pixmap( widget->window, NULL, FALSE ); | |
581 | gdk_window_set_back_pixmap( pizza->bin_window, NULL, FALSE ); | |
582 | */ | |
bf3dab48 | 583 | |
ed673c6a | 584 | /* cannot be done before realisation */ |
da048e3d | 585 | children = pizza->children; |
ed673c6a RR |
586 | while (children) |
587 | { | |
588 | child = children->data; | |
589 | children = children->next; | |
590 | ||
da048e3d | 591 | gtk_widget_set_parent_window (child->widget, pizza->bin_window); |
ed673c6a RR |
592 | } |
593 | } | |
594 | ||
bf3dab48 | 595 | static void |
da048e3d | 596 | gtk_pizza_unrealize (GtkWidget *widget) |
ed673c6a | 597 | { |
d5ab387d | 598 | GtkPizza *pizza; |
ed673c6a | 599 | |
d5ab387d RR |
600 | g_return_if_fail (widget != NULL); |
601 | g_return_if_fail (GTK_IS_PIZZA (widget)); | |
ed673c6a | 602 | |
d5ab387d | 603 | pizza = GTK_PIZZA (widget); |
ed673c6a | 604 | |
d5ab387d RR |
605 | gdk_window_set_user_data (pizza->bin_window, NULL); |
606 | gdk_window_destroy (pizza->bin_window); | |
607 | pizza->bin_window = NULL; | |
ed673c6a | 608 | |
67d78217 RR |
609 | if (GTK_WIDGET_CLASS (pizza_parent_class)->unrealize) |
610 | (* GTK_WIDGET_CLASS (pizza_parent_class)->unrealize) (widget); | |
c801d85f KB |
611 | } |
612 | ||
613 | static void | |
da048e3d | 614 | gtk_pizza_size_request (GtkWidget *widget, |
b6fa52db | 615 | GtkRequisition *requisition) |
c801d85f | 616 | { |
da048e3d RR |
617 | GtkPizza *pizza; |
618 | GtkPizzaChild *child; | |
053f9cc1 RR |
619 | GList *children; |
620 | GtkRequisition child_requisition; | |
bf3dab48 | 621 | |
053f9cc1 | 622 | g_return_if_fail (widget != NULL); |
da048e3d | 623 | g_return_if_fail (GTK_IS_PIZZA (widget)); |
053f9cc1 | 624 | g_return_if_fail (requisition != NULL); |
c801d85f | 625 | |
da048e3d | 626 | pizza = GTK_PIZZA (widget); |
bf3dab48 | 627 | |
da048e3d | 628 | children = pizza->children; |
053f9cc1 | 629 | while (children) |
c801d85f | 630 | { |
053f9cc1 RR |
631 | child = children->data; |
632 | children = children->next; | |
c801d85f | 633 | |
053f9cc1 | 634 | if (GTK_WIDGET_VISIBLE (child->widget)) |
bf3dab48 | 635 | { |
053f9cc1 | 636 | gtk_widget_size_request (child->widget, &child_requisition); |
bf3dab48 | 637 | } |
c801d85f | 638 | } |
bf3dab48 | 639 | |
053f9cc1 RR |
640 | /* request very little, I'm not sure if requesting nothing |
641 | will always have positive effects on stability... */ | |
642 | requisition->width = 2; | |
643 | requisition->height = 2; | |
c801d85f KB |
644 | } |
645 | ||
646 | static void | |
da048e3d | 647 | gtk_pizza_size_allocate (GtkWidget *widget, |
b6fa52db | 648 | GtkAllocation *allocation) |
c801d85f | 649 | { |
da048e3d | 650 | GtkPizza *pizza; |
053f9cc1 | 651 | gint border; |
ed673c6a | 652 | gint x,y,w,h; |
da048e3d | 653 | GtkPizzaChild *child; |
ed673c6a | 654 | GList *children; |
c801d85f | 655 | |
053f9cc1 | 656 | g_return_if_fail (widget != NULL); |
da048e3d | 657 | g_return_if_fail (GTK_IS_PIZZA(widget)); |
053f9cc1 | 658 | g_return_if_fail (allocation != NULL); |
c801d85f | 659 | |
da048e3d | 660 | pizza = GTK_PIZZA (widget); |
bf3dab48 | 661 | |
227e5e99 | 662 | widget->allocation = *allocation; |
bf3dab48 | 663 | |
da048e3d | 664 | if (pizza->shadow_type == GTK_MYSHADOW_NONE) |
053f9cc1 | 665 | border = 0; |
5e014a0c | 666 | else |
da048e3d | 667 | if (pizza->shadow_type == GTK_MYSHADOW_THIN) |
5e014a0c | 668 | border = 1; |
053f9cc1 RR |
669 | else |
670 | border = 2; | |
bf3dab48 | 671 | |
ed673c6a RR |
672 | x = allocation->x + border; |
673 | y = allocation->y + border; | |
674 | w = allocation->width - border*2; | |
675 | h = allocation->height - border*2; | |
034be888 | 676 | |
053f9cc1 RR |
677 | if (GTK_WIDGET_REALIZED (widget)) |
678 | { | |
ed673c6a | 679 | gdk_window_move_resize( widget->window, x, y, w, h ); |
da048e3d | 680 | gdk_window_move_resize( pizza->bin_window, 0, 0, w, h ); |
053f9cc1 | 681 | } |
bf3dab48 | 682 | |
da048e3d | 683 | children = pizza->children; |
6d693bb4 RR |
684 | while (children) |
685 | { | |
686 | child = children->data; | |
687 | children = children->next; | |
bf3dab48 | 688 | |
da048e3d | 689 | gtk_pizza_allocate_child (pizza, child); |
6d693bb4 | 690 | } |
c801d85f KB |
691 | } |
692 | ||
c801d85f | 693 | static gint |
da048e3d | 694 | gtk_pizza_expose (GtkWidget *widget, |
b6fa52db | 695 | GdkEventExpose *event) |
c801d85f | 696 | { |
b420fb6a | 697 | GtkPizza *pizza; |
b420fb6a RR |
698 | |
699 | g_return_val_if_fail (widget != NULL, FALSE); | |
700 | g_return_val_if_fail (GTK_IS_PIZZA (widget), FALSE); | |
701 | g_return_val_if_fail (event != NULL, FALSE); | |
702 | ||
703 | pizza = GTK_PIZZA (widget); | |
704 | ||
67d78217 RR |
705 | if (event->window != pizza->bin_window) |
706 | return FALSE; | |
4e5a4c69 | 707 | |
67d78217 | 708 | /* We handle all expose events in window.cpp now. */ |
b420fb6a | 709 | if (pizza->external_expose) |
d5ab387d | 710 | return FALSE; |
b420fb6a | 711 | |
67d78217 | 712 | (* GTK_WIDGET_CLASS (pizza_parent_class)->expose_event) (widget, event); |
17a1ebd1 | 713 | |
67d78217 | 714 | return FALSE; |
c801d85f KB |
715 | } |
716 | ||
22aff579 VS |
717 | static void |
718 | gtk_pizza_style_set(GtkWidget *widget, GtkStyle *previous_style) | |
719 | { | |
720 | if (GTK_WIDGET_REALIZED(widget)) | |
721 | { | |
722 | gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); | |
723 | gtk_style_set_background(widget->style, GTK_PIZZA(widget)->bin_window, GTK_STATE_NORMAL ); | |
724 | } | |
725 | ||
726 | (* GTK_WIDGET_CLASS (pizza_parent_class)->style_set) (widget, previous_style); | |
727 | } | |
728 | ||
c801d85f | 729 | static void |
da048e3d | 730 | gtk_pizza_add (GtkContainer *container, |
bf3dab48 | 731 | GtkWidget *widget) |
c801d85f | 732 | { |
ed673c6a | 733 | g_return_if_fail (container != NULL); |
da048e3d | 734 | g_return_if_fail (GTK_IS_PIZZA (container)); |
ed673c6a | 735 | g_return_if_fail (widget != NULL); |
c801d85f | 736 | |
da048e3d | 737 | gtk_pizza_put (GTK_PIZZA (container), widget, 0, 0, 20, 20 ); |
c801d85f KB |
738 | } |
739 | ||
740 | static void | |
da048e3d | 741 | gtk_pizza_remove (GtkContainer *container, |
b6fa52db | 742 | GtkWidget *widget) |
c801d85f | 743 | { |
da048e3d RR |
744 | GtkPizza *pizza; |
745 | GtkPizzaChild *child; | |
ed673c6a | 746 | GList *children; |
c801d85f | 747 | |
ed673c6a | 748 | g_return_if_fail (container != NULL); |
da048e3d | 749 | g_return_if_fail (GTK_IS_PIZZA (container)); |
ed673c6a | 750 | g_return_if_fail (widget != NULL); |
c801d85f | 751 | |
da048e3d | 752 | pizza = GTK_PIZZA (container); |
c801d85f | 753 | |
da048e3d | 754 | children = pizza->children; |
ed673c6a | 755 | while (children) |
c801d85f | 756 | { |
ed673c6a | 757 | child = children->data; |
c801d85f | 758 | |
ed673c6a | 759 | if (child->widget == widget) |
bf3dab48 VZ |
760 | { |
761 | gtk_widget_unparent (widget); | |
c801d85f | 762 | |
ed673c6a RR |
763 | /* security checks */ |
764 | g_return_if_fail (GTK_IS_WIDGET (widget)); | |
bf3dab48 VZ |
765 | |
766 | pizza->children = g_list_remove_link (pizza->children, children); | |
767 | g_list_free (children); | |
768 | g_free (child); | |
c801d85f | 769 | |
ed673c6a | 770 | /* security checks */ |
bf3dab48 VZ |
771 | g_return_if_fail (GTK_IS_WIDGET (widget)); |
772 | ||
bf3dab48 VZ |
773 | break; |
774 | } | |
c801d85f | 775 | |
ed673c6a | 776 | children = children->next; |
c801d85f KB |
777 | } |
778 | } | |
779 | ||
780 | static void | |
da048e3d | 781 | gtk_pizza_forall (GtkContainer *container, |
b6fa52db RR |
782 | gboolean include_internals, |
783 | GtkCallback callback, | |
784 | gpointer callback_data) | |
c801d85f | 785 | { |
da048e3d RR |
786 | GtkPizza *pizza; |
787 | GtkPizzaChild *child; | |
6d693bb4 | 788 | GList *children; |
c801d85f | 789 | |
6d693bb4 | 790 | g_return_if_fail (container != NULL); |
da048e3d | 791 | g_return_if_fail (GTK_IS_PIZZA (container)); |
90350682 | 792 | g_return_if_fail (callback != (GtkCallback)NULL); |
c801d85f | 793 | |
da048e3d | 794 | pizza = GTK_PIZZA (container); |
c801d85f | 795 | |
da048e3d | 796 | children = pizza->children; |
6d693bb4 | 797 | while (children) |
c801d85f | 798 | { |
6d693bb4 RR |
799 | child = children->data; |
800 | children = children->next; | |
c801d85f | 801 | |
6d693bb4 | 802 | (* callback) (child->widget, callback_data); |
c801d85f KB |
803 | } |
804 | } | |
805 | ||
67d78217 RR |
806 | static void |
807 | gtk_pizza_allocate_child (GtkPizza *pizza, | |
808 | GtkPizzaChild *child) | |
809 | { | |
810 | GtkAllocation allocation; | |
811 | GtkRequisition requisition; | |
c801d85f | 812 | |
67d78217 RR |
813 | allocation.x = child->x - pizza->xoffset; |
814 | allocation.y = child->y - pizza->yoffset; | |
815 | gtk_widget_get_child_requisition (child->widget, &requisition); | |
816 | allocation.width = requisition.width; | |
817 | allocation.height = requisition.height; | |
818 | ||
819 | gtk_widget_size_allocate (child->widget, &allocation); | |
820 | } | |
ed673c6a | 821 | |
ed673c6a | 822 | static void |
da048e3d | 823 | gtk_pizza_adjust_allocations_recurse (GtkWidget *widget, |
bf3dab48 | 824 | gpointer cb_data) |
ed673c6a | 825 | { |
da048e3d | 826 | GtkPizzaAdjData *data = cb_data; |
ed673c6a | 827 | |
6d693bb4 RR |
828 | widget->allocation.x += data->dx; |
829 | widget->allocation.y += data->dy; | |
ed673c6a | 830 | |
6d693bb4 RR |
831 | if (GTK_WIDGET_NO_WINDOW (widget) && GTK_IS_CONTAINER (widget)) |
832 | { | |
bf3dab48 VZ |
833 | gtk_container_forall (GTK_CONTAINER (widget), |
834 | gtk_pizza_adjust_allocations_recurse, | |
835 | cb_data); | |
6d693bb4 | 836 | } |
ed673c6a RR |
837 | } |
838 | ||
839 | static void | |
da048e3d | 840 | gtk_pizza_adjust_allocations (GtkPizza *pizza, |
bf3dab48 VZ |
841 | gint dx, |
842 | gint dy) | |
ed673c6a | 843 | { |
0e09f76e RR |
844 | GList *tmp_list; |
845 | GtkPizzaAdjData data; | |
ed673c6a | 846 | |
0e09f76e RR |
847 | data.dx = dx; |
848 | data.dy = dy; | |
ed673c6a | 849 | |
0e09f76e RR |
850 | tmp_list = pizza->children; |
851 | while (tmp_list) | |
ed673c6a | 852 | { |
0e09f76e RR |
853 | GtkPizzaChild *child = tmp_list->data; |
854 | tmp_list = tmp_list->next; | |
bf3dab48 | 855 | |
0e09f76e RR |
856 | child->widget->allocation.x += dx; |
857 | child->widget->allocation.y += dy; | |
ed673c6a | 858 | |
0e09f76e RR |
859 | if (GTK_WIDGET_NO_WINDOW (child->widget) && |
860 | GTK_IS_CONTAINER (child->widget)) | |
861 | { | |
862 | gtk_container_forall (GTK_CONTAINER (child->widget), | |
863 | gtk_pizza_adjust_allocations_recurse, | |
864 | &data); | |
865 | } | |
ed673c6a RR |
866 | } |
867 | } | |
bf3dab48 | 868 | |
ed673c6a RR |
869 | |
870 | /* This is the main routine to do the scrolling. Scrolling is | |
871 | * done by "Guffaw" scrolling, as in the Mozilla XFE, with | |
872 | * a few modifications. | |
bf3dab48 | 873 | * |
ed673c6a RR |
874 | * The main improvement is that we keep track of whether we |
875 | * are obscured or not. If not, we ignore the generated expose | |
876 | * events and instead do the exposes ourself, without having | |
877 | * to wait for a roundtrip to the server. This also provides | |
878 | * a limited form of expose-event compression, since we do | |
879 | * the affected area as one big chunk. | |
880 | */ | |
881 | ||
882 | void | |
da048e3d | 883 | gtk_pizza_scroll (GtkPizza *pizza, gint dx, gint dy) |
ed673c6a | 884 | { |
3fc6e5fa RR |
885 | pizza->xoffset += dx; |
886 | pizza->yoffset += dy; | |
887 | ||
888 | gtk_pizza_adjust_allocations (pizza, -dx, -dy); | |
889 | ||
890 | if (pizza->bin_window) | |
891 | gdk_window_scroll( pizza->bin_window, -dx, -dy ); | |
ed673c6a RR |
892 | } |
893 | ||
c801d85f KB |
894 | #ifdef __cplusplus |
895 | } | |
896 | #endif /* __cplusplus */ |