1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.IMContext;
26 
27 private import gdk.Window;
28 private import glib.Str;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 private import gtk.c.functions;
32 public  import gtk.c.types;
33 public  import gtkc.gtktypes;
34 private import pango.PgAttributeList;
35 private import std.algorithm;
36 
37 
38 /**
39  * #GtkIMContext defines the interface for GTK+ input methods. An input method
40  * is used by GTK+ text input widgets like #GtkEntry to map from key events to
41  * Unicode character strings.
42  * 
43  * The default input method can be set programmatically via the
44  * #GtkSettings:gtk-im-module GtkSettings property. Alternatively, you may set
45  * the GTK_IM_MODULE environment variable as documented in
46  * [Running GTK+ Applications][gtk-running].
47  * 
48  * The #GtkEntry #GtkEntry:im-module and #GtkTextView #GtkTextView:im-module
49  * properties may also be used to set input methods for specific widget
50  * instances. For instance, a certain entry widget might be expected to contain
51  * certain characters which would be easier to input with a certain input
52  * method.
53  * 
54  * An input method may consume multiple key events in sequence and finally
55  * output the composed result. This is called preediting, and an input method
56  * may provide feedback about this process by displaying the intermediate
57  * composition states as preedit text. For instance, the default GTK+ input
58  * method implements the input of arbitrary Unicode code points by holding down
59  * the Control and Shift keys and then typing “U” followed by the hexadecimal
60  * digits of the code point.  When releasing the Control and Shift keys,
61  * preediting ends and the character is inserted as text. Ctrl+Shift+u20AC for
62  * example results in the € sign.
63  * 
64  * Additional input methods can be made available for use by GTK+ widgets as
65  * loadable modules. An input method module is a small shared library which
66  * implements a subclass of #GtkIMContext or #GtkIMContextSimple and exports
67  * these four functions:
68  * 
69  * |[<!-- language="C" -->
70  * void im_module_init(GTypeModule *module);
71  * ]|
72  * This function should register the #GType of the #GtkIMContext subclass which
73  * implements the input method by means of g_type_module_register_type(). Note
74  * that g_type_register_static() cannot be used as the type needs to be
75  * registered dynamically.
76  * 
77  * |[<!-- language="C" -->
78  * void im_module_exit(void);
79  * ]|
80  * Here goes any cleanup code your input method might require on module unload.
81  * 
82  * |[<!-- language="C" -->
83  * void im_module_list(const GtkIMContextInfo ***contexts, int *n_contexts)
84  * {
85  * *contexts = info_list;
86  * *n_contexts = G_N_ELEMENTS (info_list);
87  * }
88  * ]|
89  * This function returns the list of input methods provided by the module. The
90  * example implementation above shows a common solution and simply returns a
91  * pointer to statically defined array of #GtkIMContextInfo items for each
92  * provided input method.
93  * 
94  * |[<!-- language="C" -->
95  * GtkIMContext * im_module_create(const gchar *context_id);
96  * ]|
97  * This function should return a pointer to a newly created instance of the
98  * #GtkIMContext subclass identified by @context_id. The context ID is the same
99  * as specified in the #GtkIMContextInfo array returned by im_module_list().
100  * 
101  * After a new loadable input method module has been installed on the system,
102  * the configuration file `gtk.immodules` needs to be
103  * regenerated by [gtk-query-immodules-3.0][gtk-query-immodules-3.0],
104  * in order for the new input method to become available to GTK+ applications.
105  */
106 public class IMContext : ObjectG
107 {
108 	/** the main Gtk struct */
109 	protected GtkIMContext* gtkIMContext;
110 
111 	/** Get the main Gtk struct */
112 	public GtkIMContext* getIMContextStruct(bool transferOwnership = false)
113 	{
114 		if (transferOwnership)
115 			ownedRef = false;
116 		return gtkIMContext;
117 	}
118 
119 	/** the main Gtk struct as a void* */
120 	protected override void* getStruct()
121 	{
122 		return cast(void*)gtkIMContext;
123 	}
124 
125 	protected override void setStruct(GObject* obj)
126 	{
127 		gtkIMContext = cast(GtkIMContext*)obj;
128 		super.setStruct(obj);
129 	}
130 
131 	/**
132 	 * Sets our main struct and passes it to the parent class.
133 	 */
134 	public this (GtkIMContext* gtkIMContext, bool ownedRef = false)
135 	{
136 		this.gtkIMContext = gtkIMContext;
137 		super(cast(GObject*)gtkIMContext, ownedRef);
138 	}
139 
140 
141 	/** */
142 	public static GType getType()
143 	{
144 		return gtk_im_context_get_type();
145 	}
146 
147 	/**
148 	 * Asks the widget that the input context is attached to to delete
149 	 * characters around the cursor position by emitting the
150 	 * GtkIMContext::delete_surrounding signal. Note that @offset and @n_chars
151 	 * are in characters not in bytes which differs from the usage other
152 	 * places in #GtkIMContext.
153 	 *
154 	 * In order to use this function, you should first call
155 	 * gtk_im_context_get_surrounding() to get the current context, and
156 	 * call this function immediately afterwards to make sure that you
157 	 * know what you are deleting. You should also account for the fact
158 	 * that even if the signal was handled, the input context might not
159 	 * have deleted all the characters that were requested to be deleted.
160 	 *
161 	 * This function is used by an input method that wants to make
162 	 * subsitutions in the existing text in response to new input. It is
163 	 * not useful for applications.
164 	 *
165 	 * Params:
166 	 *     offset = offset from cursor position in chars;
167 	 *         a negative value means start before the cursor.
168 	 *     nChars = number of characters to delete.
169 	 *
170 	 * Returns: %TRUE if the signal was handled.
171 	 */
172 	public bool deleteSurrounding(int offset, int nChars)
173 	{
174 		return gtk_im_context_delete_surrounding(gtkIMContext, offset, nChars) != 0;
175 	}
176 
177 	/**
178 	 * Allow an input method to internally handle key press and release
179 	 * events. If this function returns %TRUE, then no further processing
180 	 * should be done for this key event.
181 	 *
182 	 * Params:
183 	 *     event = the key event
184 	 *
185 	 * Returns: %TRUE if the input method handled the key event.
186 	 */
187 	public bool filterKeypress(GdkEventKey* event)
188 	{
189 		return gtk_im_context_filter_keypress(gtkIMContext, event) != 0;
190 	}
191 
192 	/**
193 	 * Notify the input method that the widget to which this
194 	 * input context corresponds has gained focus. The input method
195 	 * may, for example, change the displayed feedback to reflect
196 	 * this change.
197 	 */
198 	public void focusIn()
199 	{
200 		gtk_im_context_focus_in(gtkIMContext);
201 	}
202 
203 	/**
204 	 * Notify the input method that the widget to which this
205 	 * input context corresponds has lost focus. The input method
206 	 * may, for example, change the displayed feedback or reset the contexts
207 	 * state to reflect this change.
208 	 */
209 	public void focusOut()
210 	{
211 		gtk_im_context_focus_out(gtkIMContext);
212 	}
213 
214 	/**
215 	 * Retrieve the current preedit string for the input context,
216 	 * and a list of attributes to apply to the string.
217 	 * This string should be displayed inserted at the insertion
218 	 * point.
219 	 *
220 	 * Params:
221 	 *     str = location to store the retrieved
222 	 *         string. The string retrieved must be freed with g_free().
223 	 *     attrs = location to store the retrieved
224 	 *         attribute list.  When you are done with this list, you
225 	 *         must unreference it with pango_attr_list_unref().
226 	 *     cursorPos = location to store position of cursor (in characters)
227 	 *         within the preedit string.
228 	 */
229 	public void getPreeditString(out string str, out PgAttributeList attrs, out int cursorPos)
230 	{
231 		char* outstr = null;
232 		PangoAttrList* outattrs = null;
233 
234 		gtk_im_context_get_preedit_string(gtkIMContext, &outstr, &outattrs, &cursorPos);
235 
236 		str = Str.toString(outstr);
237 		attrs = ObjectG.getDObject!(PgAttributeList)(outattrs);
238 	}
239 
240 	/**
241 	 * Retrieves context around the insertion point. Input methods
242 	 * typically want context in order to constrain input text based on
243 	 * existing text; this is important for languages such as Thai where
244 	 * only some sequences of characters are allowed.
245 	 *
246 	 * This function is implemented by emitting the
247 	 * GtkIMContext::retrieve_surrounding signal on the input method; in
248 	 * response to this signal, a widget should provide as much context as
249 	 * is available, up to an entire paragraph, by calling
250 	 * gtk_im_context_set_surrounding(). Note that there is no obligation
251 	 * for a widget to respond to the ::retrieve_surrounding signal, so input
252 	 * methods must be prepared to function without context.
253 	 *
254 	 * Params:
255 	 *     text = location to store a UTF-8 encoded
256 	 *         string of text holding context around the insertion point.
257 	 *         If the function returns %TRUE, then you must free the result
258 	 *         stored in this location with g_free().
259 	 *     cursorIndex = location to store byte index of the insertion
260 	 *         cursor within @text.
261 	 *
262 	 * Returns: %TRUE if surrounding text was provided; in this case
263 	 *     you must free the result stored in *text.
264 	 */
265 	public bool getSurrounding(out string text, out int cursorIndex)
266 	{
267 		char* outtext = null;
268 
269 		auto p = gtk_im_context_get_surrounding(gtkIMContext, &outtext, &cursorIndex) != 0;
270 
271 		text = Str.toString(outtext);
272 
273 		return p;
274 	}
275 
276 	/**
277 	 * Notify the input method that a change such as a change in cursor
278 	 * position has been made. This will typically cause the input
279 	 * method to clear the preedit state.
280 	 */
281 	public void reset()
282 	{
283 		gtk_im_context_reset(gtkIMContext);
284 	}
285 
286 	/**
287 	 * Set the client window for the input context; this is the
288 	 * #GdkWindow in which the input appears. This window is
289 	 * used in order to correctly position status windows, and may
290 	 * also be used for purposes internal to the input method.
291 	 *
292 	 * Params:
293 	 *     window = the client window. This may be %NULL to indicate
294 	 *         that the previous client window no longer exists.
295 	 */
296 	public void setClientWindow(Window window)
297 	{
298 		gtk_im_context_set_client_window(gtkIMContext, (window is null) ? null : window.getWindowStruct());
299 	}
300 
301 	/**
302 	 * Notify the input method that a change in cursor
303 	 * position has been made. The location is relative to the client
304 	 * window.
305 	 *
306 	 * Params:
307 	 *     area = new location
308 	 */
309 	public void setCursorLocation(GdkRectangle* area)
310 	{
311 		gtk_im_context_set_cursor_location(gtkIMContext, area);
312 	}
313 
314 	/**
315 	 * Sets surrounding context around the insertion point and preedit
316 	 * string. This function is expected to be called in response to the
317 	 * GtkIMContext::retrieve_surrounding signal, and will likely have no
318 	 * effect if called at other times.
319 	 *
320 	 * Params:
321 	 *     text = text surrounding the insertion point, as UTF-8.
322 	 *         the preedit string should not be included within
323 	 *         @text.
324 	 *     len = the length of @text, or -1 if @text is nul-terminated
325 	 *     cursorIndex = the byte index of the insertion cursor within @text.
326 	 */
327 	public void setSurrounding(string text, int len, int cursorIndex)
328 	{
329 		gtk_im_context_set_surrounding(gtkIMContext, Str.toStringz(text), len, cursorIndex);
330 	}
331 
332 	/**
333 	 * Sets whether the IM context should use the preedit string
334 	 * to display feedback. If @use_preedit is FALSE (default
335 	 * is TRUE), then the IM context may use some other method to display
336 	 * feedback, such as displaying it in a child of the root window.
337 	 *
338 	 * Params:
339 	 *     usePreedit = whether the IM context should use the preedit string.
340 	 */
341 	public void setUsePreedit(bool usePreedit)
342 	{
343 		gtk_im_context_set_use_preedit(gtkIMContext, usePreedit);
344 	}
345 
346 	protected class OnCommitDelegateWrapper
347 	{
348 		void delegate(string, IMContext) dlg;
349 		gulong handlerId;
350 
351 		this(void delegate(string, IMContext) dlg)
352 		{
353 			this.dlg = dlg;
354 			onCommitListeners ~= this;
355 		}
356 
357 		void remove(OnCommitDelegateWrapper source)
358 		{
359 			foreach(index, wrapper; onCommitListeners)
360 			{
361 				if (wrapper.handlerId == source.handlerId)
362 				{
363 					onCommitListeners[index] = null;
364 					onCommitListeners = std.algorithm.remove(onCommitListeners, index);
365 					break;
366 				}
367 			}
368 		}
369 	}
370 	OnCommitDelegateWrapper[] onCommitListeners;
371 
372 	/**
373 	 * The ::commit signal is emitted when a complete input sequence
374 	 * has been entered by the user. This can be a single character
375 	 * immediately after a key press or the final result of preediting.
376 	 *
377 	 * Params:
378 	 *     str = the completed character(s) entered by the user
379 	 */
380 	gulong addOnCommit(void delegate(string, IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
381 	{
382 		auto wrapper = new OnCommitDelegateWrapper(dlg);
383 		wrapper.handlerId = Signals.connectData(
384 			this,
385 			"commit",
386 			cast(GCallback)&callBackCommit,
387 			cast(void*)wrapper,
388 			cast(GClosureNotify)&callBackCommitDestroy,
389 			connectFlags);
390 		return wrapper.handlerId;
391 	}
392 
393 	extern(C) static void callBackCommit(GtkIMContext* imcontextStruct, char* str, OnCommitDelegateWrapper wrapper)
394 	{
395 		wrapper.dlg(Str.toString(str), wrapper.outer);
396 	}
397 
398 	extern(C) static void callBackCommitDestroy(OnCommitDelegateWrapper wrapper, GClosure* closure)
399 	{
400 		wrapper.remove(wrapper);
401 	}
402 
403 	protected class OnDeleteSurroundingDelegateWrapper
404 	{
405 		bool delegate(int, int, IMContext) dlg;
406 		gulong handlerId;
407 
408 		this(bool delegate(int, int, IMContext) dlg)
409 		{
410 			this.dlg = dlg;
411 			onDeleteSurroundingListeners ~= this;
412 		}
413 
414 		void remove(OnDeleteSurroundingDelegateWrapper source)
415 		{
416 			foreach(index, wrapper; onDeleteSurroundingListeners)
417 			{
418 				if (wrapper.handlerId == source.handlerId)
419 				{
420 					onDeleteSurroundingListeners[index] = null;
421 					onDeleteSurroundingListeners = std.algorithm.remove(onDeleteSurroundingListeners, index);
422 					break;
423 				}
424 			}
425 		}
426 	}
427 	OnDeleteSurroundingDelegateWrapper[] onDeleteSurroundingListeners;
428 
429 	/**
430 	 * The ::delete-surrounding signal is emitted when the input method
431 	 * needs to delete all or part of the context surrounding the cursor.
432 	 *
433 	 * Params:
434 	 *     offset = the character offset from the cursor position of the text
435 	 *         to be deleted. A negative value indicates a position before
436 	 *         the cursor.
437 	 *     nChars = the number of characters to be deleted
438 	 *
439 	 * Returns: %TRUE if the signal was handled.
440 	 */
441 	gulong addOnDeleteSurrounding(bool delegate(int, int, IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
442 	{
443 		auto wrapper = new OnDeleteSurroundingDelegateWrapper(dlg);
444 		wrapper.handlerId = Signals.connectData(
445 			this,
446 			"delete-surrounding",
447 			cast(GCallback)&callBackDeleteSurrounding,
448 			cast(void*)wrapper,
449 			cast(GClosureNotify)&callBackDeleteSurroundingDestroy,
450 			connectFlags);
451 		return wrapper.handlerId;
452 	}
453 
454 	extern(C) static int callBackDeleteSurrounding(GtkIMContext* imcontextStruct, int offset, int nChars, OnDeleteSurroundingDelegateWrapper wrapper)
455 	{
456 		return wrapper.dlg(offset, nChars, wrapper.outer);
457 	}
458 
459 	extern(C) static void callBackDeleteSurroundingDestroy(OnDeleteSurroundingDelegateWrapper wrapper, GClosure* closure)
460 	{
461 		wrapper.remove(wrapper);
462 	}
463 
464 	protected class OnPreeditChangedDelegateWrapper
465 	{
466 		void delegate(IMContext) dlg;
467 		gulong handlerId;
468 
469 		this(void delegate(IMContext) dlg)
470 		{
471 			this.dlg = dlg;
472 			onPreeditChangedListeners ~= this;
473 		}
474 
475 		void remove(OnPreeditChangedDelegateWrapper source)
476 		{
477 			foreach(index, wrapper; onPreeditChangedListeners)
478 			{
479 				if (wrapper.handlerId == source.handlerId)
480 				{
481 					onPreeditChangedListeners[index] = null;
482 					onPreeditChangedListeners = std.algorithm.remove(onPreeditChangedListeners, index);
483 					break;
484 				}
485 			}
486 		}
487 	}
488 	OnPreeditChangedDelegateWrapper[] onPreeditChangedListeners;
489 
490 	/**
491 	 * The ::preedit-changed signal is emitted whenever the preedit sequence
492 	 * currently being entered has changed.  It is also emitted at the end of
493 	 * a preedit sequence, in which case
494 	 * gtk_im_context_get_preedit_string() returns the empty string.
495 	 */
496 	gulong addOnPreeditChanged(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
497 	{
498 		auto wrapper = new OnPreeditChangedDelegateWrapper(dlg);
499 		wrapper.handlerId = Signals.connectData(
500 			this,
501 			"preedit-changed",
502 			cast(GCallback)&callBackPreeditChanged,
503 			cast(void*)wrapper,
504 			cast(GClosureNotify)&callBackPreeditChangedDestroy,
505 			connectFlags);
506 		return wrapper.handlerId;
507 	}
508 
509 	extern(C) static void callBackPreeditChanged(GtkIMContext* imcontextStruct, OnPreeditChangedDelegateWrapper wrapper)
510 	{
511 		wrapper.dlg(wrapper.outer);
512 	}
513 
514 	extern(C) static void callBackPreeditChangedDestroy(OnPreeditChangedDelegateWrapper wrapper, GClosure* closure)
515 	{
516 		wrapper.remove(wrapper);
517 	}
518 
519 	protected class OnPreeditEndDelegateWrapper
520 	{
521 		void delegate(IMContext) dlg;
522 		gulong handlerId;
523 
524 		this(void delegate(IMContext) dlg)
525 		{
526 			this.dlg = dlg;
527 			onPreeditEndListeners ~= this;
528 		}
529 
530 		void remove(OnPreeditEndDelegateWrapper source)
531 		{
532 			foreach(index, wrapper; onPreeditEndListeners)
533 			{
534 				if (wrapper.handlerId == source.handlerId)
535 				{
536 					onPreeditEndListeners[index] = null;
537 					onPreeditEndListeners = std.algorithm.remove(onPreeditEndListeners, index);
538 					break;
539 				}
540 			}
541 		}
542 	}
543 	OnPreeditEndDelegateWrapper[] onPreeditEndListeners;
544 
545 	/**
546 	 * The ::preedit-end signal is emitted when a preediting sequence
547 	 * has been completed or canceled.
548 	 */
549 	gulong addOnPreeditEnd(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
550 	{
551 		auto wrapper = new OnPreeditEndDelegateWrapper(dlg);
552 		wrapper.handlerId = Signals.connectData(
553 			this,
554 			"preedit-end",
555 			cast(GCallback)&callBackPreeditEnd,
556 			cast(void*)wrapper,
557 			cast(GClosureNotify)&callBackPreeditEndDestroy,
558 			connectFlags);
559 		return wrapper.handlerId;
560 	}
561 
562 	extern(C) static void callBackPreeditEnd(GtkIMContext* imcontextStruct, OnPreeditEndDelegateWrapper wrapper)
563 	{
564 		wrapper.dlg(wrapper.outer);
565 	}
566 
567 	extern(C) static void callBackPreeditEndDestroy(OnPreeditEndDelegateWrapper wrapper, GClosure* closure)
568 	{
569 		wrapper.remove(wrapper);
570 	}
571 
572 	protected class OnPreeditStartDelegateWrapper
573 	{
574 		void delegate(IMContext) dlg;
575 		gulong handlerId;
576 
577 		this(void delegate(IMContext) dlg)
578 		{
579 			this.dlg = dlg;
580 			onPreeditStartListeners ~= this;
581 		}
582 
583 		void remove(OnPreeditStartDelegateWrapper source)
584 		{
585 			foreach(index, wrapper; onPreeditStartListeners)
586 			{
587 				if (wrapper.handlerId == source.handlerId)
588 				{
589 					onPreeditStartListeners[index] = null;
590 					onPreeditStartListeners = std.algorithm.remove(onPreeditStartListeners, index);
591 					break;
592 				}
593 			}
594 		}
595 	}
596 	OnPreeditStartDelegateWrapper[] onPreeditStartListeners;
597 
598 	/**
599 	 * The ::preedit-start signal is emitted when a new preediting sequence
600 	 * starts.
601 	 */
602 	gulong addOnPreeditStart(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
603 	{
604 		auto wrapper = new OnPreeditStartDelegateWrapper(dlg);
605 		wrapper.handlerId = Signals.connectData(
606 			this,
607 			"preedit-start",
608 			cast(GCallback)&callBackPreeditStart,
609 			cast(void*)wrapper,
610 			cast(GClosureNotify)&callBackPreeditStartDestroy,
611 			connectFlags);
612 		return wrapper.handlerId;
613 	}
614 
615 	extern(C) static void callBackPreeditStart(GtkIMContext* imcontextStruct, OnPreeditStartDelegateWrapper wrapper)
616 	{
617 		wrapper.dlg(wrapper.outer);
618 	}
619 
620 	extern(C) static void callBackPreeditStartDestroy(OnPreeditStartDelegateWrapper wrapper, GClosure* closure)
621 	{
622 		wrapper.remove(wrapper);
623 	}
624 
625 	protected class OnRetrieveSurroundingDelegateWrapper
626 	{
627 		bool delegate(IMContext) dlg;
628 		gulong handlerId;
629 
630 		this(bool delegate(IMContext) dlg)
631 		{
632 			this.dlg = dlg;
633 			onRetrieveSurroundingListeners ~= this;
634 		}
635 
636 		void remove(OnRetrieveSurroundingDelegateWrapper source)
637 		{
638 			foreach(index, wrapper; onRetrieveSurroundingListeners)
639 			{
640 				if (wrapper.handlerId == source.handlerId)
641 				{
642 					onRetrieveSurroundingListeners[index] = null;
643 					onRetrieveSurroundingListeners = std.algorithm.remove(onRetrieveSurroundingListeners, index);
644 					break;
645 				}
646 			}
647 		}
648 	}
649 	OnRetrieveSurroundingDelegateWrapper[] onRetrieveSurroundingListeners;
650 
651 	/**
652 	 * The ::retrieve-surrounding signal is emitted when the input method
653 	 * requires the context surrounding the cursor.  The callback should set
654 	 * the input method surrounding context by calling the
655 	 * gtk_im_context_set_surrounding() method.
656 	 *
657 	 * Returns: %TRUE if the signal was handled.
658 	 */
659 	gulong addOnRetrieveSurrounding(bool delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
660 	{
661 		auto wrapper = new OnRetrieveSurroundingDelegateWrapper(dlg);
662 		wrapper.handlerId = Signals.connectData(
663 			this,
664 			"retrieve-surrounding",
665 			cast(GCallback)&callBackRetrieveSurrounding,
666 			cast(void*)wrapper,
667 			cast(GClosureNotify)&callBackRetrieveSurroundingDestroy,
668 			connectFlags);
669 		return wrapper.handlerId;
670 	}
671 
672 	extern(C) static int callBackRetrieveSurrounding(GtkIMContext* imcontextStruct, OnRetrieveSurroundingDelegateWrapper wrapper)
673 	{
674 		return wrapper.dlg(wrapper.outer);
675 	}
676 
677 	extern(C) static void callBackRetrieveSurroundingDestroy(OnRetrieveSurroundingDelegateWrapper wrapper, GClosure* closure)
678 	{
679 		wrapper.remove(wrapper);
680 	}
681 }