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 }