1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * (C) 1998,1999 by Marcin Dalecki <[email protected]> 12 * 13 * Support for GTK+ 2 was added by: 14 * 15 * (C) 2002,2003 Jason Hildebrand <[email protected]> 16 * Daniel Elstner <[email protected]> 17 * 18 * This is a special purpose container widget, which manages arbitrary 19 * children at arbitrary positions width arbitrary sizes. This finally puts 20 * an end on our resize problems with which we where struggling for such a 21 * long time. 22 */ 23 24 #include "vim.h" 25 #include <gtk/gtk.h> /* without this it compiles, but gives errors at 26 runtime! */ 27 #include "gui_gtk_f.h" 28 #include <gtk/gtksignal.h> 29 #ifdef WIN3264 30 # include <gdk/gdkwin32.h> 31 #else 32 # include <gdk/gdkx.h> 33 #endif 34 35 typedef struct _GtkFormChild GtkFormChild; 36 37 struct _GtkFormChild 38 { 39 GtkWidget *widget; 40 GdkWindow *window; 41 gint x; /* relative subwidget x position */ 42 gint y; /* relative subwidget y position */ 43 gint mapped; 44 }; 45 46 47 static void gtk_form_class_init(GtkFormClass *klass); 48 static void gtk_form_init(GtkForm *form); 49 50 static void gtk_form_realize(GtkWidget *widget); 51 static void gtk_form_unrealize(GtkWidget *widget); 52 static void gtk_form_map(GtkWidget *widget); 53 static void gtk_form_size_request(GtkWidget *widget, 54 GtkRequisition *requisition); 55 static void gtk_form_size_allocate(GtkWidget *widget, 56 GtkAllocation *allocation); 57 static gint gtk_form_expose(GtkWidget *widget, 58 GdkEventExpose *event); 59 60 static void gtk_form_remove(GtkContainer *container, 61 GtkWidget *widget); 62 static void gtk_form_forall(GtkContainer *container, 63 gboolean include_internals, 64 GtkCallback callback, 65 gpointer callback_data); 66 67 static void gtk_form_attach_child_window(GtkForm *form, 68 GtkFormChild *child); 69 static void gtk_form_realize_child(GtkForm *form, 70 GtkFormChild *child); 71 static void gtk_form_position_child(GtkForm *form, 72 GtkFormChild *child, 73 gboolean force_allocate); 74 static void gtk_form_position_children(GtkForm *form); 75 76 static GdkFilterReturn gtk_form_filter(GdkXEvent *gdk_xevent, 77 GdkEvent *event, 78 gpointer data); 79 static GdkFilterReturn gtk_form_main_filter(GdkXEvent *gdk_xevent, 80 GdkEvent *event, 81 gpointer data); 82 83 static void gtk_form_set_static_gravity(GdkWindow *window, 84 gboolean use_static); 85 86 static void gtk_form_send_configure(GtkForm *form); 87 88 static void gtk_form_child_map(GtkWidget *widget, gpointer user_data); 89 static void gtk_form_child_unmap(GtkWidget *widget, gpointer user_data); 90 91 static GtkWidgetClass *parent_class = NULL; 92 93 /* Public interface 94 */ 95 96 GtkWidget * 97 gtk_form_new(void) 98 { 99 GtkForm *form; 100 101 form = gtk_type_new(gtk_form_get_type()); 102 103 return GTK_WIDGET(form); 104 } 105 106 void 107 gtk_form_put(GtkForm *form, 108 GtkWidget *child_widget, 109 gint x, 110 gint y) 111 { 112 GtkFormChild *child; 113 114 g_return_if_fail(GTK_IS_FORM(form)); 115 116 /* LINTED: avoid warning: conversion to 'unsigned long' */ 117 child = g_new(GtkFormChild, 1); 118 119 child->widget = child_widget; 120 child->window = NULL; 121 child->x = x; 122 child->y = y; 123 child->widget->requisition.width = 0; 124 child->widget->requisition.height = 0; 125 child->mapped = FALSE; 126 127 form->children = g_list_append(form->children, child); 128 129 /* child->window must be created and attached to the widget _before_ 130 * it has been realized, or else things will break with GTK2. Note 131 * that gtk_widget_set_parent() realizes the widget if it's visible 132 * and its parent is mapped. 133 */ 134 if (GTK_WIDGET_REALIZED(form)) 135 gtk_form_attach_child_window(form, child); 136 137 gtk_widget_set_parent(child_widget, GTK_WIDGET(form)); 138 gtk_widget_size_request(child->widget, NULL); 139 140 if (GTK_WIDGET_REALIZED(form) && !GTK_WIDGET_REALIZED(child_widget)) 141 gtk_form_realize_child(form, child); 142 143 gtk_form_position_child(form, child, TRUE); 144 } 145 146 void 147 gtk_form_move(GtkForm *form, 148 GtkWidget *child_widget, 149 gint x, 150 gint y) 151 { 152 GList *tmp_list; 153 GtkFormChild *child; 154 155 g_return_if_fail(GTK_IS_FORM(form)); 156 157 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next) 158 { 159 child = tmp_list->data; 160 if (child->widget == child_widget) 161 { 162 child->x = x; 163 child->y = y; 164 165 gtk_form_position_child(form, child, TRUE); 166 return; 167 } 168 } 169 } 170 171 void 172 gtk_form_freeze(GtkForm *form) 173 { 174 g_return_if_fail(GTK_IS_FORM(form)); 175 176 ++form->freeze_count; 177 } 178 179 void 180 gtk_form_thaw(GtkForm *form) 181 { 182 g_return_if_fail(GTK_IS_FORM(form)); 183 184 if (form->freeze_count) 185 { 186 if (!(--form->freeze_count)) 187 { 188 gtk_form_position_children(form); 189 gtk_widget_queue_draw(GTK_WIDGET(form)); 190 } 191 } 192 } 193 194 /* Basic Object handling procedures 195 */ 196 GtkType 197 gtk_form_get_type(void) 198 { 199 static GtkType form_type = 0; 200 201 if (!form_type) 202 { 203 GtkTypeInfo form_info; 204 205 vim_memset(&form_info, 0, sizeof(form_info)); 206 form_info.type_name = "GtkForm"; 207 form_info.object_size = sizeof(GtkForm); 208 form_info.class_size = sizeof(GtkFormClass); 209 form_info.class_init_func = (GtkClassInitFunc)gtk_form_class_init; 210 form_info.object_init_func = (GtkObjectInitFunc)gtk_form_init; 211 212 form_type = gtk_type_unique(GTK_TYPE_CONTAINER, &form_info); 213 } 214 return form_type; 215 } 216 217 static void 218 gtk_form_class_init(GtkFormClass *klass) 219 { 220 GtkWidgetClass *widget_class; 221 GtkContainerClass *container_class; 222 223 widget_class = (GtkWidgetClass *) klass; 224 container_class = (GtkContainerClass *) klass; 225 226 parent_class = gtk_type_class(gtk_container_get_type()); 227 228 widget_class->realize = gtk_form_realize; 229 widget_class->unrealize = gtk_form_unrealize; 230 widget_class->map = gtk_form_map; 231 widget_class->size_request = gtk_form_size_request; 232 widget_class->size_allocate = gtk_form_size_allocate; 233 widget_class->expose_event = gtk_form_expose; 234 235 container_class->remove = gtk_form_remove; 236 container_class->forall = gtk_form_forall; 237 } 238 239 static void 240 gtk_form_init(GtkForm *form) 241 { 242 form->children = NULL; 243 244 form->width = 1; 245 form->height = 1; 246 247 form->bin_window = NULL; 248 249 form->configure_serial = 0; 250 form->visibility = GDK_VISIBILITY_PARTIAL; 251 252 form->freeze_count = 0; 253 } 254 255 /* 256 * Widget methods 257 */ 258 259 static void 260 gtk_form_realize(GtkWidget *widget) 261 { 262 GList *tmp_list; 263 GtkForm *form; 264 GdkWindowAttr attributes; 265 gint attributes_mask; 266 267 g_return_if_fail(GTK_IS_FORM(widget)); 268 269 form = GTK_FORM(widget); 270 GTK_WIDGET_SET_FLAGS(form, GTK_REALIZED); 271 272 attributes.window_type = GDK_WINDOW_CHILD; 273 attributes.x = widget->allocation.x; 274 attributes.y = widget->allocation.y; 275 attributes.width = widget->allocation.width; 276 attributes.height = widget->allocation.height; 277 attributes.wclass = GDK_INPUT_OUTPUT; 278 attributes.visual = gtk_widget_get_visual(widget); 279 attributes.colormap = gtk_widget_get_colormap(widget); 280 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; 281 282 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; 283 284 widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), 285 &attributes, attributes_mask); 286 gdk_window_set_user_data(widget->window, widget); 287 288 attributes.x = 0; 289 attributes.y = 0; 290 attributes.event_mask = gtk_widget_get_events(widget); 291 292 form->bin_window = gdk_window_new(widget->window, 293 &attributes, attributes_mask); 294 gdk_window_set_user_data(form->bin_window, widget); 295 296 gtk_form_set_static_gravity(form->bin_window, TRUE); 297 298 widget->style = gtk_style_attach(widget->style, widget->window); 299 gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); 300 gtk_style_set_background(widget->style, form->bin_window, GTK_STATE_NORMAL); 301 302 gdk_window_add_filter(widget->window, gtk_form_main_filter, form); 303 gdk_window_add_filter(form->bin_window, gtk_form_filter, form); 304 305 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next) 306 { 307 GtkFormChild *child = tmp_list->data; 308 309 gtk_form_attach_child_window(form, child); 310 311 if (GTK_WIDGET_VISIBLE(child->widget)) 312 gtk_form_realize_child(form, child); 313 } 314 } 315 316 317 /* After reading the documentation at 318 * http://developer.gnome.org/doc/API/2.0/gtk/gtk-changes-2-0.html 319 * I think it should be possible to remove this function when compiling 320 * against gtk-2.0. It doesn't seem to cause problems, though. 321 * 322 * Well, I reckon at least the gdk_window_show(form->bin_window) 323 * is necessary. GtkForm is anything but a usual container widget. 324 */ 325 static void 326 gtk_form_map(GtkWidget *widget) 327 { 328 GList *tmp_list; 329 GtkForm *form; 330 331 g_return_if_fail(GTK_IS_FORM(widget)); 332 333 form = GTK_FORM(widget); 334 335 GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED); 336 337 gdk_window_show(widget->window); 338 gdk_window_show(form->bin_window); 339 340 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next) 341 { 342 GtkFormChild *child = tmp_list->data; 343 344 if (GTK_WIDGET_VISIBLE(child->widget) 345 && !GTK_WIDGET_MAPPED(child->widget)) 346 gtk_widget_map(child->widget); 347 } 348 } 349 350 static void 351 gtk_form_unrealize(GtkWidget *widget) 352 { 353 GList *tmp_list; 354 GtkForm *form; 355 356 g_return_if_fail(GTK_IS_FORM(widget)); 357 358 form = GTK_FORM(widget); 359 360 tmp_list = form->children; 361 362 gdk_window_set_user_data(form->bin_window, NULL); 363 gdk_window_destroy(form->bin_window); 364 form->bin_window = NULL; 365 366 while (tmp_list) 367 { 368 GtkFormChild *child = tmp_list->data; 369 370 if (child->window != NULL) 371 { 372 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget), 373 GTK_SIGNAL_FUNC(gtk_form_child_map), 374 child); 375 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget), 376 GTK_SIGNAL_FUNC(gtk_form_child_unmap), 377 child); 378 379 gdk_window_set_user_data(child->window, NULL); 380 gdk_window_destroy(child->window); 381 382 child->window = NULL; 383 } 384 385 tmp_list = tmp_list->next; 386 } 387 388 if (GTK_WIDGET_CLASS (parent_class)->unrealize) 389 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); 390 } 391 392 static void 393 gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition) 394 { 395 GList *tmp_list; 396 GtkForm *form; 397 398 g_return_if_fail(GTK_IS_FORM(widget)); 399 400 form = GTK_FORM(widget); 401 402 requisition->width = form->width; 403 requisition->height = form->height; 404 405 tmp_list = form->children; 406 407 while (tmp_list) 408 { 409 GtkFormChild *child = tmp_list->data; 410 gtk_widget_size_request(child->widget, NULL); 411 tmp_list = tmp_list->next; 412 } 413 } 414 415 static void 416 gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation) 417 { 418 GList *tmp_list; 419 GtkForm *form; 420 gboolean need_reposition; 421 422 g_return_if_fail(GTK_IS_FORM(widget)); 423 424 if (widget->allocation.x == allocation->x 425 && widget->allocation.y == allocation->y 426 && widget->allocation.width == allocation->width 427 && widget->allocation.height == allocation->height) 428 return; 429 430 need_reposition = widget->allocation.width != allocation->width 431 || widget->allocation.height != allocation->height; 432 form = GTK_FORM(widget); 433 434 if (need_reposition) 435 { 436 tmp_list = form->children; 437 438 while (tmp_list) 439 { 440 GtkFormChild *child = tmp_list->data; 441 gtk_form_position_child(form, child, TRUE); 442 443 tmp_list = tmp_list->next; 444 } 445 } 446 447 if (GTK_WIDGET_REALIZED(widget)) 448 { 449 gdk_window_move_resize(widget->window, 450 allocation->x, allocation->y, 451 allocation->width, allocation->height); 452 gdk_window_move_resize(GTK_FORM(widget)->bin_window, 453 0, 0, 454 allocation->width, allocation->height); 455 } 456 widget->allocation = *allocation; 457 if (need_reposition) 458 gtk_form_send_configure(form); 459 } 460 461 static gint 462 gtk_form_expose(GtkWidget *widget, GdkEventExpose *event) 463 { 464 GList *tmp_list; 465 GtkForm *form; 466 467 g_return_val_if_fail(GTK_IS_FORM(widget), FALSE); 468 469 form = GTK_FORM(widget); 470 471 if (event->window == form->bin_window) 472 return FALSE; 473 474 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next) 475 { 476 GtkFormChild *formchild = tmp_list->data; 477 GtkWidget *child = formchild->widget; 478 /* 479 * The following chunk of code is taken from gtkcontainer.c. The 480 * gtk1.x code synthesized expose events directly on the child widgets, 481 * which can't be done in gtk2 482 */ 483 if (GTK_WIDGET_DRAWABLE(child) && GTK_WIDGET_NO_WINDOW(child) 484 && child->window == event->window) 485 { 486 GdkEventExpose child_event; 487 child_event = *event; 488 489 child_event.region = gtk_widget_region_intersect(child, event->region); 490 if (!gdk_region_empty(child_event.region)) 491 { 492 gdk_region_get_clipbox(child_event.region, &child_event.area); 493 gtk_widget_send_expose(child, (GdkEvent *)&child_event); 494 } 495 } 496 } 497 498 return FALSE; 499 } 500 501 /* Container method 502 */ 503 static void 504 gtk_form_remove(GtkContainer *container, GtkWidget *widget) 505 { 506 GList *tmp_list; 507 GtkForm *form; 508 GtkFormChild *child = NULL; /* init for gcc */ 509 510 g_return_if_fail(GTK_IS_FORM(container)); 511 512 form = GTK_FORM(container); 513 514 tmp_list = form->children; 515 while (tmp_list) 516 { 517 child = tmp_list->data; 518 if (child->widget == widget) 519 break; 520 tmp_list = tmp_list->next; 521 } 522 523 if (tmp_list) 524 { 525 if (child->window) 526 { 527 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget), 528 GTK_SIGNAL_FUNC(>k_form_child_map), child); 529 gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget), 530 GTK_SIGNAL_FUNC(>k_form_child_unmap), child); 531 532 /* FIXME: This will cause problems for reparenting NO_WINDOW 533 * widgets out of a GtkForm 534 */ 535 gdk_window_set_user_data(child->window, NULL); 536 gdk_window_destroy(child->window); 537 } 538 gtk_widget_unparent(widget); 539 540 form->children = g_list_remove_link(form->children, tmp_list); 541 g_list_free_1(tmp_list); 542 g_free(child); 543 } 544 } 545 546 static void 547 gtk_form_forall(GtkContainer *container, 548 gboolean include_internals UNUSED, 549 GtkCallback callback, 550 gpointer callback_data) 551 { 552 GtkForm *form; 553 GtkFormChild *child; 554 GList *tmp_list; 555 556 g_return_if_fail(GTK_IS_FORM(container)); 557 g_return_if_fail(callback != NULL); 558 559 form = GTK_FORM(container); 560 561 tmp_list = form->children; 562 while (tmp_list) 563 { 564 child = tmp_list->data; 565 tmp_list = tmp_list->next; 566 567 (*callback) (child->widget, callback_data); 568 } 569 } 570 571 /* Operations on children 572 */ 573 574 static void 575 gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child) 576 { 577 if (child->window != NULL) 578 return; /* been there, done that */ 579 580 if (GTK_WIDGET_NO_WINDOW(child->widget)) 581 { 582 GtkWidget *widget; 583 GdkWindowAttr attributes; 584 gint attributes_mask; 585 586 widget = GTK_WIDGET(form); 587 588 attributes.window_type = GDK_WINDOW_CHILD; 589 attributes.x = child->x; 590 attributes.y = child->y; 591 attributes.width = child->widget->requisition.width; 592 attributes.height = child->widget->requisition.height; 593 attributes.wclass = GDK_INPUT_OUTPUT; 594 attributes.visual = gtk_widget_get_visual(widget); 595 attributes.colormap = gtk_widget_get_colormap(widget); 596 attributes.event_mask = GDK_EXPOSURE_MASK; 597 598 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; 599 child->window = gdk_window_new(form->bin_window, 600 &attributes, attributes_mask); 601 gdk_window_set_user_data(child->window, widget); 602 603 gtk_style_set_background(widget->style, 604 child->window, 605 GTK_STATE_NORMAL); 606 607 gtk_widget_set_parent_window(child->widget, child->window); 608 gtk_form_set_static_gravity(child->window, TRUE); 609 /* 610 * Install signal handlers to map/unmap child->window 611 * alongside with the actual widget. 612 */ 613 gtk_signal_connect(GTK_OBJECT(child->widget), "map", 614 GTK_SIGNAL_FUNC(>k_form_child_map), child); 615 gtk_signal_connect(GTK_OBJECT(child->widget), "unmap", 616 GTK_SIGNAL_FUNC(>k_form_child_unmap), child); 617 } 618 else if (!GTK_WIDGET_REALIZED(child->widget)) 619 { 620 gtk_widget_set_parent_window(child->widget, form->bin_window); 621 } 622 } 623 624 static void 625 gtk_form_realize_child(GtkForm *form, GtkFormChild *child) 626 { 627 gtk_form_attach_child_window(form, child); 628 gtk_widget_realize(child->widget); 629 630 if (child->window == NULL) /* might be already set, see above */ 631 gtk_form_set_static_gravity(child->widget->window, TRUE); 632 } 633 634 static void 635 gtk_form_position_child(GtkForm *form, GtkFormChild *child, 636 gboolean force_allocate) 637 { 638 gint x; 639 gint y; 640 641 x = child->x; 642 y = child->y; 643 644 if ((x >= G_MINSHORT) && (x <= G_MAXSHORT) && 645 (y >= G_MINSHORT) && (y <= G_MAXSHORT)) 646 { 647 if (!child->mapped) 648 { 649 if (GTK_WIDGET_MAPPED(form) && GTK_WIDGET_VISIBLE(child->widget)) 650 { 651 if (!GTK_WIDGET_MAPPED(child->widget)) 652 gtk_widget_map(child->widget); 653 654 child->mapped = TRUE; 655 force_allocate = TRUE; 656 } 657 } 658 659 if (force_allocate) 660 { 661 GtkAllocation allocation; 662 663 if (GTK_WIDGET_NO_WINDOW(child->widget)) 664 { 665 if (child->window) 666 { 667 gdk_window_move_resize(child->window, 668 x, y, 669 child->widget->requisition.width, 670 child->widget->requisition.height); 671 } 672 673 allocation.x = 0; 674 allocation.y = 0; 675 } 676 else 677 { 678 allocation.x = x; 679 allocation.y = y; 680 } 681 682 allocation.width = child->widget->requisition.width; 683 allocation.height = child->widget->requisition.height; 684 685 gtk_widget_size_allocate(child->widget, &allocation); 686 } 687 } 688 else 689 { 690 if (child->mapped) 691 { 692 child->mapped = FALSE; 693 694 if (GTK_WIDGET_MAPPED(child->widget)) 695 gtk_widget_unmap(child->widget); 696 } 697 } 698 } 699 700 static void 701 gtk_form_position_children(GtkForm *form) 702 { 703 GList *tmp_list; 704 705 for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next) 706 gtk_form_position_child(form, tmp_list->data, FALSE); 707 } 708 709 /* Callbacks */ 710 711 /* The main event filter. Actually, we probably don't really need 712 * to install this as a filter at all, since we are calling it 713 * directly above in the expose-handling hack. 714 * 715 * This routine identifies expose events that are generated when 716 * we've temporarily moved the bin_window_origin, and translates 717 * them or discards them, depending on whether we are obscured 718 * or not. 719 */ 720 static GdkFilterReturn 721 gtk_form_filter(GdkXEvent *gdk_xevent, GdkEvent *event UNUSED, gpointer data) 722 { 723 XEvent *xevent; 724 GtkForm *form; 725 726 xevent = (XEvent *) gdk_xevent; 727 form = GTK_FORM(data); 728 729 switch (xevent->type) 730 { 731 case Expose: 732 if (xevent->xexpose.serial == form->configure_serial) 733 { 734 if (form->visibility == GDK_VISIBILITY_UNOBSCURED) 735 return GDK_FILTER_REMOVE; 736 else 737 break; 738 } 739 break; 740 741 case ConfigureNotify: 742 if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0)) 743 form->configure_serial = xevent->xconfigure.serial; 744 break; 745 } 746 747 return GDK_FILTER_CONTINUE; 748 } 749 750 /* Although GDK does have a GDK_VISIBILITY_NOTIFY event, 751 * there is no corresponding event in GTK, so we have 752 * to get the events from a filter 753 */ 754 static GdkFilterReturn 755 gtk_form_main_filter(GdkXEvent *gdk_xevent, 756 GdkEvent *event UNUSED, 757 gpointer data) 758 { 759 XEvent *xevent; 760 GtkForm *form; 761 762 xevent = (XEvent *) gdk_xevent; 763 form = GTK_FORM(data); 764 765 if (xevent->type == VisibilityNotify) 766 { 767 switch (xevent->xvisibility.state) 768 { 769 case VisibilityFullyObscured: 770 form->visibility = GDK_VISIBILITY_FULLY_OBSCURED; 771 break; 772 773 case VisibilityPartiallyObscured: 774 form->visibility = GDK_VISIBILITY_PARTIAL; 775 break; 776 777 case VisibilityUnobscured: 778 form->visibility = GDK_VISIBILITY_UNOBSCURED; 779 break; 780 } 781 782 return GDK_FILTER_REMOVE; 783 } 784 return GDK_FILTER_CONTINUE; 785 } 786 787 static void 788 gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static) 789 { 790 /* We don't check if static gravity is actually supported, because it 791 * results in an annoying assertion error message. */ 792 gdk_window_set_static_gravities(window, use_static); 793 } 794 795 void 796 gtk_form_move_resize(GtkForm *form, GtkWidget *widget, 797 gint x, gint y, gint w, gint h) 798 { 799 widget->requisition.width = w; 800 widget->requisition.height = h; 801 802 gtk_form_move(form, widget, x, y); 803 } 804 805 static void 806 gtk_form_send_configure(GtkForm *form) 807 { 808 GtkWidget *widget; 809 GdkEventConfigure event; 810 811 widget = GTK_WIDGET(form); 812 813 event.type = GDK_CONFIGURE; 814 event.window = widget->window; 815 event.x = widget->allocation.x; 816 event.y = widget->allocation.y; 817 event.width = widget->allocation.width; 818 event.height = widget->allocation.height; 819 820 gtk_main_do_event((GdkEvent*)&event); 821 } 822 823 static void 824 gtk_form_child_map(GtkWidget *widget UNUSED, gpointer user_data) 825 { 826 GtkFormChild *child; 827 828 child = (GtkFormChild *)user_data; 829 830 child->mapped = TRUE; 831 gdk_window_show(child->window); 832 } 833 834 static void 835 gtk_form_child_unmap(GtkWidget *widget UNUSED, gpointer user_data) 836 { 837 GtkFormChild *child; 838 839 child = (GtkFormChild *)user_data; 840 841 child->mapped = FALSE; 842 gdk_window_hide(child->window); 843 } 844 845