With the exceptions of DnD, wxGTk now works with
[wxWidgets.git] / src / gtk1 / win_gtk.c
1 /* ///////////////////////////////////////////////////////////////////////////
2 // Name: win_gtk.c
3 // Purpose: native GTK+ widget for wxWindows
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////// */
9
10 #include "wx/gtk/win_gtk.h"
11 #include <gtk/gtkfeatures.h>
12
13 /*-------------------------------------------------------------------------
14 // conditional compilation
15 //------------------------------------------------------------------------- */
16
17 #if (GTK_MINOR_VERSION > 0)
18 #define NEW_GTK_CONSTRUCT_CODE
19 #endif
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif /* __cplusplus */
24
25 static void gtk_myfixed_class_init (GtkMyFixedClass *klass);
26 static void gtk_myfixed_init (GtkMyFixed *myfixed);
27 static void gtk_myfixed_map (GtkWidget *widget);
28 #ifndef NEW_GTK_CONSTRUCT_CODE
29 static void gtk_myfixed_unmap (GtkWidget *widget);
30 #endif
31 static void gtk_myfixed_realize (GtkWidget *widget);
32 static void gtk_myfixed_size_request (GtkWidget *widget,
33 GtkRequisition *requisition);
34 static void gtk_myfixed_size_allocate (GtkWidget *widget,
35 GtkAllocation *allocation);
36 static void gtk_myfixed_paint (GtkWidget *widget,
37 GdkRectangle *area);
38 static void gtk_myfixed_draw (GtkWidget *widget,
39 GdkRectangle *area);
40 static gint gtk_myfixed_expose (GtkWidget *widget,
41 GdkEventExpose *event);
42 static void gtk_myfixed_add (GtkContainer *container,
43 GtkWidget *widget);
44 static void gtk_myfixed_remove (GtkContainer *container,
45 GtkWidget *widget);
46 static void gtk_myfixed_foreach (GtkContainer *container,
47 #if (GTK_MINOR_VERSION > 0)
48 gboolean include_internals,
49 #endif
50 GtkCallback callback,
51 gpointer callback_data);
52 #ifdef NEW_GTK_CONSTRUCT_CODE
53 static GtkType gtk_myfixed_child_type (GtkContainer *container);
54 #endif
55
56
57 static GtkContainerClass *parent_class = NULL;
58
59
60 guint
61 gtk_myfixed_get_type ()
62 {
63 static guint myfixed_type = 0;
64
65 if (!myfixed_type)
66 {
67 GtkTypeInfo myfixed_info =
68 {
69 "GtkMyFixed",
70 sizeof (GtkMyFixed),
71 sizeof (GtkMyFixedClass),
72 (GtkClassInitFunc) gtk_myfixed_class_init,
73 (GtkObjectInitFunc) gtk_myfixed_init,
74 #ifndef NEW_GTK_CONSTRUCT_CODE
75 (GtkArgSetFunc) NULL,
76 (GtkArgGetFunc) NULL,
77 #else
78 /* reserved_1 */ NULL,
79 /* reserved_2 */ NULL,
80 (GtkClassInitFunc) NULL,
81 #endif
82 };
83
84 myfixed_type = gtk_type_unique (gtk_container_get_type (), &myfixed_info);
85 }
86
87 return myfixed_type;
88 }
89
90 static void
91 gtk_myfixed_class_init (GtkMyFixedClass *klass)
92 {
93 GtkObjectClass *object_class;
94 GtkWidgetClass *widget_class;
95 GtkContainerClass *container_class;
96
97 object_class = (GtkObjectClass*) klass;
98 widget_class = (GtkWidgetClass*) klass;
99 container_class = (GtkContainerClass*) klass;
100
101 #ifndef NEW_GTK_CONSTRUCT_CODE
102 parent_class = gtk_type_class (gtk_container_get_type ());
103 #else
104 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
105 #endif
106
107 widget_class->map = gtk_myfixed_map;
108 #ifndef NEW_GTK_CONSTRUCT_CODE
109 widget_class->unmap = gtk_myfixed_unmap;
110 #endif
111 widget_class->realize = gtk_myfixed_realize;
112 widget_class->size_request = gtk_myfixed_size_request;
113 widget_class->size_allocate = gtk_myfixed_size_allocate;
114 widget_class->draw = gtk_myfixed_draw;
115 widget_class->expose_event = gtk_myfixed_expose;
116
117 container_class->add = gtk_myfixed_add;
118 container_class->remove = gtk_myfixed_remove;
119 #if (GTK_MINOR_VERSION > 0)
120 container_class->forall = gtk_myfixed_foreach;
121 #else
122 container_class->foreach = gtk_myfixed_foreach;
123 #endif
124
125 #ifdef NEW_GTK_CONSTRUCT_CODE
126 container_class->child_type = gtk_myfixed_child_type;
127 #endif
128 }
129
130 #ifdef NEW_GTK_CONSTRUCT_CODE
131 static GtkType
132 gtk_myfixed_child_type (GtkContainer *container)
133 {
134 return GTK_TYPE_WIDGET;
135 }
136 #endif
137
138 static void
139 gtk_myfixed_init (GtkMyFixed *myfixed)
140 {
141 GTK_WIDGET_UNSET_FLAGS (myfixed, GTK_NO_WINDOW);
142
143 #ifndef NEW_GTK_CONSTRUCT_CODE
144 GTK_WIDGET_SET_FLAGS (myfixed, GTK_BASIC);
145 #endif
146
147 myfixed->children = NULL;
148 }
149
150 GtkWidget*
151 gtk_myfixed_new ()
152 {
153 GtkMyFixed *myfixed;
154
155 myfixed = gtk_type_new (gtk_myfixed_get_type ());
156
157 return GTK_WIDGET (myfixed);
158 }
159
160 void
161 gtk_myfixed_put (GtkMyFixed *myfixed,
162 GtkWidget *widget,
163 gint16 x,
164 gint16 y)
165 {
166 GtkMyFixedChild *child_info;
167
168 g_return_if_fail (myfixed != NULL);
169 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
170 g_return_if_fail (widget != NULL);
171
172 child_info = g_new (GtkMyFixedChild, 1);
173 child_info->widget = widget;
174 child_info->x = x;
175 child_info->y = y;
176
177 gtk_widget_set_parent (widget, GTK_WIDGET (myfixed));
178
179 myfixed->children = g_list_append (myfixed->children, child_info);
180
181 if (GTK_WIDGET_REALIZED (myfixed) && !GTK_WIDGET_REALIZED (widget))
182 gtk_widget_realize (widget);
183
184 if (GTK_WIDGET_MAPPED (myfixed) && !GTK_WIDGET_MAPPED (widget))
185 gtk_widget_map (widget);
186
187 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (myfixed))
188 gtk_widget_queue_resize (GTK_WIDGET (myfixed));
189 }
190
191 void
192 gtk_myfixed_move (GtkMyFixed *myfixed,
193 GtkWidget *widget,
194 gint16 x,
195 gint16 y)
196 {
197 GtkMyFixedChild *child;
198 GList *children;
199
200 g_return_if_fail (myfixed != NULL);
201 g_return_if_fail (GTK_IS_MYFIXED (myfixed));
202 g_return_if_fail (widget != NULL);
203
204 children = myfixed->children;
205 while (children)
206 {
207 child = children->data;
208 children = children->next;
209
210 if (child->widget == widget)
211 {
212 if ((child->x == x) && (child->y == y)) return;
213
214 child->x = x;
215 child->y = y;
216
217 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (myfixed))
218 gtk_widget_queue_resize (GTK_WIDGET (myfixed));
219
220 break;
221 }
222 }
223 }
224
225 static void
226 gtk_myfixed_map (GtkWidget *widget)
227 {
228 GtkMyFixed *myfixed;
229 GtkMyFixedChild *child;
230 GList *children;
231
232 g_return_if_fail (widget != NULL);
233 g_return_if_fail (GTK_IS_MYFIXED (widget));
234
235 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
236 myfixed = GTK_MYFIXED (widget);
237
238 gdk_window_show (widget->window);
239
240 children = myfixed->children;
241 while (children)
242 {
243 child = children->data;
244 children = children->next;
245
246 if (GTK_WIDGET_VISIBLE (child->widget) &&
247 !GTK_WIDGET_MAPPED (child->widget))
248 gtk_widget_map (child->widget);
249 }
250 }
251
252 #ifndef NEW_GTK_CONSTRUCT_CODE
253 static void
254 gtk_myfixed_unmap (GtkWidget *widget)
255 {
256 g_return_if_fail (widget != NULL);
257 g_return_if_fail (GTK_IS_MYFIXED (widget));
258
259 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
260 }
261 #endif
262
263 static void
264 gtk_myfixed_realize (GtkWidget *widget)
265 {
266 GtkMyFixed *myfixed;
267 GdkWindowAttr attributes;
268 gint attributes_mask;
269
270 g_return_if_fail (widget != NULL);
271 g_return_if_fail (GTK_IS_MYFIXED (widget));
272
273 myfixed = GTK_MYFIXED (widget);
274
275 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
276
277 attributes.window_type = GDK_WINDOW_CHILD;
278 attributes.x = widget->allocation.x;
279 attributes.y = widget->allocation.y;
280 attributes.width = 32000;
281 attributes.height = 32000;
282 attributes.wclass = GDK_INPUT_OUTPUT;
283 attributes.visual = gtk_widget_get_visual (widget);
284 attributes.colormap = gtk_widget_get_colormap (widget);
285 attributes.event_mask = gtk_widget_get_events (widget);
286 attributes.event_mask |=
287 GDK_EXPOSURE_MASK |
288 GDK_POINTER_MOTION_MASK |
289 GDK_POINTER_MOTION_HINT_MASK |
290 GDK_BUTTON_MOTION_MASK |
291 GDK_BUTTON1_MOTION_MASK |
292 GDK_BUTTON2_MOTION_MASK |
293 GDK_BUTTON3_MOTION_MASK |
294 GDK_BUTTON_PRESS_MASK |
295 GDK_BUTTON_RELEASE_MASK |
296 GDK_KEY_PRESS_MASK |
297 GDK_KEY_RELEASE_MASK |
298 GDK_ENTER_NOTIFY_MASK |
299 GDK_LEAVE_NOTIFY_MASK |
300 GDK_FOCUS_CHANGE_MASK;
301
302 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
303
304 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes,
305 attributes_mask);
306 gdk_window_set_user_data (widget->window, widget);
307
308 widget->style = gtk_style_attach (widget->style, widget->window);
309 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
310 }
311
312 static void
313 gtk_myfixed_size_request (GtkWidget *widget,
314 GtkRequisition *requisition)
315 {
316 GtkMyFixed *myfixed;
317 GtkMyFixedChild *child;
318 GList *children;
319
320 g_return_if_fail (widget != NULL);
321 g_return_if_fail (GTK_IS_MYFIXED (widget));
322 g_return_if_fail (requisition != NULL);
323
324 myfixed = GTK_MYFIXED (widget);
325
326 requisition->width = 0;
327 requisition->height = 0;
328
329 children = myfixed->children;
330 while (children)
331 {
332 child = children->data;
333 children = children->next;
334
335 if (GTK_WIDGET_VISIBLE (child->widget))
336 {
337 gtk_widget_size_request (child->widget, &child->widget->requisition);
338 }
339 }
340 }
341
342 static void
343 gtk_myfixed_size_allocate (GtkWidget *widget,
344 GtkAllocation *allocation)
345 {
346 GtkMyFixed *myfixed;
347 GtkMyFixedChild *child;
348 GtkAllocation child_allocation;
349 GList *children;
350 guint16 border_width;
351
352 g_return_if_fail (widget != NULL);
353 g_return_if_fail (GTK_IS_MYFIXED(widget));
354 g_return_if_fail (allocation != NULL);
355
356 myfixed = GTK_MYFIXED (widget);
357
358 widget->allocation = *allocation;
359 if (GTK_WIDGET_REALIZED (widget))
360 gdk_window_move_resize (widget->window, allocation->x, allocation->y, 32000, 32000 );
361
362 border_width = GTK_CONTAINER (myfixed)->border_width;
363
364 children = myfixed->children;
365 while (children)
366 {
367 child = children->data;
368 children = children->next;
369
370 if (GTK_WIDGET_VISIBLE (child->widget))
371 {
372 child_allocation.x = child->x + border_width;
373 child_allocation.y = child->y + border_width;
374 child_allocation.width = child->widget->requisition.width;
375 child_allocation.height = child->widget->requisition.height;
376 gtk_widget_size_allocate (child->widget, &child_allocation);
377 }
378 }
379 }
380
381 static void
382 gtk_myfixed_paint (GtkWidget *widget,
383 GdkRectangle *area)
384 {
385 g_return_if_fail (widget != NULL);
386 g_return_if_fail (GTK_IS_MYFIXED (widget));
387 g_return_if_fail (area != NULL);
388
389 if (GTK_WIDGET_DRAWABLE (widget))
390 gdk_window_clear_area (widget->window,
391 area->x, area->y,
392 area->width, area->height);
393 }
394
395 static void
396 gtk_myfixed_draw (GtkWidget *widget,
397 GdkRectangle *area)
398 {
399 GtkMyFixed *myfixed;
400 GtkMyFixedChild *child;
401 GdkRectangle child_area;
402 GList *children;
403
404 g_return_if_fail (widget != NULL);
405 g_return_if_fail (GTK_IS_MYFIXED (widget));
406
407 if (GTK_WIDGET_DRAWABLE (widget))
408 {
409 myfixed = GTK_MYFIXED (widget);
410 gtk_myfixed_paint (widget, area);
411
412 children = myfixed->children;
413 while (children)
414 {
415 child = children->data;
416 children = children->next;
417
418 if (gtk_widget_intersect (child->widget, area, &child_area))
419 gtk_widget_draw (child->widget, &child_area);
420 }
421 }
422 }
423
424 static gint
425 gtk_myfixed_expose (GtkWidget *widget,
426 GdkEventExpose *event)
427 {
428 GtkMyFixed *myfixed;
429 GtkMyFixedChild *child;
430 GdkEventExpose child_event;
431 GList *children;
432
433 g_return_val_if_fail (widget != NULL, FALSE);
434 g_return_val_if_fail (GTK_IS_MYFIXED (widget), FALSE);
435 g_return_val_if_fail (event != NULL, FALSE);
436
437 if (GTK_WIDGET_DRAWABLE (widget))
438 {
439 myfixed = GTK_MYFIXED (widget);
440
441 child_event = *event;
442
443 children = myfixed->children;
444 while (children)
445 {
446 child = children->data;
447 children = children->next;
448
449 if (GTK_WIDGET_NO_WINDOW (child->widget) &&
450 gtk_widget_intersect (child->widget, &event->area,
451 &child_event.area))
452 gtk_widget_event (child->widget, (GdkEvent*) &child_event);
453 }
454 }
455
456 return FALSE;
457 }
458
459 static void
460 gtk_myfixed_add (GtkContainer *container,
461 GtkWidget *widget)
462 {
463 g_return_if_fail (container != NULL);
464 g_return_if_fail (GTK_IS_MYFIXED (container));
465 g_return_if_fail (widget != NULL);
466
467 gtk_myfixed_put (GTK_MYFIXED (container), widget, 0, 0);
468 }
469
470 static void
471 gtk_myfixed_remove (GtkContainer *container,
472 GtkWidget *widget)
473 {
474 GtkMyFixed *myfixed;
475 GtkMyFixedChild *child;
476 GList *children;
477
478 g_return_if_fail (container != NULL);
479 g_return_if_fail (GTK_IS_MYFIXED (container));
480 g_return_if_fail (widget != NULL);
481
482 myfixed = GTK_MYFIXED (container);
483
484 children = myfixed->children;
485 while (children)
486 {
487 child = children->data;
488
489 if (child->widget == widget)
490 {
491 gtk_widget_unparent (widget);
492
493 myfixed->children = g_list_remove_link (myfixed->children, children);
494 g_list_free (children);
495 g_free (child);
496
497 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
498 gtk_widget_queue_resize (GTK_WIDGET (container));
499
500 break;
501 }
502
503 children = children->next;
504 }
505 }
506
507 static void
508 gtk_myfixed_foreach (GtkContainer *container,
509 #if (GTK_MINOR_VERSION > 0)
510 gboolean include_internals,
511 #endif
512 GtkCallback callback,
513 gpointer callback_data)
514 {
515 GtkMyFixed *myfixed;
516 GtkMyFixedChild *child;
517 GList *children;
518
519 g_return_if_fail (container != NULL);
520 g_return_if_fail (GTK_IS_MYFIXED (container));
521 g_return_if_fail (callback != NULL);
522
523 myfixed = GTK_MYFIXED (container);
524
525 children = myfixed->children;
526 while (children)
527 {
528 child = children->data;
529 children = children->next;
530
531 (* callback) (child->widget, callback_data);
532 }
533 }
534
535
536 #ifdef __cplusplus
537 }
538 #endif /* __cplusplus */
539