Re-organize cross-platform support for text input methods.

FLTK 1.3 supports complex text input methods (TIMs) for the 3 platforms
(X11, Windows, macOS). This support has an interface with FLTK that is
common for X11 and Windows, via (undocumented) functions fl_set_spot(),
fl_set_status() and fl_reset_spot().
In contrast, and because it's been developed independently, the
interface between the macOS TIM and FLTK 1.3 is completely different :
static functions FL::insertion_point_location() and Fl::reset_marked_text().

The present change implements a single TIM/FLTK interface
used by all platforms based on functions fl_set_spot() and
fl_reset_spot().

The previous macOS-specific functions FL::insertion_point_location() and
Fl::reset_marked_text() are maintained only for compatibility with 1.3
and deprecated.
This commit is contained in:
ManoloFLTK
2022-01-07 16:34:44 +01:00
parent 27c175dad8
commit 5bab46940c
13 changed files with 71 additions and 59 deletions
+5 -2
View File
@@ -146,8 +146,11 @@ public:
static Fl_Screen_Driver *screen_driver();
static Fl_System_Driver *system_driver();
static void reset_marked_text(); // resets marked text
static void insertion_point_location(int x, int y, int height); // sets window coordinates & height of insertion point
#ifdef __APPLE__ // deprecated in 1.4 - only for compatibility with 1.3
static void reset_marked_text();
static void insertion_point_location(int x, int y, int height);
#endif
/** Get the box shadow width of all "shadow" boxtypes in pixels.
\since 1.4.0
+18 -2
View File
@@ -1076,9 +1076,25 @@ FL_EXPORT const char *fl_expand_text(const char *from, char *buf, int maxbuf, do
// XIM:
/** \todo provide user documentation for fl_set_status function */
FL_EXPORT void fl_set_status(int X, int Y, int W, int H);
/** \todo provide user documentation for fl_set_spot function */
/** Inform text input methods about the current text insertion cursor.
\param font Font currently in use in text input.
\param size Size of the current font.
\param X,Y Position of the bottom of the current text insertion cursor.
\param W,H Width and height of the current text insertion cursor.
\param win Points to the Fl_Window object containing the current text widget, or NULL.
*/
FL_EXPORT void fl_set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win = 0);
/** \todo provide user documentation for fl_reset_spot function*/
/** Resets marked text.
In many languages, typing a character can involve multiple keystrokes. For
example, the Ä can be composed of two dots (¨) on top of the
character, followed by the letter A (on a Mac with U.S. keyboard, you'd
type Alt-U, Shift-A. To inform the user that the dots may be followed by
another character, the ¨ is underlined).
Call this function if character composition needs to be aborted for some
reason. One such example would be the text input widget losing focus.
*/
FL_EXPORT void fl_reset_spot(void);
-25
View File
@@ -1885,31 +1885,6 @@ int Fl::dnd()
return Fl::screen_driver()->dnd();
}
/**
Resets marked text.
In many languages, typing a character can involve multiple keystrokes. For
example, the Ä can be composed of two dots (¨) on top of the
character, followed by the letter A (on a Mac with U.S. keyboard, you'd
type Alt-U, Shift-A. To inform the user that the dots may be followed by
another character, the ¨ is underlined).
Call this function if character composition needs to be aborted for some
reason. One such example would be the text input widget losing focus.
*/
void Fl::reset_marked_text() {
Fl::screen_driver()->reset_marked_text();
}
/**
Sets window coordinates and height of insertion point.
\see Fl::compose(int& del) for a detailed description.
*/
void Fl::insertion_point_location(int x, int y, int height) {
Fl::screen_driver()->insertion_point_location(x, y, height);
}
int Fl::event_key(int k) {
return system_driver()->event_key(k);
}
+1 -1
View File
@@ -469,7 +469,7 @@ int Fl_Input::handle(int event) {
case FL_UNFOCUS:
if (Fl::screen_driver()->has_marked_text() && Fl::compose_state) {
this->mark( this->position() );
Fl::reset_marked_text();
fl_reset_spot();
}
break;
case FL_FOCUS:
-1
View File
@@ -377,7 +377,6 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) {
} else {
fl_rectf((int)(xpos+curx+0.5), Y+ypos, 2, height);
}
Fl::insertion_point_location((int)xpos+curx, Y+ypos+height, height);
ypos_cur = ypos+height; //fix issue #270
}
+1 -4
View File
@@ -122,12 +122,9 @@ public:
static int secret_input_character;
/* Implement to indicate whether complex text input may involve marked text.
When it does, has_marked_text returns non zero and reset_marked_text() and
insertion_point_location() must also be implemented.
When it does, has_marked_text returns non zero.
*/
virtual int has_marked_text() const { return 0; }
virtual void reset_marked_text() {}
virtual void insertion_point_location(int /*x*/, int /*y*/, int /*height*/) {}
// implement so text-editing widgets support dead keys
virtual int compose(int &del) {
del = 0;
-1
View File
@@ -2424,7 +2424,6 @@ void Fl_Text_Display::draw_cursor( int X, int Y ) {
if ( X < text_area.x - 1 || X > text_area.x + text_area.w )
return;
Fl::insertion_point_location(X, bot, fontHeight);
/* For cursors other than the block, make them around 2/3 of a character
width, rounded to an even number of pixels so that X will draw an
odd number centered on the stem at x. */
+2 -1
View File
@@ -670,9 +670,10 @@ int Fl_Text_Editor::handle(int event) {
if (Fl::screen_driver()->has_marked_text() && buffer()->selected() && Fl::compose_state) {
int pos = insert_position();
buffer()->select(pos, pos);
Fl::reset_marked_text();
fl_reset_spot();
}
if (buffer()->selected()) redraw(); // Redraw selections...
// FALLTHROUGH
case FL_HIDE:
if (when() & FL_WHEN_RELEASE) maybe_do_callback();
return 1;
+11 -2
View File
@@ -2674,7 +2674,7 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
- (void)unmarkText {
fl_lock_function();
Fl::reset_marked_text();
Fl_Cocoa_Screen_Driver::reset_marked_text();
fl_unlock_function();
//NSLog(@"unmarkText");
}
@@ -2720,7 +2720,7 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
glyphRect.size.width = 0;
int x, y, height;
if (((Fl_Cocoa_Screen_Driver*)Fl::screen_driver())->insertion_point_location(&x, &y, &height)) {
if (Fl_Cocoa_Screen_Driver::insertion_point_location(&x, &y, &height)) {
glyphRect.origin.x = (CGFloat)x;
glyphRect.origin.y = (CGFloat)y;
} else {
@@ -4624,3 +4624,12 @@ void Fl_Cocoa_Screen_Driver::default_icons(const Fl_RGB_Image *icons[], int coun
default_icon = rgb_to_nsimage(icons[0]);
}
}
// Deprecated in 1.4 - only for backward compatibility with 1.3
void Fl::insertion_point_location(int x, int y, int height) {
Fl_Cocoa_Screen_Driver::insertion_point_location(x, y, height);
}
// Deprecated in 1.4 - only for backward compatibility with 1.3
void Fl::reset_marked_text() {
Fl_Cocoa_Screen_Driver::reset_marked_text();
}
+19 -16
View File
@@ -40,32 +40,35 @@ int Fl::compose_state = 0;
<p>If <i>false</i> is returned, the keys should be treated as function
keys, and del is set to zero. You could insert the text anyways, if
you don't know what else to do.
<p>Text editing widgets can preferentially call fl_set_spot() to indicate the window
coordinates of the bottom of the current insertion point and the line height.
This way, auxiliary windows that help choosing among alternative characters
with some text input methods appear just below or above the insertion point.
If widgets don't do that, such auxiliary windows appear at the widget's bottom.
<p>On the Mac OS platform, text input can involve marked text, that is,
<p>On some platforms, text input can involve marked text, that is,
temporary text replaced by other text during the input process. This occurs,
e.g., when using dead keys or when entering CJK characters.
e.g., under macOS when using dead keys or when entering CJK characters.
Text editing widgets should preferentially signal
marked text, usually underlining it. Widgets can use
<tt>int Fl::compose_state</tt> <i>after</i> having called Fl::compose(int&)
to obtain the length in bytes of marked text that always finishes at the
current insertion point. Widgets should also call
<tt>void Fl::reset_marked_text()</tt> when processing FL_UNFOCUS
events. Optionally, widgets can also call
<tt>void Fl::insertion_point_location(int x, int y, int height)</tt> to indicate the window
coordinates of the bottom of the current insertion point and the line height.
This way, auxiliary windows that help choosing among alternative characters
appear just below the insertion point. If widgets don't do that,
auxiliary windows appear at the widget's bottom. The
Fl_Input and Fl_Text_Editor widgets underline marked text.
void fl_reset_spot() when processing FL_UNFOCUS
events. The Fl_Input and Fl_Text_Editor widgets underline marked text.
If none of this is done by a user-defined text editing widget,
text input will work, but will not signal to the user what text is marked.
Finally, text editing widgets should call <tt>set_flag(MAC_USE_ACCENTS_MENU);</tt>
in their constructor if they want to use the feature introduced with Mac OS 10.7 "Lion"
where pressing and holding certain keys on the keyboard opens an accented-character menu window.
<p>Though the current implementation returns immediately, future
versions may take quite awhile, as they may pop up a window or do
other user-interface things to allow characters to be selected.
<p>Finally, text editing widgets should call <tt>set_flag(MAC_USE_ACCENTS_MENU);</tt>
in their constructor if they want to use, on the macOS platform, the feature introduced with Mac OS 10.7 "Lion"
where pressing and holding certain keys on the keyboard opens a diacritic marks popup window.
\note For compatibility with FLTK 1.3, text editing widgets can call
<tt>Fl::insertion_point_location(int x, int y, int height)</tt> and <tt>Fl::reset_marked_text()</tt>
<u>only under the macOS platform</u> to indicate/reset the coordinates of the current insertion point.
This is deprecated in version 1.4 because redundant with the platform-independent
fl_set_spot() and fl_reset_spot() functions.
*/
int Fl::compose(int& del) {
return Fl::screen_driver()->compose(del);
+3 -3
View File
@@ -86,9 +86,9 @@ public:
virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
virtual int has_marked_text() const;
virtual void reset_marked_text();
virtual void insertion_point_location(int x, int y, int height);
int insertion_point_location(int *px, int *py, int *pheight);
static void reset_marked_text();
static void insertion_point_location(int x, int y, int height);
static int insertion_point_location(int *px, int *py, int *pheight);
virtual int dnd(int use_selection);
virtual int compose(int &del);
virtual int input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input);
@@ -174,6 +174,8 @@ protected:
virtual void restore_scale(float);
virtual void antialias(int state);
virtual int antialias();
virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
virtual void reset_spot();
};
class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver {
@@ -17,7 +17,7 @@
#include <config.h>
#include "Fl_Quartz_Graphics_Driver.H"
#include "../Darwin/Fl_Darwin_System_Driver.H"
#include "../../Fl_Screen_Driver.H"
#include "../Cocoa/Fl_Cocoa_Screen_Driver.H"
#include <FL/platform.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Image_Surface.H>
@@ -182,3 +182,11 @@ void Fl_Quartz_Graphics_Driver::restore_scale(float s) {
CGContextScaleCTM(gc_, s, s);
}
}
void Fl_Quartz_Graphics_Driver::set_spot(int /*font*/, int size, int X, int Y, int /*W*/, int /*H*/, Fl_Window* /*win*/) {
Fl_Cocoa_Screen_Driver::insertion_point_location(X, Y, size);
}
void Fl_Quartz_Graphics_Driver::reset_spot() {
Fl_Cocoa_Screen_Driver::reset_marked_text();
}