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