2004-01-22 20:17:34 +00:00
|
|
|
<chapter id="gtk-migrating-checklist">
|
|
|
|
<title>Migration Checklist</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
This chapter includes a checklist of things you need to do to
|
|
|
|
ensure that your programs are good citizens in the GTK+ world. By
|
|
|
|
paying attention to the points in the checklist, you ensure that
|
|
|
|
many automatic features of GTK+ will work correctly in your
|
|
|
|
program.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<section id="checklist-popup-menu">
|
|
|
|
<title>Implement GtkWidget::popup_menu</title>
|
|
|
|
|
|
|
|
<formalpara>
|
|
|
|
<title>Why</title>
|
|
|
|
<para>
|
|
|
|
By handling this signal, you let widgets have
|
|
|
|
context-sensitive menus that can be invoked with the standard
|
|
|
|
key bindings.
|
|
|
|
</para>
|
|
|
|
</formalpara>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The <link
|
|
|
|
linkend="GtkWidget-popup-menu">GtkWidget::popup_menu</link>
|
|
|
|
signal instructs the widget for which it is emitted to create a
|
|
|
|
context-sensitive popup menu. By default, the <link
|
|
|
|
linkend="gtk-bindings">key binding mechanism</link> is set to
|
|
|
|
emit this signal when the
|
|
|
|
<keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
|
|
|
|
or <keycap>Menu</keycap> keys are pressed while a widget has the
|
|
|
|
focus. If a widget in your application shows a popup menu when
|
|
|
|
you press a mouse button, you can make it work as well through
|
|
|
|
the normal key binding mechanism in the following fahion:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<orderedlist>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Write a function to create and show a popup menu. This
|
|
|
|
function needs to know the button number and the event's
|
|
|
|
time to pass them to gtk_menu_popup(). You can implement
|
|
|
|
such a function like this:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting id="do_popup_menu">
|
|
|
|
static void
|
|
|
|
do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
|
|
|
|
{
|
|
|
|
GtkWidget *menu;
|
|
|
|
int button, event_time;
|
|
|
|
|
2005-05-16 19:34:39 +00:00
|
|
|
menu = gtk_menu_new (<!-- -->);
|
2004-01-22 20:17:34 +00:00
|
|
|
g_signal_connect (menu, "deactivate",
|
|
|
|
G_CALLBACK (gtk_widget_destroy), NULL);
|
|
|
|
|
|
|
|
/* ... add menu items ... */
|
|
|
|
|
|
|
|
if (event)
|
|
|
|
{
|
|
|
|
button = event->button;
|
|
|
|
event_time = event->time;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
button = 0;
|
2005-05-16 19:34:39 +00:00
|
|
|
event_time = gtk_get_current_event_time (<!-- -->);
|
2004-01-22 20:17:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
|
|
|
|
button, event_time);
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
In your button_press handler, call this function when you
|
|
|
|
need to pop up a menu:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
static gboolean
|
|
|
|
my_widget_button_press_event_handler (GtkWidget *widget, GdkEventButton *event)
|
|
|
|
{
|
|
|
|
/* Ignore double-clicks and triple-clicks */
|
|
|
|
if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
|
|
|
|
{
|
|
|
|
do_popup_menu (widget, event);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Implement a handler for the popup_menu signal:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting>
|
|
|
|
static gboolean
|
|
|
|
my_widget_popup_menu_handler (GtkWidget *widget)
|
|
|
|
{
|
|
|
|
do_popup_menu (widget, NULL);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</listitem>
|
|
|
|
</orderedlist>
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
If you do not pass a positioning function to gtk_menu_popup(),
|
|
|
|
it will show the menu at the mouse position by default. This
|
|
|
|
is what you usually want when the menu is shown as a result of
|
|
|
|
pressing a mouse button. However, if you press the
|
|
|
|
<keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
|
|
|
|
or <keycap>Menu</keycap> keys while the widget is focused, the
|
|
|
|
mouse cursor may not be near the widget at all. In the <link
|
|
|
|
linkend="do_popup_menu">example above</link>, you may want to
|
|
|
|
provide your own <link
|
|
|
|
linkend="GtkMenuPositionFunc">menu-positioning function</link>
|
|
|
|
in the case where the <parameter>event</parameter> is
|
|
|
|
<constant>NULL</constant>. This function should compute the
|
|
|
|
desired position for a menu when it is invoked through the
|
2005-05-16 19:34:39 +00:00
|
|
|
keyboard. For example, #GtkEntry aligns the
|
2004-01-22 20:44:38 +00:00
|
|
|
top edge of its popup menu with the bottom edge of the entry.
|
2004-01-22 20:17:34 +00:00
|
|
|
</para>
|
|
|
|
</note>
|
2004-01-23 16:43:27 +00:00
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
For the standard key bindings to work, your widget must be
|
|
|
|
able to take the keyboard focus. In general, widgets should
|
|
|
|
be fully usable through the keyboard and not just the mouse.
|
|
|
|
The very first step of this is to ensure that your widget
|
2005-05-16 19:34:39 +00:00
|
|
|
turns on the %GTK_CAN_FOCUS <link
|
|
|
|
linkend="gtkwidgetflags">flag</link>.
|
2004-01-23 16:43:27 +00:00
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
</section>
|
|
|
|
|
|
|
|
<section id="checklist-gdkeventexpose-region">
|
|
|
|
<title>Use GdkEventExpose.region</title>
|
|
|
|
|
|
|
|
<formalpara>
|
|
|
|
<title>Why</title>
|
|
|
|
<para>
|
|
|
|
The <structfield>region</structfield> field of
|
|
|
|
<structname>GdkEventExpose</structname> allows you to redraw
|
|
|
|
less than the traditional
|
|
|
|
<structfield>GdkEventRegion.area</structfield>.
|
|
|
|
</para>
|
|
|
|
</formalpara>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
In GTK+ 1.x, the <structname>GdkEventExpose</structname>
|
|
|
|
structure only had an <structfield>area</structfield> field to
|
|
|
|
let you determine the region that you needed to redraw. In GTK+
|
|
|
|
2.x, this field exists for compatibility and as a simple
|
|
|
|
interface. However, there is also a
|
|
|
|
<structfield>region</structfield> field which contains a
|
|
|
|
fine-grained region. The <structfield>area</structfield> field
|
|
|
|
is simply the bounding rectangle of the
|
|
|
|
<structfield>region</structfield>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Widgets that are very expensive to re-render, such as an image
|
|
|
|
editor, may prefer to use the
|
|
|
|
<structfield>GdkEventExpose.region</structfield> field to paint
|
|
|
|
as little as possible. Widgets that just use a few drawing
|
|
|
|
primitives, such as labels and buttons, may prefer to use the
|
|
|
|
traditional <structfield>GdkEventExpose.area</structfield> field
|
|
|
|
for simplicity.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Regions have an internal representation that is accessible as a
|
|
|
|
list of rectangles. To turn the
|
|
|
|
<structfield>GdkEventExpose.region</structfield> field into such
|
|
|
|
a list, use gdk_region_get_rectangles():
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting id="gdkregion-get-rectangles">
|
|
|
|
static gboolean
|
|
|
|
my_widget_expose_event_handler (GtkWidget *widget, GdkEventExpose *event)
|
|
|
|
{
|
|
|
|
GdkRectangle *rects;
|
|
|
|
int n_rects;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
gdk_region_get_rectangles (event->region, &rects, &n_rects);
|
|
|
|
|
|
|
|
for (i = 0; i < n_rects; i++)
|
|
|
|
{
|
|
|
|
/* Repaint rectangle: (rects[i].x, rects[i].y),
|
|
|
|
* (rects[i].width, rects[i].height)
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (rects);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
</programlisting>
|
2004-01-22 20:17:34 +00:00
|
|
|
</section>
|
2004-02-16 19:00:16 +00:00
|
|
|
|
|
|
|
<section id="checklist-modifiers">
|
|
|
|
<title>Test for modifier keys correctly</title>
|
|
|
|
|
|
|
|
<formalpara>
|
|
|
|
<title>Why</title>
|
|
|
|
<para>
|
2004-02-16 19:55:18 +00:00
|
|
|
With
|
2005-05-16 19:34:39 +00:00
|
|
|
gtk_accelerator_get_default_mod_mask()
|
2004-02-16 19:55:18 +00:00
|
|
|
you can test for modifier keys reliably; this way your key
|
|
|
|
event handlers will work correctly even if
|
|
|
|
<keycap>NumLock</keycap> or <keycap>CapsLock</keycap> are
|
|
|
|
activated.
|
2004-02-16 19:00:16 +00:00
|
|
|
</para>
|
|
|
|
</formalpara>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
In a <structname>GdkEventKey</structname>, the
|
|
|
|
<structfield>state</structfield> field is a bit mask which
|
|
|
|
indicates the modifier state at the time the key was pressed.
|
2004-02-16 19:55:18 +00:00
|
|
|
Modifiers are keys like <keycap>Control</keycap> and
|
2004-02-16 19:00:16 +00:00
|
|
|
<keycap>NumLock</keycap>. When implementing a <link
|
|
|
|
linkend="GtkWidget-key-press-event">GtkWidget::key_press_event</link>
|
2005-05-16 19:34:39 +00:00
|
|
|
handler, you should use gtk_accelerator_get_default_mod_mask() to
|
2004-02-16 19:55:18 +00:00
|
|
|
test against modifier keys. This function returns a bit mask
|
|
|
|
which encompasses all the modifiers which the user may be
|
|
|
|
actively pressing, such as <keycap>Control</keycap>,
|
|
|
|
<keycap>Shift</keycap>, and <keycap>Alt</keycap>, but ignores
|
2004-02-16 19:00:16 +00:00
|
|
|
"inocuous" modifiers such as <keycap>NumLock</keycap> and
|
2004-02-16 19:55:18 +00:00
|
|
|
<keycap>CapsLock</keycap>.
|
2004-02-16 19:00:16 +00:00
|
|
|
</para>
|
|
|
|
|
2004-02-16 19:55:18 +00:00
|
|
|
<para>
|
|
|
|
Say you want to see if
|
|
|
|
<keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
|
|
|
|
was pressed. Doing a simple test like
|
2004-02-18 02:54:11 +00:00
|
|
|
<literal>event->keysym == GDK_F10 &&
|
2004-02-16 19:55:18 +00:00
|
|
|
event->state == GDK_CONTROL_MASK</literal> is not
|
|
|
|
enough. If <keycap>CapsLock</keycap> is pressed, then
|
|
|
|
<structfield>event->state</structfield> will be equal to
|
|
|
|
<literal>GDK_CONTROL_MASK | GDK_LOCK_MASK</literal>, and the
|
|
|
|
simple test will fail. By taking the logical-and of
|
|
|
|
<structfield>event->state</structfield> and
|
2005-05-16 19:34:39 +00:00
|
|
|
gtk_accelerator_get_default_mod_mask(), you
|
2004-02-16 19:55:18 +00:00
|
|
|
can ignore the modifiers which are not actively pressed by the
|
|
|
|
user at the same time as the base key.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The following example correctly tests for
|
|
|
|
<keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
|
|
|
|
being pressed.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting id="default-mod-mask">
|
2004-02-16 19:00:16 +00:00
|
|
|
static gboolean
|
2004-02-16 19:55:18 +00:00
|
|
|
my_widget_key_press_event_handler (GtkWidget *widget, GdkEventKey *event)
|
2004-02-16 19:00:16 +00:00
|
|
|
{
|
2004-02-16 19:55:18 +00:00
|
|
|
guint modifiers;
|
|
|
|
|
2005-05-16 19:34:39 +00:00
|
|
|
modifiers = gtk_accelerator_get_default_mod_mask (<!-- -->);
|
2004-02-16 19:55:18 +00:00
|
|
|
|
2004-02-16 19:00:16 +00:00
|
|
|
if (event->keysym == GDK_F10
|
2004-02-16 19:55:18 +00:00
|
|
|
&& (event->state & modifiers) == GDK_CONTROL_MASK)
|
2004-02-16 19:00:16 +00:00
|
|
|
{
|
|
|
|
g_print ("Control-F10 was pressed\n");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</section>
|
2005-05-18 06:13:42 +00:00
|
|
|
|
|
|
|
<section id="checklist-named-icons">
|
|
|
|
<title>Use named icons</title>
|
|
|
|
|
|
|
|
<formalpara>
|
|
|
|
<title>Why</title>
|
|
|
|
<para>
|
|
|
|
Named icons automatically adapt to theme changes, giving your
|
|
|
|
application a much more integrated appearance.
|
|
|
|
</para>
|
|
|
|
</formalpara>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Since GTK+ 2.6, named icons can be used for window icons (see
|
|
|
|
gtk_window_set_icon_name()) and images (see gtk_image_set_icon_name()).
|
|
|
|
In GTK+ 2.8, you can also use named icons for drag-and-drop (see
|
|
|
|
gtk_drag_source_set_icon_name()) and in treeview cells (see the
|
|
|
|
<link linkend="GtkCellRendererPixbuf--icon-name">icon_name</link>
|
|
|
|
property of #GtkCellRendererPixbuf).
|
|
|
|
</para>
|
2005-05-18 14:34:32 +00:00
|
|
|
</section>
|
2004-01-22 20:17:34 +00:00
|
|
|
</chapter>
|
|
|
|
|
|
|
|
<!--
|
|
|
|
Local variables:
|
|
|
|
mode: sgml
|
|
|
|
sgml-parent-document: ("gtk-docs.sgml" "book" "part" "chapter")
|
|
|
|
End:
|
|
|
|
-->
|