1 <chapter id="gtk-migrating-checklist">
2 <title>Migration Checklist</title>
5 This chapter includes a checklist of things you need to do to
6 ensure that your programs are good citizens in the GTK+ world. By
7 paying attention to the points in the checklist, you ensure that
8 many automatic features of GTK+ will work correctly in your
12 <section id="checklist-popup-menu">
13 <title>Implement GtkWidget::popup_menu</title>
18 By handling this signal, you let widgets have
19 context-sensitive menus that can be invoked with the standard
26 linkend="GtkWidget-popup-menu">GtkWidget::popup_menu</link>
27 signal instructs the widget for which it is emitted to create a
28 context-sensitive popup menu. By default, the <link
29 linkend="gtk-bindings">key binding mechanism</link> is set to
30 emit this signal when the
31 <keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
32 or <keycap>Menu</keycap> keys are pressed while a widget has the
33 focus. If a widget in your application shows a popup menu when
34 you press a mouse button, you can make it work as well through
35 the normal key binding mechanism in the following fahion:
41 Write a function to create and show a popup menu. This
42 function needs to know the button number and the event's
43 time to pass them to gtk_menu_popup(). You can implement
44 such a function like this:
47 <programlisting id="do_popup_menu">
49 do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
52 int button, event_time;
54 menu = gtk_menu_new ();
55 g_signal_connect (menu, "deactivate",
56 G_CALLBACK (gtk_widget_destroy), NULL);
58 /* ... add menu items ... */
62 button = event->button;
63 event_time = event->time;
68 event_time = gtk_get_current_event_time ();
71 gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
79 In your button_press handler, call this function when you
80 need to pop up a menu:
85 my_widget_button_press_event_handler (GtkWidget *widget, GdkEventButton *event)
87 /* Ignore double-clicks and triple-clicks */
88 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
90 do_popup_menu (widget, event);
101 Implement a handler for the popup_menu signal:
106 my_widget_popup_menu_handler (GtkWidget *widget)
108 do_popup_menu (widget, NULL);
117 If you do not pass a positioning function to gtk_menu_popup(),
118 it will show the menu at the mouse position by default. This
119 is what you usually want when the menu is shown as a result of
120 pressing a mouse button. However, if you press the
121 <keycombo><keycap>Shift</keycap><keycap>F10</keycap></keycombo>
122 or <keycap>Menu</keycap> keys while the widget is focused, the
123 mouse cursor may not be near the widget at all. In the <link
124 linkend="do_popup_menu">example above</link>, you may want to
125 provide your own <link
126 linkend="GtkMenuPositionFunc">menu-positioning function</link>
127 in the case where the <parameter>event</parameter> is
128 <constant>NULL</constant>. This function should compute the
129 desired position for a menu when it is invoked through the
130 keyboard. For example, <xref linkend="GtkEntry"/> aligns the
131 top edge of its popup menu with the bottom edge of the entry.
137 For the standard key bindings to work, your widget must be
138 able to take the keyboard focus. In general, widgets should
139 be fully usable through the keyboard and not just the mouse.
140 The very first step of this is to ensure that your widget
142 linkend="gtkwidgetflags"><constant>GTK_CAN_FOCUS</constant></link>
148 <section id="checklist-gdkeventexpose-region">
149 <title>Use GdkEventExpose.region</title>
154 The <structfield>region</structfield> field of
155 <structname>GdkEventExpose</structname> allows you to redraw
156 less than the traditional
157 <structfield>GdkEventRegion.area</structfield>.
162 In GTK+ 1.x, 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 GTK+
165 2.x, this field exists for compatibility and as a simple
166 interface. However, there is also a
167 <structfield>region</structfield> field which contains a
168 fine-grained region. The <structfield>area</structfield> field
169 is simply the bounding rectangle of the
170 <structfield>region</structfield>.
174 Widgets that are very expensive to re-render, such as an image
175 editor, may prefer to use the
176 <structfield>GdkEventExpose.region</structfield> field to paint
177 as little as possible. Widgets that just use a few drawing
178 primitives, such as labels and buttons, may prefer to use the
179 traditional <structfield>GdkEventExpose.area</structfield> field
184 Regions have an internal representation that is accessible as a
185 list of rectangles. To turn the
186 <structfield>GdkEventExpose.region</structfield> field into such
187 a list, use gdk_region_get_rectangles():
190 <programlisting id="gdkregion-get-rectangles">
192 my_widget_expose_event_handler (GtkWidget *widget, GdkEventExpose *event)
198 gdk_region_get_rectangles (event->region, &rects, &n_rects);
200 for (i = 0; i < n_rects; i++)
202 /* Repaint rectangle: (rects[i].x, rects[i].y),
203 * (rects[i].width, rects[i].height)
214 <section id="checklist-modifiers">
215 <title>Test for modifier keys correctly</title>
221 <function>gtk_accelerator_get_default_mod_mask()</function>
222 you can test for modifier keys reliably; this way your key
223 event handlers will work correctly even if
224 <keycap>NumLock</keycap> or <keycap>CapsLock</keycap> are
230 In a <structname>GdkEventKey</structname>, the
231 <structfield>state</structfield> field is a bit mask which
232 indicates the modifier state at the time the key was pressed.
233 Modifiers are keys like <keycap>Control</keycap> and
234 <keycap>NumLock</keycap>. When implementing a <link
235 linkend="GtkWidget-key-press-event">GtkWidget::key_press_event</link>
236 handler, you should use
237 <function>gtk_accelerator_get_default_mod_mask()</function> to
238 test against modifier keys. This function returns a bit mask
239 which encompasses all the modifiers which the user may be
240 actively pressing, such as <keycap>Control</keycap>,
241 <keycap>Shift</keycap>, and <keycap>Alt</keycap>, but ignores
242 "inocuous" modifiers such as <keycap>NumLock</keycap> and
243 <keycap>CapsLock</keycap>.
247 Say you want to see if
248 <keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
249 was pressed. Doing a simple test like
250 <literal>event->keysym == GDK_F10 &&
251 event->state == GDK_CONTROL_MASK</literal> is not
252 enough. If <keycap>CapsLock</keycap> is pressed, then
253 <structfield>event->state</structfield> will be equal to
254 <literal>GDK_CONTROL_MASK | GDK_LOCK_MASK</literal>, and the
255 simple test will fail. By taking the logical-and of
256 <structfield>event->state</structfield> and
257 <function>gtk_accelerator_get_default_mod_mask()</function>, you
258 can ignore the modifiers which are not actively pressed by the
259 user at the same time as the base key.
263 The following example correctly tests for
264 <keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
268 <programlisting id="default-mod-mask">
270 my_widget_key_press_event_handler (GtkWidget *widget, GdkEventKey *event)
274 modifiers = gtk_accelerator_get_default_mod_mask ();
276 if (event->keysym == GDK_F10
277 && (event->state & modifiers) == GDK_CONTROL_MASK)
279 g_print ("Control-F10 was pressed\n");
292 sgml-parent-document: ("gtk-docs.sgml" "book" "part" "chapter")