diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/android/detect.py | 2 | ||||
-rw-r--r-- | platform/android/display_server_android.cpp | 21 | ||||
-rw-r--r-- | platform/javascript/detect.py | 2 | ||||
-rw-r--r-- | platform/linuxbsd/detect.py | 19 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 129 | ||||
-rw-r--r-- | platform/linuxbsd/display_server_x11.h | 1 | ||||
-rw-r--r-- | platform/osx/display_server_osx.mm | 38 | ||||
-rw-r--r-- | platform/server/detect.py | 31 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 40 |
9 files changed, 243 insertions, 40 deletions
diff --git a/platform/android/detect.py b/platform/android/detect.py index 0accacb679..60d4146712 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -215,7 +215,7 @@ def configure(env): env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++abi/include"]) # Disable exceptions and rtti on non-tools (template) builds - if env["tools"]: + if env["tools"] or env["builtin_icu"]: env.Append(CXXFLAGS=["-frtti"]) else: env.Append(CXXFLAGS=["-fno-rtti", "-fno-exceptions"]) diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index e82a12ece5..aab5da4fde 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -498,9 +498,28 @@ void DisplayServerAndroid::_set_key_modifier_state(Ref<InputEventWithModifiers> } void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) { + static char32_t prev_wc = 0; + char32_t unicode = p_unicode_char; + if ((p_unicode_char & 0xfffffc00) == 0xd800) { + if (prev_wc != 0) { + ERR_PRINT("invalid utf16 surrogate input"); + } + prev_wc = unicode; + return; // Skip surrogate. + } else if ((unicode & 0xfffffc00) == 0xdc00) { + if (prev_wc == 0) { + ERR_PRINT("invalid utf16 surrogate input"); + return; // Skip invalid surrogate. + } + unicode = (prev_wc << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000); + prev_wc = 0; + } else { + prev_wc = 0; + } + Ref<InputEventKey> ev; ev.instance(); - int val = p_unicode_char; + int val = unicode; int keycode = android_get_keysym(p_keycode); int phy_keycode = android_get_keysym(p_scancode); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 71189cf697..9f584d0899 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -71,6 +71,8 @@ def configure(env): ) # Tools need more memory. Initial stack memory in bytes. See `src/settings.js` in emscripten repository (will be renamed to INITIAL_MEMORY). env.Append(LINKFLAGS=["-s", "TOTAL_MEMORY=33554432"]) + elif env["builtin_icu"]: + env.Append(CCFLAGS=["-frtti"]) else: # Disable exceptions and rtti on non-tools (template) builds # These flags help keep the file size down. diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index a8bc3a09f6..277aafc107 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -205,14 +205,31 @@ def configure(env): # freetype depends on libpng and zlib, so bundling one of them while keeping others # as shared libraries leads to weird issues - if env["builtin_freetype"] or env["builtin_libpng"] or env["builtin_zlib"]: + if ( + env["builtin_freetype"] + or env["builtin_libpng"] + or env["builtin_zlib"] + or env["builtin_graphite"] + or env["builtin_harfbuzz"] + ): env["builtin_freetype"] = True env["builtin_libpng"] = True env["builtin_zlib"] = True + env["builtin_graphite"] = True + env["builtin_harfbuzz"] = True if not env["builtin_freetype"]: env.ParseConfig("pkg-config freetype2 --cflags --libs") + if not env["builtin_graphite"]: + env.ParseConfig("pkg-config graphite2 --cflags --libs") + + if not env["builtin_icu"]: + env.ParseConfig("pkg-config icu-uc --cflags --libs") + + if not env["builtin_harfbuzz"]: + env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs") + if not env["builtin_libpng"]: env.ParseConfig("pkg-config libpng16 --cflags --libs") diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 74c69c0823..356668a375 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -465,59 +465,138 @@ Bool DisplayServerX11::_predicate_clipboard_selection(Display *display, XEvent * } } +Bool DisplayServerX11::_predicate_clipboard_incr(Display *display, XEvent *event, XPointer arg) { + if (event->type == PropertyNotify && event->xproperty.state == PropertyNewValue) { + return True; + } else { + return False; + } +} + String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const { String ret; - Atom type; - Atom selection = XA_PRIMARY; - int format, result; - unsigned long len, bytes_left, dummy; - unsigned char *data; Window selection_owner = XGetSelectionOwner(x11_display, p_source); - if (selection_owner == x11_window) { return internal_clipboard; } if (selection_owner != None) { - { - // Block events polling while processing selection events. - MutexLock mutex_lock(events_mutex); + // Block events polling while processing selection events. + MutexLock mutex_lock(events_mutex); - XConvertSelection(x11_display, p_source, target, selection, - x11_window, CurrentTime); + Atom selection = XA_PRIMARY; + XConvertSelection(x11_display, p_source, target, selection, + x11_window, CurrentTime); - XFlush(x11_display); + XFlush(x11_display); - // Blocking wait for predicate to be True - // and remove the event from the queue. - XEvent event; - XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window); - } + // Blocking wait for predicate to be True and remove the event from the queue. + XEvent event; + XIfEvent(x11_display, &event, _predicate_clipboard_selection, (XPointer)&x11_window); - // - // Do not get any data, see how much data is there - // + // Do not get any data, see how much data is there. + Atom type; + int format, result; + unsigned long len, bytes_left, dummy; + unsigned char *data; XGetWindowProperty(x11_display, x11_window, selection, // Tricky.. 0, 0, // offset - len 0, // Delete 0==FALSE - AnyPropertyType, //flag + AnyPropertyType, // flag &type, // return type &format, // return format - &len, &bytes_left, //that + &len, &bytes_left, // data length &data); - // DATA is There - if (bytes_left > 0) { + + if (data) { + XFree(data); + } + + if (type == XInternAtom(x11_display, "INCR", 0)) { + // Data is going to be received incrementally. + DEBUG_LOG_X11("INCR selection started.\n"); + + LocalVector<uint8_t> incr_data; + uint32_t data_size = 0; + bool success = false; + + // Delete INCR property to notify the owner. + XDeleteProperty(x11_display, x11_window, type); + + // Process events from the queue. + bool done = false; + while (!done) { + if (!_wait_for_events()) { + // Error or timeout, abort. + break; + } + + // Non-blocking wait for next event and remove it from the queue. + XEvent ev; + while (XCheckIfEvent(x11_display, &ev, _predicate_clipboard_incr, nullptr)) { + result = XGetWindowProperty(x11_display, x11_window, + selection, // selection type + 0, LONG_MAX, // offset - len + True, // delete property to notify the owner + AnyPropertyType, // flag + &type, // return type + &format, // return format + &len, &bytes_left, // data length + &data); + + DEBUG_LOG_X11("PropertyNotify: len=%lu, format=%i\n", len, format); + + if (result == Success) { + if (data && (len > 0)) { + uint32_t prev_size = incr_data.size(); + if (prev_size == 0) { + // First property contains initial data size. + unsigned long initial_size = *(unsigned long *)data; + incr_data.resize(initial_size); + } else { + // New chunk, resize to be safe and append data. + incr_data.resize(MAX(data_size + len, prev_size)); + memcpy(incr_data.ptr() + data_size, data, len); + data_size += len; + } + } else { + // Last chunk, process finished. + done = true; + success = true; + } + } else { + printf("Failed to get selection data chunk.\n"); + done = true; + } + + if (data) { + XFree(data); + } + + if (done) { + break; + } + } + } + + if (success && (data_size > 0)) { + ret.parse_utf8((const char *)incr_data.ptr(), data_size); + } + } else if (bytes_left > 0) { + // Data is ready and can be processed all at once. result = XGetWindowProperty(x11_display, x11_window, selection, 0, bytes_left, 0, AnyPropertyType, &type, &format, &len, &dummy, &data); + if (result == Success) { ret.parse_utf8((const char *)data); } else { - printf("FAIL\n"); + printf("Failed to get selection data.\n"); } + if (data) { XFree(data); } diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 682f1c8ef3..61fb04cbf3 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -270,6 +270,7 @@ class DisplayServerX11 : public DisplayServer { static Bool _predicate_all_events(Display *display, XEvent *event, XPointer arg); static Bool _predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg); + static Bool _predicate_clipboard_incr(Display *display, XEvent *event, XPointer arg); static Bool _predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg); protected: diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 1ad7117b39..3025210195 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -701,8 +701,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; characters = (NSString *)aString; } - NSUInteger i, length = [characters length]; - NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet]; NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet]; if ([characters rangeOfCharacterFromSet:ctrlChars].length && [characters rangeOfCharacterFromSet:wsnlChars].length == 0) { @@ -712,8 +710,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; return; } - for (i = 0; i < length; i++) { - const unichar codepoint = [characters characterAtIndex:i]; + Char16String text; + text.resize([characters length] + 1); + [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])]; + + String u32text; + u32text.parse_utf16(text.ptr(), text.length()); + + for (int i = 0; i < u32text.length(); i++) { + const char32_t codepoint = u32text[i]; if ((codepoint & 0xFF00) == 0xF700) { continue; } @@ -1315,7 +1320,16 @@ static int remapKey(unsigned int key, unsigned int state) { if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { // Fallback unicode character handler used if IME is not active - for (NSUInteger i = 0; i < length; i++) { + Char16String text; + text.resize([characters length] + 1); + [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])]; + + String u32text; + u32text.parse_utf16(text.ptr(), text.length()); + + for (int i = 0; i < u32text.length(); i++) { + const char32_t codepoint = u32text[i]; + DisplayServerOSX::KeyEvent ke; ke.window_id = window_id; @@ -1325,7 +1339,7 @@ static int remapKey(unsigned int key, unsigned int state) { ke.keycode = remapKey([event keyCode], [event modifierFlags]); ke.physical_keycode = translateKey([event keyCode]); ke.raw = true; - ke.unicode = [characters characterAtIndex:i]; + ke.unicode = codepoint; _push_to_key_event_buffer(ke); } @@ -1417,7 +1431,15 @@ static int remapKey(unsigned int key, unsigned int state) { // Fallback unicode character handler used if IME is not active if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) { - for (NSUInteger i = 0; i < length; i++) { + Char16String text; + text.resize([characters length] + 1); + [characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])]; + + String u32text; + u32text.parse_utf16(text.ptr(), text.length()); + + for (int i = 0; i < u32text.length(); i++) { + const char32_t codepoint = u32text[i]; DisplayServerOSX::KeyEvent ke; ke.window_id = window_id; @@ -1427,7 +1449,7 @@ static int remapKey(unsigned int key, unsigned int state) { ke.keycode = remapKey([event keyCode], [event modifierFlags]); ke.physical_keycode = translateKey([event keyCode]); ke.raw = true; - ke.unicode = [characters characterAtIndex:i]; + ke.unicode = codepoint; _push_to_key_event_buffer(ke); } diff --git a/platform/server/detect.py b/platform/server/detect.py index d9ac357679..bf4744a234 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -138,14 +138,31 @@ def configure(env): # freetype depends on libpng and zlib, so bundling one of them while keeping others # as shared libraries leads to weird issues - if env["builtin_freetype"] or env["builtin_libpng"] or env["builtin_zlib"]: + if ( + env["builtin_freetype"] + or env["builtin_libpng"] + or env["builtin_zlib"] + or env["builtin_graphite"] + or env["builtin_harfbuzz"] + ): env["builtin_freetype"] = True env["builtin_libpng"] = True env["builtin_zlib"] = True + env["builtin_graphite"] = True + env["builtin_harfbuzz"] = True if not env["builtin_freetype"]: env.ParseConfig("pkg-config freetype2 --cflags --libs") + if not env["builtin_graphite"]: + env.ParseConfig("pkg-config graphite2 --cflags --libs") + + if not env["builtin_icu"]: + env.ParseConfig("pkg-config icu-uc --cflags --libs") + + if not env["builtin_harfbuzz"]: + env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs") + if not env["builtin_libpng"]: env.ParseConfig("pkg-config libpng16 --cflags --libs") @@ -233,7 +250,17 @@ def configure(env): env.Append(CPPDEFINES=["SERVER_ENABLED", "UNIX_ENABLED"]) if platform.system() == "Darwin": - env.Append(LINKFLAGS=["-framework", "Cocoa", "-framework", "Carbon", "-lz", "-framework", "IOKit"]) + env.Append( + LINKFLAGS=[ + "-framework", + "Cocoa", + "-framework", + "Carbon", + "-lz", + "-framework", + "IOKit", + ] + ) env.Append(LIBS=["pthread"]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index dfbb734ee4..2581cc3af6 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -2792,6 +2792,24 @@ void DisplayServerWindows::_process_key_events() { case WM_CHAR: { // extended keys should only be processed as WM_KEYDOWN message. if (!KeyMappingWindows::is_extended_key(ke.wParam) && ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR))) { + static char32_t prev_wc = 0; + char32_t unicode = ke.wParam; + if ((unicode & 0xfffffc00) == 0xd800) { + if (prev_wc != 0) { + ERR_PRINT("invalid utf16 surrogate input"); + } + prev_wc = unicode; + break; // Skip surrogate. + } else if ((unicode & 0xfffffc00) == 0xdc00) { + if (prev_wc == 0) { + ERR_PRINT("invalid utf16 surrogate input"); + break; // Skip invalid surrogate. + } + unicode = (prev_wc << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000); + prev_wc = 0; + } else { + prev_wc = 0; + } Ref<InputEventKey> k; k.instance(); @@ -2803,7 +2821,7 @@ void DisplayServerWindows::_process_key_events() { k->set_pressed(true); k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam)); k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); - k->set_unicode(ke.wParam); + k->set_unicode(unicode); if (k->get_unicode() && gr_mem) { k->set_alt(false); k->set_control(false); @@ -2840,7 +2858,25 @@ void DisplayServerWindows::_process_key_events() { k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24))); if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { - k->set_unicode(key_event_buffer[i + 1].wParam); + char32_t unicode = key_event_buffer[i + 1].wParam; + static char32_t prev_wck = 0; + if ((unicode & 0xfffffc00) == 0xd800) { + if (prev_wck != 0) { + ERR_PRINT("invalid utf16 surrogate input"); + } + prev_wck = unicode; + break; // Skip surrogate. + } else if ((unicode & 0xfffffc00) == 0xdc00) { + if (prev_wck == 0) { + ERR_PRINT("invalid utf16 surrogate input"); + break; // Skip invalid surrogate. + } + unicode = (prev_wck << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000); + prev_wck = 0; + } else { + prev_wck = 0; + } + k->set_unicode(unicode); } if (k->get_unicode() && gr_mem) { k->set_alt(false); |