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 /** 126 * Sets our main struct and passes it to the parent class. 127 */ 128 public this (GtkIMContext* gtkIMContext, bool ownedRef = false) 129 { 130 this.gtkIMContext = gtkIMContext; 131 super(cast(GObject*)gtkIMContext, ownedRef); 132 } 133 134 135 /** */ 136 public static GType getType() 137 { 138 return gtk_im_context_get_type(); 139 } 140 141 /** 142 * Asks the widget that the input context is attached to to delete 143 * characters around the cursor position by emitting the 144 * GtkIMContext::delete_surrounding signal. Note that @offset and @n_chars 145 * are in characters not in bytes which differs from the usage other 146 * places in #GtkIMContext. 147 * 148 * In order to use this function, you should first call 149 * gtk_im_context_get_surrounding() to get the current context, and 150 * call this function immediately afterwards to make sure that you 151 * know what you are deleting. You should also account for the fact 152 * that even if the signal was handled, the input context might not 153 * have deleted all the characters that were requested to be deleted. 154 * 155 * This function is used by an input method that wants to make 156 * subsitutions in the existing text in response to new input. It is 157 * not useful for applications. 158 * 159 * Params: 160 * offset = offset from cursor position in chars; 161 * a negative value means start before the cursor. 162 * nChars = number of characters to delete. 163 * 164 * Returns: %TRUE if the signal was handled. 165 */ 166 public bool deleteSurrounding(int offset, int nChars) 167 { 168 return gtk_im_context_delete_surrounding(gtkIMContext, offset, nChars) != 0; 169 } 170 171 /** 172 * Allow an input method to internally handle key press and release 173 * events. If this function returns %TRUE, then no further processing 174 * should be done for this key event. 175 * 176 * Params: 177 * event = the key event 178 * 179 * Returns: %TRUE if the input method handled the key event. 180 */ 181 public bool filterKeypress(GdkEventKey* event) 182 { 183 return gtk_im_context_filter_keypress(gtkIMContext, event) != 0; 184 } 185 186 /** 187 * Notify the input method that the widget to which this 188 * input context corresponds has gained focus. The input method 189 * may, for example, change the displayed feedback to reflect 190 * this change. 191 */ 192 public void focusIn() 193 { 194 gtk_im_context_focus_in(gtkIMContext); 195 } 196 197 /** 198 * Notify the input method that the widget to which this 199 * input context corresponds has lost focus. The input method 200 * may, for example, change the displayed feedback or reset the contexts 201 * state to reflect this change. 202 */ 203 public void focusOut() 204 { 205 gtk_im_context_focus_out(gtkIMContext); 206 } 207 208 /** 209 * Retrieve the current preedit string for the input context, 210 * and a list of attributes to apply to the string. 211 * This string should be displayed inserted at the insertion 212 * point. 213 * 214 * Params: 215 * str = location to store the retrieved 216 * string. The string retrieved must be freed with g_free(). 217 * attrs = location to store the retrieved 218 * attribute list. When you are done with this list, you 219 * must unreference it with pango_attr_list_unref(). 220 * cursorPos = location to store position of cursor (in characters) 221 * within the preedit string. 222 */ 223 public void getPreeditString(out string str, out PgAttributeList attrs, out int cursorPos) 224 { 225 char* outstr = null; 226 PangoAttrList* outattrs = null; 227 228 gtk_im_context_get_preedit_string(gtkIMContext, &outstr, &outattrs, &cursorPos); 229 230 str = Str.toString(outstr); 231 attrs = ObjectG.getDObject!(PgAttributeList)(outattrs); 232 } 233 234 /** 235 * Retrieves context around the insertion point. Input methods 236 * typically want context in order to constrain input text based on 237 * existing text; this is important for languages such as Thai where 238 * only some sequences of characters are allowed. 239 * 240 * This function is implemented by emitting the 241 * GtkIMContext::retrieve_surrounding signal on the input method; in 242 * response to this signal, a widget should provide as much context as 243 * is available, up to an entire paragraph, by calling 244 * gtk_im_context_set_surrounding(). Note that there is no obligation 245 * for a widget to respond to the ::retrieve_surrounding signal, so input 246 * methods must be prepared to function without context. 247 * 248 * Params: 249 * text = location to store a UTF-8 encoded 250 * string of text holding context around the insertion point. 251 * If the function returns %TRUE, then you must free the result 252 * stored in this location with g_free(). 253 * cursorIndex = location to store byte index of the insertion 254 * cursor within @text. 255 * 256 * Returns: %TRUE if surrounding text was provided; in this case 257 * you must free the result stored in *text. 258 */ 259 public bool getSurrounding(out string text, out int cursorIndex) 260 { 261 char* outtext = null; 262 263 auto p = gtk_im_context_get_surrounding(gtkIMContext, &outtext, &cursorIndex) != 0; 264 265 text = Str.toString(outtext); 266 267 return p; 268 } 269 270 /** 271 * Notify the input method that a change such as a change in cursor 272 * position has been made. This will typically cause the input 273 * method to clear the preedit state. 274 */ 275 public void reset() 276 { 277 gtk_im_context_reset(gtkIMContext); 278 } 279 280 /** 281 * Set the client window for the input context; this is the 282 * #GdkWindow in which the input appears. This window is 283 * used in order to correctly position status windows, and may 284 * also be used for purposes internal to the input method. 285 * 286 * Params: 287 * window = the client window. This may be %NULL to indicate 288 * that the previous client window no longer exists. 289 */ 290 public void setClientWindow(Window window) 291 { 292 gtk_im_context_set_client_window(gtkIMContext, (window is null) ? null : window.getWindowStruct()); 293 } 294 295 /** 296 * Notify the input method that a change in cursor 297 * position has been made. The location is relative to the client 298 * window. 299 * 300 * Params: 301 * area = new location 302 */ 303 public void setCursorLocation(GdkRectangle* area) 304 { 305 gtk_im_context_set_cursor_location(gtkIMContext, area); 306 } 307 308 /** 309 * Sets surrounding context around the insertion point and preedit 310 * string. This function is expected to be called in response to the 311 * GtkIMContext::retrieve_surrounding signal, and will likely have no 312 * effect if called at other times. 313 * 314 * Params: 315 * text = text surrounding the insertion point, as UTF-8. 316 * the preedit string should not be included within 317 * @text. 318 * len = the length of @text, or -1 if @text is nul-terminated 319 * cursorIndex = the byte index of the insertion cursor within @text. 320 */ 321 public void setSurrounding(string text, int len, int cursorIndex) 322 { 323 gtk_im_context_set_surrounding(gtkIMContext, Str.toStringz(text), len, cursorIndex); 324 } 325 326 /** 327 * Sets whether the IM context should use the preedit string 328 * to display feedback. If @use_preedit is FALSE (default 329 * is TRUE), then the IM context may use some other method to display 330 * feedback, such as displaying it in a child of the root window. 331 * 332 * Params: 333 * usePreedit = whether the IM context should use the preedit string. 334 */ 335 public void setUsePreedit(bool usePreedit) 336 { 337 gtk_im_context_set_use_preedit(gtkIMContext, usePreedit); 338 } 339 340 protected class OnCommitDelegateWrapper 341 { 342 void delegate(string, IMContext) dlg; 343 gulong handlerId; 344 345 this(void delegate(string, IMContext) dlg) 346 { 347 this.dlg = dlg; 348 onCommitListeners ~= this; 349 } 350 351 void remove(OnCommitDelegateWrapper source) 352 { 353 foreach(index, wrapper; onCommitListeners) 354 { 355 if (wrapper.handlerId == source.handlerId) 356 { 357 onCommitListeners[index] = null; 358 onCommitListeners = std.algorithm.remove(onCommitListeners, index); 359 break; 360 } 361 } 362 } 363 } 364 OnCommitDelegateWrapper[] onCommitListeners; 365 366 /** 367 * The ::commit signal is emitted when a complete input sequence 368 * has been entered by the user. This can be a single character 369 * immediately after a key press or the final result of preediting. 370 * 371 * Params: 372 * str = the completed character(s) entered by the user 373 */ 374 gulong addOnCommit(void delegate(string, IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 375 { 376 auto wrapper = new OnCommitDelegateWrapper(dlg); 377 wrapper.handlerId = Signals.connectData( 378 this, 379 "commit", 380 cast(GCallback)&callBackCommit, 381 cast(void*)wrapper, 382 cast(GClosureNotify)&callBackCommitDestroy, 383 connectFlags); 384 return wrapper.handlerId; 385 } 386 387 extern(C) static void callBackCommit(GtkIMContext* imcontextStruct, char* str, OnCommitDelegateWrapper wrapper) 388 { 389 wrapper.dlg(Str.toString(str), wrapper.outer); 390 } 391 392 extern(C) static void callBackCommitDestroy(OnCommitDelegateWrapper wrapper, GClosure* closure) 393 { 394 wrapper.remove(wrapper); 395 } 396 397 protected class OnDeleteSurroundingDelegateWrapper 398 { 399 bool delegate(int, int, IMContext) dlg; 400 gulong handlerId; 401 402 this(bool delegate(int, int, IMContext) dlg) 403 { 404 this.dlg = dlg; 405 onDeleteSurroundingListeners ~= this; 406 } 407 408 void remove(OnDeleteSurroundingDelegateWrapper source) 409 { 410 foreach(index, wrapper; onDeleteSurroundingListeners) 411 { 412 if (wrapper.handlerId == source.handlerId) 413 { 414 onDeleteSurroundingListeners[index] = null; 415 onDeleteSurroundingListeners = std.algorithm.remove(onDeleteSurroundingListeners, index); 416 break; 417 } 418 } 419 } 420 } 421 OnDeleteSurroundingDelegateWrapper[] onDeleteSurroundingListeners; 422 423 /** 424 * The ::delete-surrounding signal is emitted when the input method 425 * needs to delete all or part of the context surrounding the cursor. 426 * 427 * Params: 428 * offset = the character offset from the cursor position of the text 429 * to be deleted. A negative value indicates a position before 430 * the cursor. 431 * nChars = the number of characters to be deleted 432 * 433 * Returns: %TRUE if the signal was handled. 434 */ 435 gulong addOnDeleteSurrounding(bool delegate(int, int, IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 436 { 437 auto wrapper = new OnDeleteSurroundingDelegateWrapper(dlg); 438 wrapper.handlerId = Signals.connectData( 439 this, 440 "delete-surrounding", 441 cast(GCallback)&callBackDeleteSurrounding, 442 cast(void*)wrapper, 443 cast(GClosureNotify)&callBackDeleteSurroundingDestroy, 444 connectFlags); 445 return wrapper.handlerId; 446 } 447 448 extern(C) static int callBackDeleteSurrounding(GtkIMContext* imcontextStruct, int offset, int nChars, OnDeleteSurroundingDelegateWrapper wrapper) 449 { 450 return wrapper.dlg(offset, nChars, wrapper.outer); 451 } 452 453 extern(C) static void callBackDeleteSurroundingDestroy(OnDeleteSurroundingDelegateWrapper wrapper, GClosure* closure) 454 { 455 wrapper.remove(wrapper); 456 } 457 458 protected class OnPreeditChangedDelegateWrapper 459 { 460 void delegate(IMContext) dlg; 461 gulong handlerId; 462 463 this(void delegate(IMContext) dlg) 464 { 465 this.dlg = dlg; 466 onPreeditChangedListeners ~= this; 467 } 468 469 void remove(OnPreeditChangedDelegateWrapper source) 470 { 471 foreach(index, wrapper; onPreeditChangedListeners) 472 { 473 if (wrapper.handlerId == source.handlerId) 474 { 475 onPreeditChangedListeners[index] = null; 476 onPreeditChangedListeners = std.algorithm.remove(onPreeditChangedListeners, index); 477 break; 478 } 479 } 480 } 481 } 482 OnPreeditChangedDelegateWrapper[] onPreeditChangedListeners; 483 484 /** 485 * The ::preedit-changed signal is emitted whenever the preedit sequence 486 * currently being entered has changed. It is also emitted at the end of 487 * a preedit sequence, in which case 488 * gtk_im_context_get_preedit_string() returns the empty string. 489 */ 490 gulong addOnPreeditChanged(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 491 { 492 auto wrapper = new OnPreeditChangedDelegateWrapper(dlg); 493 wrapper.handlerId = Signals.connectData( 494 this, 495 "preedit-changed", 496 cast(GCallback)&callBackPreeditChanged, 497 cast(void*)wrapper, 498 cast(GClosureNotify)&callBackPreeditChangedDestroy, 499 connectFlags); 500 return wrapper.handlerId; 501 } 502 503 extern(C) static void callBackPreeditChanged(GtkIMContext* imcontextStruct, OnPreeditChangedDelegateWrapper wrapper) 504 { 505 wrapper.dlg(wrapper.outer); 506 } 507 508 extern(C) static void callBackPreeditChangedDestroy(OnPreeditChangedDelegateWrapper wrapper, GClosure* closure) 509 { 510 wrapper.remove(wrapper); 511 } 512 513 protected class OnPreeditEndDelegateWrapper 514 { 515 void delegate(IMContext) dlg; 516 gulong handlerId; 517 518 this(void delegate(IMContext) dlg) 519 { 520 this.dlg = dlg; 521 onPreeditEndListeners ~= this; 522 } 523 524 void remove(OnPreeditEndDelegateWrapper source) 525 { 526 foreach(index, wrapper; onPreeditEndListeners) 527 { 528 if (wrapper.handlerId == source.handlerId) 529 { 530 onPreeditEndListeners[index] = null; 531 onPreeditEndListeners = std.algorithm.remove(onPreeditEndListeners, index); 532 break; 533 } 534 } 535 } 536 } 537 OnPreeditEndDelegateWrapper[] onPreeditEndListeners; 538 539 /** 540 * The ::preedit-end signal is emitted when a preediting sequence 541 * has been completed or canceled. 542 */ 543 gulong addOnPreeditEnd(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 544 { 545 auto wrapper = new OnPreeditEndDelegateWrapper(dlg); 546 wrapper.handlerId = Signals.connectData( 547 this, 548 "preedit-end", 549 cast(GCallback)&callBackPreeditEnd, 550 cast(void*)wrapper, 551 cast(GClosureNotify)&callBackPreeditEndDestroy, 552 connectFlags); 553 return wrapper.handlerId; 554 } 555 556 extern(C) static void callBackPreeditEnd(GtkIMContext* imcontextStruct, OnPreeditEndDelegateWrapper wrapper) 557 { 558 wrapper.dlg(wrapper.outer); 559 } 560 561 extern(C) static void callBackPreeditEndDestroy(OnPreeditEndDelegateWrapper wrapper, GClosure* closure) 562 { 563 wrapper.remove(wrapper); 564 } 565 566 protected class OnPreeditStartDelegateWrapper 567 { 568 void delegate(IMContext) dlg; 569 gulong handlerId; 570 571 this(void delegate(IMContext) dlg) 572 { 573 this.dlg = dlg; 574 onPreeditStartListeners ~= this; 575 } 576 577 void remove(OnPreeditStartDelegateWrapper source) 578 { 579 foreach(index, wrapper; onPreeditStartListeners) 580 { 581 if (wrapper.handlerId == source.handlerId) 582 { 583 onPreeditStartListeners[index] = null; 584 onPreeditStartListeners = std.algorithm.remove(onPreeditStartListeners, index); 585 break; 586 } 587 } 588 } 589 } 590 OnPreeditStartDelegateWrapper[] onPreeditStartListeners; 591 592 /** 593 * The ::preedit-start signal is emitted when a new preediting sequence 594 * starts. 595 */ 596 gulong addOnPreeditStart(void delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 597 { 598 auto wrapper = new OnPreeditStartDelegateWrapper(dlg); 599 wrapper.handlerId = Signals.connectData( 600 this, 601 "preedit-start", 602 cast(GCallback)&callBackPreeditStart, 603 cast(void*)wrapper, 604 cast(GClosureNotify)&callBackPreeditStartDestroy, 605 connectFlags); 606 return wrapper.handlerId; 607 } 608 609 extern(C) static void callBackPreeditStart(GtkIMContext* imcontextStruct, OnPreeditStartDelegateWrapper wrapper) 610 { 611 wrapper.dlg(wrapper.outer); 612 } 613 614 extern(C) static void callBackPreeditStartDestroy(OnPreeditStartDelegateWrapper wrapper, GClosure* closure) 615 { 616 wrapper.remove(wrapper); 617 } 618 619 protected class OnRetrieveSurroundingDelegateWrapper 620 { 621 bool delegate(IMContext) dlg; 622 gulong handlerId; 623 624 this(bool delegate(IMContext) dlg) 625 { 626 this.dlg = dlg; 627 onRetrieveSurroundingListeners ~= this; 628 } 629 630 void remove(OnRetrieveSurroundingDelegateWrapper source) 631 { 632 foreach(index, wrapper; onRetrieveSurroundingListeners) 633 { 634 if (wrapper.handlerId == source.handlerId) 635 { 636 onRetrieveSurroundingListeners[index] = null; 637 onRetrieveSurroundingListeners = std.algorithm.remove(onRetrieveSurroundingListeners, index); 638 break; 639 } 640 } 641 } 642 } 643 OnRetrieveSurroundingDelegateWrapper[] onRetrieveSurroundingListeners; 644 645 /** 646 * The ::retrieve-surrounding signal is emitted when the input method 647 * requires the context surrounding the cursor. The callback should set 648 * the input method surrounding context by calling the 649 * gtk_im_context_set_surrounding() method. 650 * 651 * Returns: %TRUE if the signal was handled. 652 */ 653 gulong addOnRetrieveSurrounding(bool delegate(IMContext) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 654 { 655 auto wrapper = new OnRetrieveSurroundingDelegateWrapper(dlg); 656 wrapper.handlerId = Signals.connectData( 657 this, 658 "retrieve-surrounding", 659 cast(GCallback)&callBackRetrieveSurrounding, 660 cast(void*)wrapper, 661 cast(GClosureNotify)&callBackRetrieveSurroundingDestroy, 662 connectFlags); 663 return wrapper.handlerId; 664 } 665 666 extern(C) static int callBackRetrieveSurrounding(GtkIMContext* imcontextStruct, OnRetrieveSurroundingDelegateWrapper wrapper) 667 { 668 return wrapper.dlg(wrapper.outer); 669 } 670 671 extern(C) static void callBackRetrieveSurroundingDestroy(OnRetrieveSurroundingDelegateWrapper wrapper, GClosure* closure) 672 { 673 wrapper.remove(wrapper); 674 } 675 }