Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Gtk+/Gnome Application Development
Prev Home Next

Realization and Mapping

If you aren't familiar with the concept of realizing and mapping a widget, go back and read the section called Realizing, Mapping, and Showing in the chapter called GTK+ Basics before reading this section.

GtkEv does not override the map or unmap method; the default GtkWidget methods suffice. The defaults set and unset the GTK_WIDGET_MAPPED flag, and show or hide widget->window.

Any widget with a GdkWindow that has GtkWidget as its immediate parent will need to override the realize method; the default is only suitable for windowless widgets. GtkEv is no exception. GtkEv also overrides the unrealize method, in order to destroy the event window.

Here is GtkEv's realize method:


static void 
gtk_ev_realize        (GtkWidget        *widget)
{
  GdkWindowAttr attributes;
  gint attributes_mask;
  GtkEv* ev;
  GdkCursor* cursor;

  g_return_if_fail(widget != NULL);
  g_return_if_fail(GTK_IS_EV(widget));

  ev = GTK_EV(widget);

  /* Set realized flag */

  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);

  /* Main widget window */

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = widget->allocation.x;
  attributes.y = widget->allocation.y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;

  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                   &attributes, attributes_mask);
  gdk_window_set_user_data (widget->window, widget);

  /* Event window */

  cursor = gdk_cursor_new(GDK_CROSSHAIR);

  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.x = ev->event_window_rect.x;
  attributes.y = ev->event_window_rect.y;
  attributes.width = ev->event_window_rect.width;
  attributes.height = ev->event_window_rect.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
  attributes.event_mask = GDK_ALL_EVENTS_MASK;
  attributes.cursor = cursor;

  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | 
    GDK_WA_COLORMAP | GDK_WA_CURSOR;

  ev->event_window = gdk_window_new (widget->window,
                                     &attributes, attributes_mask);
  gdk_window_set_user_data (ev->event_window, widget);

  gdk_window_show(ev->event_window);

  gdk_cursor_destroy(cursor);

  /* Style */

  widget->style = gtk_style_attach (widget->style, widget->window);

  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);

  gdk_window_set_background (ev->event_window, 
                             &widget->style->base[GTK_STATE_NORMAL]);
}
      

The first step in any realize method is to set the GTK_REALIZED flag; this is a small but important detail. After that, most of the realize method is concerned with creating the two GdkWindows, as described in the section called GdkWindow in the chapter called GDK Basics. widget->window should be created as a subwindow of the widget's parent's GdkWindow; the parent window is obtained with gtk_widget_get_parent_window().

Notice that all events are requested on the event window, for obvious reasons. Also, the event window has a special cursor, to give the user visual feedback when the pointer moves into it. The client-side cursor handle is destroyed immediately after attaching the cursor to the window; the X server will keep it around as long as it's in use.

After creating each GdkWindow, a pointer to the GtkEv is stored in the GdkWindow's "user data" field. GTK+ uses the contents of this field to determine which widget should receive events that occur on the window. Recall that GTK+ receives a stream of events from GDK, and that each GdkEvent has a window field indicating the GdkWindow that received it. GTK+ forwards each event to the widget owning the event's GdkWindow. (the section called Events in the chapter called GDK Basics details this process if you don't remember.)

The code calls gdk_window_show() on the event window but not widget->window; widget->window should not be shown until the widget is mapped. Because the event window is a child of widget->window, it will remain offscreen until its parent is shown. Alternatively, GtkEv could implement a map method to show the child, but this way seems simpler.

All widgets must take create their associated GtkStyle in their realize method, because a style contains X resources. (See the section called GtkStyle and Themes in the chapter called GDK Basics for more information about GtkStyle.) Recall from the section called Realizing, Mapping, and Showing in the chapter called GTK+ Basics that widgets allocate all X resources in their realize method. GTK+ provides a simple function to create a widget's style:


  widget->style = gtk_style_attach (widget->style, widget->window);

      

After filling in widget->style, GtkEv uses colors from the style to set window backgrounds. It sets the main window's background using gtk_style_set_background(), which could do almost anything (it might invoke a routine from a dynamically loaded theme module). If the default theme is running, it simply sets the window's background to an appropriate color or pixmap tile. There is no special style function to set the background of the event window, so we set it to the "base" color (the base color is white by default; it's the background color for lists and text entries). Selecting a color from the style means that users will be able to customize the widget's color. It's also convenient to avoid allocating and deallocating a custom color.

Notice that the realize method does not chain up to the default realize method, because the default isn't appropriate for GtkEv.

Unrealizing GtkEv is relatively simple:


static void 
gtk_ev_unrealize (GtkWidget        *widget)
{
  GtkEv* ev;

  g_return_if_fail(widget != NULL);
  g_return_if_fail(GTK_IS_EV(widget));

  ev = GTK_EV(widget);

  /* Hide all windows */

  if (GTK_WIDGET_MAPPED (widget))
    gtk_widget_unmap (widget);
  
  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);

  /* Destroy our child window */

  if (ev->event_window)
    {
      gdk_window_set_user_data(ev->event_window, NULL);
      gdk_window_destroy(ev->event_window);
      ev->event_window = NULL;
    }

  /* This destroys widget->window and unsets the realized flag
   */
  if (GTK_WIDGET_CLASS(parent_class)->unrealize)
    (* GTK_WIDGET_CLASS(parent_class)->unrealize) (widget);
}
      

First, the unrealize method ensures that the widget is unmapped. This is essential: GTK+ maintains the invariant that mapped widgets are also realized. Next, the unrealize method destroys the event window. It sets the window's user data to NULL before destroying it; otherwise GtkEv would receive a useless destroy event. Finally, GtkEv chains up to the default unrealize method, which unsets the GTK_WIDGET_REALIZED flag and destroys widget->window. Unrealize implemenations are required to chain up to their base class's implementation.

When writing your realize and unrealize methods, keep in mind that they can be called multiple times, but they are always paired. That is, a widget can be unrealized and re-realized over and over, but it will never be realized twice without an intervening unrealize. The pairing is guaranteed; that is, if a widget is realized it will definitely be unrealized sooner or later, unless the program exits.

Gtk+/Gnome Application Development
Prev Home Next

 
 
  Published under free license. Design by Interspire