forked from AuroraMiddleware/gtk
310 lines
10 KiB
XML
310 lines
10 KiB
XML
<?xml version="1.0"?>
|
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
|
]>
|
|
<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 #GtkWidget::popup-menu 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;
|
|
|
|
menu = gtk_menu_new (<!-- -->);
|
|
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;
|
|
event_time = gtk_get_current_event_time (<!-- -->);
|
|
}
|
|
|
|
gtk_menu_attach_to_widget (GTK_MENU (menu), my_widget, NULL);
|
|
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
|
|
button, event_time);
|
|
}
|
|
</programlisting>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
In your #GtkWidget::button-press-event 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 #GtkWidget::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
|
|
%NULL. This function should compute the desired position for
|
|
a menu when it is invoked through the keyboard. For example,
|
|
#GtkEntry aligns the top edge of its popup menu with the bottom
|
|
edge of the entry.
|
|
</para>
|
|
</note>
|
|
|
|
<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
|
|
turns on the %GTK_CAN_FOCUS <link linkend="gtkwidgetflags">flag</link>.
|
|
</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 early GTK+ versions, the <structname>GdkEventExpose</structname>
|
|
structure only had an <structfield>area</structfield> field to
|
|
let you determine the region that you needed to redraw. In current
|
|
GTK+, this field still 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>
|
|
</section>
|
|
|
|
<section id="checklist-modifiers">
|
|
<title>Test for modifier keys correctly</title>
|
|
|
|
<formalpara>
|
|
<title>Why</title>
|
|
<para>
|
|
With gtk_accelerator_get_default_mod_mask() 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.
|
|
</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.
|
|
Modifiers are keys like <keycap>Control</keycap> and
|
|
<keycap>NumLock</keycap>. When implementing a
|
|
#GtkWidget::key-press-event handler, you should use
|
|
gtk_accelerator_get_default_mod_mask() to
|
|
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
|
|
"innocuous" modifiers such as <keycap>NumLock</keycap> and
|
|
<keycap>CapsLock</keycap>.
|
|
</para>
|
|
|
|
<para>
|
|
Say you want to see if
|
|
<keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
|
|
was pressed. Doing a simple test like
|
|
<literal>event->keysym == GDK_F10 &&
|
|
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
|
|
gtk_accelerator_get_default_mod_mask(), you
|
|
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">
|
|
static gboolean
|
|
my_widget_key_press_event_handler (GtkWidget *widget, GdkEventKey *event)
|
|
{
|
|
GdkModifierType modifiers;
|
|
|
|
modifiers = gtk_accelerator_get_default_mod_mask (<!-- -->);
|
|
|
|
if (event->keysym == GDK_F10
|
|
&& (event->state & modifiers) == GDK_CONTROL_MASK)
|
|
{
|
|
g_print ("Control-F10 was pressed\n");
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
</programlisting>
|
|
</section>
|
|
|
|
<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>
|
|
Named icons can be used for window icons (see gtk_window_set_icon_name())
|
|
and images (see gtk_image_set_icon_name()). You can also use named icons
|
|
for drag-and-drop (see gtk_drag_source_set_icon_name()) and in treeview
|
|
cells (see the #GtkCellRendererPixbuf:icon-name property).
|
|
</para>
|
|
</section>
|
|
</chapter>
|
|
|
|
<!--
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-parent-document: ("gtk-docs.sgml" "book" "part" "chapter")
|
|
End:
|
|
-->
|