]> Pileus Git - ~andy/gtk/blob - docs/reference/gtk/migrating-checklist.sgml
Rearrange migration chapter a bit
[~andy/gtk] / docs / reference / gtk / migrating-checklist.sgml
1 <?xml version="1.0"?>
2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
3                "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
4 ]>
5 <chapter id="gtk-migrating-checklist">
6   <title>Migration Details Checklist</title>
7
8   <para>
9     This chapter includes a checklist of smaller things you need to do to
10     ensure that your programs are good citizens in the GTK+ world.  By
11     paying attention to the points in the checklist, you ensure that
12     many automatic features of GTK+ will work correctly in your
13     program.
14   </para>
15
16   <section id="checklist-popup-menu">
17     <title>Implement GtkWidget::popup_menu</title>
18
19     <formalpara>
20       <title>Why</title>
21       <para>
22         By handling this signal, you let widgets have
23         context-sensitive menus that can be invoked with the standard
24         key bindings.
25       </para>
26     </formalpara>
27
28     <para>
29       The #GtkWidget::popup-menu signal instructs the widget for which
30       it is emitted to create a context-sensitive popup menu. By default,
31       the <link linkend="gtk-bindings">key binding mechanism</link> is set to
32       emit this signal when the
33       <keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
34       or <keycap>Menu</keycap> keys are pressed while a widget has the
35       focus.  If a widget in your application shows a popup menu when
36       you press a mouse button, you can make it work as well through
37       the normal key binding mechanism in the following fahion:
38     </para>
39
40     <orderedlist>
41       <listitem>
42         <para>
43           Write a function to create and show a popup menu.  This
44           function needs to know the button number and the event's
45           time to pass them to gtk_menu_popup().  You can implement
46           such a function like this:
47         </para>
48
49         <programlisting id="do_popup_menu">
50 static void
51 do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
52 {
53   GtkWidget *menu;
54   int button, event_time;
55
56   menu = gtk_menu_new (<!-- -->);
57   g_signal_connect (menu, "deactivate",
58                     G_CALLBACK (gtk_widget_destroy), NULL);
59
60   /* ... add menu items ... */
61
62   if (event)
63     {
64       button = event->button;
65       event_time = event->time;
66     }
67   else
68     {
69       button = 0;
70       event_time = gtk_get_current_event_time (<!-- -->);
71     }
72
73   gtk_menu_attach_to_widget (GTK_MENU (menu), my_widget, NULL);
74   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
75                   button, event_time);
76 }
77         </programlisting>
78       </listitem>
79
80       <listitem>
81         <para>
82           In your #GtkWidget::button-press-event handler, call this function
83           when you need to pop up a menu:
84         </para>
85
86         <programlisting>
87 static gboolean
88 my_widget_button_press_event_handler (GtkWidget *widget, GdkEventButton *event)
89 {
90   /* Ignore double-clicks and triple-clicks */
91   if (event->button == 3 &amp;&amp; event->type == GDK_BUTTON_PRESS)
92     {
93       do_popup_menu (widget, event);
94       return TRUE;
95     }
96
97   return FALSE;
98 }
99         </programlisting>
100       </listitem>
101
102       <listitem>
103         <para>
104           Implement a handler for the #GtkWidget::popup-menu signal:
105         </para>
106
107         <programlisting>
108 static gboolean
109 my_widget_popup_menu_handler (GtkWidget *widget)
110 {
111   do_popup_menu (widget, NULL);
112   return TRUE;
113 }
114         </programlisting>
115       </listitem>
116     </orderedlist>
117
118     <note>
119       <para>
120         If you do not pass a positioning function to gtk_menu_popup(),
121         it will show the menu at the mouse position by default.  This
122         is what you usually want when the menu is shown as a result of
123         pressing a mouse button.  However, if you press the
124         <keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
125         or <keycap>Menu</keycap> keys while the widget is focused, the
126         mouse cursor may not be near the widget at all.  In the <link
127         linkend="do_popup_menu">example above</link>, you may want to
128         provide your own <link
129         linkend="GtkMenuPositionFunc">menu-positioning function</link>
130         in the case where the <parameter>event</parameter> is
131         %NULL.  This function should compute the desired position for
132         a menu when it is invoked through the keyboard.  For example,
133         #GtkEntry aligns the top edge of its popup menu with the bottom
134         edge of the entry.
135       </para>
136     </note>
137
138     <note>
139       <para>
140         For the standard key bindings to work, your widget must be
141         able to take the keyboard focus.  In general, widgets should
142         be fully usable through the keyboard and not just the mouse.
143         The very first step of this is to ensure that your widget
144         turns on the %GTK_CAN_FOCUS <link linkend="gtkwidgetflags">flag</link>.
145       </para>
146     </note>
147   </section>
148
149   <section id="checklist-gdkeventexpose-region">
150     <title>Use GdkEventExpose.region</title>
151
152     <formalpara>
153       <title>Why</title>
154       <para>
155         The <structfield>region</structfield> field of
156         <structname>GdkEventExpose</structname> allows you to redraw
157         less than the traditional <structfield>GdkEventRegion.area</structfield>.
158       </para>
159     </formalpara>
160
161     <para>
162       In early GTK+ versions, the <structname>GdkEventExpose</structname>
163       structure only had an <structfield>area</structfield> field to
164       let you determine the region that you needed to redraw. In current
165       GTK+, this field still exists for compatibility and as a simple
166       interface. However, there is also a <structfield>region</structfield>
167       field which contains a fine-grained region. The
168       <structfield>area</structfield> field is simply the bounding rectangle
169       of the <structfield>region</structfield>.
170     </para>
171
172     <para>
173       Widgets that are very expensive to re-render, such as an image
174       editor, may prefer to use the
175       <structfield>GdkEventExpose.region</structfield> field to paint
176       as little as possible.  Widgets that just use a few drawing
177       primitives, such as labels and buttons, may prefer to use the
178       traditional <structfield>GdkEventExpose.area</structfield> field
179       for simplicity.
180     </para>
181
182     <para>
183       Regions have an internal representation that is accessible as a
184       list of rectangles.  To turn the
185       <structfield>GdkEventExpose.region</structfield> field into such
186       a list, use gdk_region_get_rectangles():
187     </para>
188
189     <programlisting id="gdkregion-get-rectangles">
190 static gboolean
191 my_widget_expose_event_handler (GtkWidget *widget, GdkEventExpose *event)
192 {
193   GdkRectangle *rects;
194   int n_rects;
195   int i;
196
197   gdk_region_get_rectangles (event-&gt;region, &amp;rects, &amp;n_rects);
198
199   for (i = 0; i &lt; n_rects; i++)
200     {
201       /* Repaint rectangle: (rects[i].x, rects[i].y),
202        *                    (rects[i].width, rects[i].height)
203        */
204     }
205
206   g_free (rects);
207
208   return FALSE;
209 }
210     </programlisting>
211   </section>
212
213   <section id="checklist-modifiers">
214     <title>Test for modifier keys correctly</title>
215
216     <formalpara>
217       <title>Why</title>
218       <para>
219         With gtk_accelerator_get_default_mod_mask() you can test for
220         modifier keys reliably; this way your key event handlers will
221         work correctly even if <keycap>NumLock</keycap> or
222         <keycap>CapsLock</keycap> are activated.
223       </para>
224     </formalpara>
225
226     <para>
227       In a <structname>GdkEventKey</structname>, the
228       <structfield>state</structfield> field is a bit mask which
229       indicates the modifier state at the time the key was pressed.
230       Modifiers are keys like <keycap>Control</keycap> and
231       <keycap>NumLock</keycap>.  When implementing a
232       #GtkWidget::key-press-event handler, you should use
233       gtk_accelerator_get_default_mod_mask() to
234       test against modifier keys.  This function returns a bit mask
235       which encompasses all the modifiers which the user may be
236       actively pressing, such as <keycap>Control</keycap>,
237       <keycap>Shift</keycap>, and <keycap>Alt</keycap>, but ignores
238       "innocuous" modifiers such as <keycap>NumLock</keycap> and
239       <keycap>CapsLock</keycap>.
240     </para>
241
242     <para>
243       Say you want to see if
244       <keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
245       was pressed.  Doing a simple test like
246       <literal>event-&gt;keysym&nbsp;==&nbsp;GDK_F10 &amp;&amp;
247       event->state&nbsp;==&nbsp;GDK_CONTROL_MASK</literal> is not
248       enough.  If <keycap>CapsLock</keycap> is pressed, then
249       <structfield>event-&gt;state</structfield> will be equal to
250       <literal>GDK_CONTROL_MASK | GDK_LOCK_MASK</literal>, and the
251       simple test will fail.  By taking the logical-and of
252       <structfield>event->state</structfield> and
253       gtk_accelerator_get_default_mod_mask(), you
254       can ignore the modifiers which are not actively pressed by the
255       user at the same time as the base key.
256     </para>
257
258     <para>
259       The following example correctly tests for
260       <keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
261       being pressed.
262     </para>
263
264     <programlisting id="default-mod-mask">
265 static gboolean
266 my_widget_key_press_event_handler (GtkWidget *widget, GdkEventKey *event)
267 {
268   GdkModifierType modifiers;
269
270   modifiers = gtk_accelerator_get_default_mod_mask (<!-- -->);
271
272   if (event-&gt;keysym == GDK_F10
273       &amp;&amp; (event-&gt;state &amp; modifiers) == GDK_CONTROL_MASK)
274     {
275       g_print ("Control-F10 was pressed\n");
276       return TRUE;
277     }
278
279   return FALSE;
280 }
281     </programlisting>
282   </section>
283
284   <section id="checklist-named-icons">
285     <title>Use named icons</title>
286
287     <formalpara>
288       <title>Why</title>
289       <para>
290         Named icons automatically adapt to theme changes, giving your
291         application a much more integrated appearance.
292       </para>
293     </formalpara>
294
295     <para>
296       Named icons can be used for window icons (see gtk_window_set_icon_name())
297       and images (see gtk_image_set_icon_name()). You can also use named icons
298       for drag-and-drop (see gtk_drag_source_set_icon_name()) and in treeview
299       cells (see the #GtkCellRendererPixbuf:icon-name property).
300     </para>
301   </section>
302 </chapter>
303
304 <!--
305 Local variables:
306 mode: sgml
307 sgml-parent-document: ("gtk-docs.sgml" "book" "part" "chapter")
308 End:
309 -->