diff options
| author | Erik Kundiman <erik@megapahit.org> | 2026-04-25 06:54:10 +0800 |
|---|---|---|
| committer | Erik Kundiman <erik@megapahit.org> | 2026-04-25 06:54:10 +0800 |
| commit | d1f106774adcd850fca0bbe9167f6c214d4263a5 (patch) | |
| tree | b29e4db7e9f57edce25a669f1bf4ac8cb946dd0d /indra | |
| parent | df9970272800a71c180aa73fe2f71eb2f1b95fd5 (diff) | |
| parent | 4ccf6d90efe34475a39c89bf40f17c0d56a3ce1a (diff) | |
Merge tag 'Second_Life_Release#4ccf6d90-26.2' into 2026.02
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llmath/v3math.h | 9 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 63 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 13 | ||||
| -rwxr-xr-x | indra/newview/llviewerparceloverlay.cpp | 235 | ||||
| -rw-r--r-- | indra/newview/llviewerparceloverlay.h | 5 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 20 | ||||
| -rw-r--r-- | indra/newview/llwindowlistener.cpp | 42 |
7 files changed, 172 insertions, 215 deletions
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 0e11dca876..196ecdcf7d 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -155,7 +155,6 @@ class LLVector3 friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k - friend const LLVector3& operator/=(LLVector3& a, const LLVector3& b); friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; friend LLVector3 operator-(const LLVector3 &a); // Return vector -a @@ -461,14 +460,6 @@ inline const LLVector3& operator/=(LLVector3& a, F32 k) return a; } -inline const LLVector3& operator/=(LLVector3& a, const LLVector3& b) -{ - a.mV[VX] /= b.mV[VX]; - a.mV[VY] /= b.mV[VY]; - a.mV[VZ] /= b.mV[VZ]; - return a; -} - inline LLVector3 operator-(const LLVector3& a) { return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 8aacba00ac..658947d531 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1846,64 +1846,25 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) return; } - LLVector4a vert(x, y, z); - transform(vert); - mVerticesp[mCount] = vert; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; -} - -void LLRender::transform(LLVector3& vert) -{ - if (!mUIOffset.empty()) + if (mUIOffset.empty()) { - vert += LLVector3(mUIOffset.back().getF32ptr()); - vert *= LLVector3(mUIScale.back().getF32ptr()); + mVerticesp[mCount].set(x,y,z); } -} - -void LLRender::transform(LLVector4a& vert) -{ - if (!mUIOffset.empty()) + else { + LLVector4a vert(x, y, z); vert.add(mUIOffset.back()); vert.mul(mUIScale.back()); + mVerticesp[mCount] = vert; } -} - -void LLRender::untransform(LLVector3& vert) -{ - if (!mUIOffset.empty()) - { - vert /= LLVector3(mUIScale.back().getF32ptr()); - vert -= LLVector3(mUIOffset.back().getF32ptr()); - } -} - -void LLRender::batchTransform(LLVector4a* verts, U32 vert_count) -{ - if (!mUIOffset.empty()) - { - const LLVector4a& offset = mUIOffset.back(); - const LLVector4a& scale = mUIScale.back(); - - for (U32 i = 0; i < vert_count; ++i) - { - verts[i].add(offset); - verts[i].mul(scale); - } - } -} -void LLRender::vertexBatchPreTransformed(const std::vector<LLVector4a>& verts) -{ - vertexBatchPreTransformed(verts.data(), narrow(verts.size())); + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1924,7 +1885,7 @@ void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1948,7 +1909,7 @@ void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector } } -void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 4ca63e7f1f..e6ae3baac6 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -462,16 +462,9 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void transform(LLVector3& vert); - void transform(LLVector4a& vert); - void untransform(LLVector3& vert); - - void batchTransform(LLVector4a* verts, U32 vert_count); - - void vertexBatchPreTransformed(const std::vector<LLVector4a>& verts); - void vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count); - void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U*, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 02fdddd5d5..0bb03cdd60 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -63,9 +63,9 @@ LLUIColor LLViewerParcelOverlay::sForSaleColor; LLUIColor LLViewerParcelOverlay::sAuctionColor; LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters) -: mRegion(region), - mParcelGridsPerEdge(S32(region_width_meters / PARCEL_GRID_STEP_METERS)), - mDirty(false), +: mRegion( region ), + mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ), + mDirty( false ), mTimeSinceLastUpdate(), mOverlayTextureIdx(-1) { @@ -467,9 +467,9 @@ void LLViewerParcelOverlay::updatePropertyLines() { for (S32 col = 0; col < GRIDS_PER_EDGE; col++) { - U8 overlay = mOwnership[row * GRIDS_PER_EDGE + col]; + U8 overlay = mOwnership[row*GRIDS_PER_EDGE+col]; S32 colorIndex = overlay & PARCEL_COLOR_MASK; - switch (colorIndex) + switch(colorIndex) { case PARCEL_SELF: case PARCEL_GROUP: @@ -483,11 +483,11 @@ void LLViewerParcelOverlay::updatePropertyLines() const LLColor4U& color = colors[colorIndex]; - F32 left = col * GRID_STEP; - F32 right = left + GRID_STEP; + F32 left = col*GRID_STEP; + F32 right = left+GRID_STEP; - F32 bottom = row * GRID_STEP; - F32 top = bottom + GRID_STEP; + F32 bottom = row*GRID_STEP; + F32 top = bottom+GRID_STEP; // West edge if (overlay & PARCEL_WEST_LINE) @@ -528,121 +528,99 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 Edge& edge = mEdges.back(); edge.color = color; - // Detailized rendering vertices: - // A B C D E F G - // *-*------*--------*--------*------*-* : 'outside' vertices are placed right on the border - // *------*--------*--------*------* : 'inside' vertices are shifted on LINE_WIDTH inside - - // Simplified rendering vertices: - // A G - // *-----------------------------------* - // *-----------------------------------* - F32 outside_x = start_x; F32 outside_y = start_y; - F32 outside_z = land.resolveHeightRegion(outside_x, outside_y); - F32 inside_x = start_x + tick_dx; - F32 inside_y = start_y + tick_dy; - F32 inside_z = land.resolveHeightRegion(inside_x, inside_y); - - auto move = [&](F32 distance) - { - outside_x += dx * distance; - outside_y += dy * distance; - outside_z = land.resolveHeightRegion(outside_x, outside_y); - inside_x += dx * distance; - inside_y += dy * distance; - inside_z = land.resolveHeightRegion(inside_x, inside_y); - }; + F32 outside_z = 0.f; + F32 inside_x = start_x + tick_dx; + F32 inside_y = start_y + tick_dy; + F32 inside_z = 0.f; - auto split = [&](U32 lod, const LLVector4a& start, F32 x, F32 y, F32 z, F32 part) + auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part) { - F32 new_x = start[VX] + (x - start[VX]) * part; - F32 new_y = start[VY] + (y - start[VY]) * part; - edge.pushVertex(lod, new_x, new_y, water_z, 0); + F32 new_x = start.mV[VX] + (x - start.mV[VX]) * part; + F32 new_y = start.mV[VY] + (y - start.mV[VY]) * part; + F32 new_z = start.mV[VZ] + (z - start.mV[VZ]) * part; + edge.vertices.emplace_back(new_x, new_y, new_z); }; - auto checkForSplit = [&](U32 lod) + auto checkForSplit = [&]() { - const std::vector<LLVector4a>& vertices = edge.verticesUnderWater[lod]; - const LLVector4a& last_outside = vertices.back(); - F32 z0 = last_outside[VZ]; + const LLVector3& last_outside = edge.vertices.back(); + F32 z0 = last_outside.mV[VZ]; F32 z1 = outside_z; if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) return; F32 part = (water_z - z0) / (z1 - z0); - const LLVector4a& last_inside = vertices[vertices.size() - 2]; - split(lod, last_inside, inside_x, inside_y, inside_z, part); - split(lod, last_outside, outside_x, outside_y, outside_z, part); + const LLVector3& last_inside = edge.vertices[edge.vertices.size() - 2]; + split(last_inside, inside_x, inside_y, inside_z, part); + split(last_outside, outside_x, outside_y, outside_z, part); }; - auto pushTwoVertices = [&](U32 lod) - { - LLVector3 out(outside_x, outside_y, outside_z); - LLVector3 in(inside_x, inside_y, inside_z); - if (fabs(inside_z - outside_z) < LINE_WIDTH / 5) - { - edge.pushVertex(lod, inside_x, inside_y, inside_z, water_z); - } - else - { - // Make the line thinner if heights differ too much - LLVector3 dist(in - out); - F32 coef = dist.length() / LINE_WIDTH; - LLVector3 new_in(out + dist / coef); - edge.pushVertex(lod, new_in[VX], new_in[VY], new_in[VZ], water_z); - } - edge.pushVertex(lod, outside_x, outside_y, outside_z, water_z); - }; + // First part, only one vertex + outside_z = land.resolveHeightRegion( outside_x, outside_y ); - // Point A simplified (first two vertices) - pushTwoVertices(1); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); - // Point A detailized (only one vertex) - edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); + inside_x += dx * LINE_WIDTH; + inside_y += dy * LINE_WIDTH; - // Point B (two vertices) - move(LINE_WIDTH); - pushTwoVertices(0); + outside_x += dx * LINE_WIDTH; + outside_y += dy * LINE_WIDTH; - // Points C, D, E - F32 distance = 1.f - LINE_WIDTH; + // Then the "actual edge" + inside_z = land.resolveHeightRegion( inside_x, inside_y ); + outside_z = land.resolveHeightRegion( outside_x, outside_y ); + + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); + + inside_x += dx * (dx - LINE_WIDTH); + inside_y += dy * (dy - LINE_WIDTH); + + outside_x += dx * (dx - LINE_WIDTH); + outside_y += dy * (dy - LINE_WIDTH); + + // Middle part, full width constexpr S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS; - for (U32 i = 1; i < GRID_STEP; ++i) + for (S32 i = 1; i < GRID_STEP; i++) { - move(distance); - checkForSplit(0); - pushTwoVertices(0); - distance = 1.f; + inside_z = land.resolveHeightRegion( inside_x, inside_y ); + outside_z = land.resolveHeightRegion( outside_x, outside_y ); + + checkForSplit(); + + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); + + inside_x += dx; + inside_y += dy; + + outside_x += dx; + outside_y += dy; } - // Point F (two vertices) - move(1.f - LINE_WIDTH); - checkForSplit(0); - pushTwoVertices(0); + // Extra buffer for edge + inside_x -= dx * LINE_WIDTH; + inside_y -= dy * LINE_WIDTH; - // Point G simplified (last two vertices) - move(LINE_WIDTH); - pushTwoVertices(1); + outside_x -= dx * LINE_WIDTH; + outside_y -= dy * LINE_WIDTH; - // Point G detailized (only one vertex) - edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); -} + inside_z = land.resolveHeightRegion( inside_x, inside_y ); + outside_z = land.resolveHeightRegion( outside_x, outside_y ); -void LLViewerParcelOverlay::Edge::pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z) -{ - verticesUnderWater[lod].emplace_back(x, y, z); - gGL.transform(verticesUnderWater[lod].back()); + checkForSplit(); - if (z >= water_z) - { - verticesAboveWater[lod].push_back(verticesUnderWater[lod].back()); - } - else - { - verticesAboveWater[lod].emplace_back(x, y, water_z); - gGL.transform(verticesAboveWater[lod].back()); - } + edge.vertices.emplace_back(inside_x, inside_y, inside_z); + edge.vertices.emplace_back(outside_x, outside_y, outside_z); + + outside_x += dx * LINE_WIDTH; + outside_y += dy * LINE_WIDTH; + + // Last edge is not drawn to the edge + outside_z = land.resolveHeightRegion( outside_x, outside_y ); + + edge.vertices.emplace_back(outside_x, outside_y, outside_z); } void LLViewerParcelOverlay::setDirty() @@ -687,9 +665,6 @@ void LLViewerParcelOverlay::renderPropertyLines() if (!show) return; - LL_PROFILE_ZONE_SCOPED; - LL_PROFILE_GPU_ZONE("Property Lines"); - LLSurface& land = mRegion->getLand(); bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); @@ -727,8 +702,6 @@ void LLViewerParcelOverlay::renderPropertyLines() // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); - bool draw_underwater = camera_region.mV[VZ] < water_z || - !gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); // Set up a cull plane 2 * PARCEL_GRID_STEP_METERS behind // the camera. The cull plane normal is the camera's at axis. @@ -736,23 +709,15 @@ void LLViewerParcelOverlay::renderPropertyLines() cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - bool render_hidden = !draw_underwater && - LLSelectMgr::sRenderHiddenSelections && - LLFloaterReg::instanceVisible("build"); + bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); constexpr F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; - const F32 PROPERTY_LINE_LOD0_DIST_SQUARED = PROPERTY_LINE_CLIP_DIST_SQUARED / 25; for (const Edge& edge : mEdges) { - const std::vector<LLVector4a>& vertices0 = edge.verticesAboveWater[0]; - const F32* first = vertices0.front().getF32ptr(); - const F32* last = vertices0.back().getF32ptr(); - LLVector3 center((first[VX] + last[VX]) / 2, (first[VY] + last[VY]) / 2, (first[VZ] + last[VZ]) / 2); - gGL.untransform(center); + LLVector3 center = edge.vertices[edge.vertices.size() >> 1]; - F32 dist_squared = dist_vec_squared(center, camera_region); - if (dist_squared > PROPERTY_LINE_CLIP_DIST_SQUARED) + if (dist_vec_squared2D(center, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } @@ -766,33 +731,43 @@ void LLViewerParcelOverlay::renderPropertyLines() continue; } - U32 lod = dist_squared < PROPERTY_LINE_LOD0_DIST_SQUARED ? 0 : 1; - gGL.begin(LLRender::TRIANGLE_STRIP); gGL.color4ubv(edge.color.mV); - if (draw_underwater) + for (const LLVector3& vertex : edge.vertices) { - gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); + if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) + { + gGL.vertex3fv(vertex.mV); + } + else + { + LLVector3 visible = vertex; + visible.mV[VZ] = water_z; + gGL.vertex3fv(visible.mV); + } } - else + + gGL.end(); + + if (render_hidden) { - gGL.vertexBatchPreTransformed(edge.verticesAboveWater[lod]); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - if (render_hidden) - { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.begin(LLRender::TRIANGLE_STRIP); - LLColor4U color = edge.color; - color.mV[VALPHA] /= 4; - gGL.color4ubv(color.mV); + LLColor4U color = edge.color; + color.mV[VALPHA] /= 4; + gGL.color4ubv(color.mV); - gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); + for (const LLVector3& vertex : edge.vertices) + { + gGL.vertex3fv(vertex.mV); } - } - gGL.end(); + gGL.end(); + } } gGL.popMatrix(); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 7271c85701..50bef02ddf 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -116,10 +116,7 @@ private: struct Edge { - void pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z); - // LOD: 0 - detailized, 1 - simplified - std::vector<LLVector4a> verticesAboveWater[2]; - std::vector<LLVector4a> verticesUnderWater[2]; + std::vector<LLVector3> vertices; LLColor4U color; }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f4227b1026..c95a3c9578 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2332,14 +2332,22 @@ void LLViewerWindow::initWorldUI() physical_mem = LLMemory::getMaxMemKB(); } - if (!gNonInteractive && physical_mem > MIN_PHYSICAL_MEMORY) + if (!gNonInteractive) { - LL_INFOS() << "Preloading cef instances" << LL_ENDL; + if (physical_mem > MIN_PHYSICAL_MEMORY) + { + LL_INFOS() << "Preloading cef instances" << LL_ENDL; - LLFloaterReg::getInstance("destinations"); - LLFloaterReg::getInstance("avatar_welcome_pack"); - LLFloaterReg::getInstance("search"); - LLFloaterReg::getInstance("marketplace"); + LLFloaterReg::getInstance("destinations"); + LLFloaterReg::getInstance("avatar_welcome_pack"); + LLFloaterReg::getInstance("search"); + LLFloaterReg::getInstance("marketplace"); + } + else if (gSavedSettings.getBOOL("FirstLoginThisInstall")) + { + // Preload the welcome pack for first-time login even on low end hardware + LLFloaterReg::getInstance("avatar_welcome_pack"); + } } } diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index 31005fb734..38e49d0750 100644 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -91,7 +91,8 @@ LLWindowListener::LLWindowListener(LLViewerWindow *window, const KeyboardGetter& &LLWindowListener::getPaths, LLSDMap("reply", LLSD())); add("keyDown", - keySomething + "keypress event.\n" + keyExplain + mask, + keySomething + "keypress event.\n" + keyExplain + + "The [\"char\"] parameter detects and handles non-ASCII characters seperately\n" + mask, &LLWindowListener::keyDown); add("keyUp", keySomething + "key release event.\n" + keyExplain + mask, @@ -270,6 +271,20 @@ void LLWindowListener::keyDown(LLSD const & evt) KEY key = getKEY(evt); MASK mask = getMask(evt); + bool is_non_ascii = false; + llwchar uni_char = 0; + + if (evt.has("char")) + { + LLWString wstr = utf8str_to_wstring(evt["char"].asString()); + if (!wstr.empty()) + { + uni_char = wstr[0]; + // If the Unicode code point is outside ASCII range, use Unicode-only handling + is_non_ascii = (uni_char >= 0x80); + } + } + if (evt.has("path")) { std::string path(evt["path"]); @@ -284,8 +299,17 @@ void LLWindowListener::keyDown(LLSD const & evt) response.setResponse(target_view->getInfo()); gFocusMgr.setKeyboardFocus(target_view); - gViewerInput.handleKey(key, mask, false); - if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + + if (is_non_ascii) + { + // For non-ASCII characters, only send the Unicode event + mWindow->handleUnicodeChar(uni_char, mask); + } + else + { + gViewerInput.handleKey(key, mask, false); + if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + } } else { @@ -296,8 +320,16 @@ void LLWindowListener::keyDown(LLSD const & evt) } else { - gViewerInput.handleKey(key, mask, false); - if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + if (is_non_ascii) + { + // For non-ASCII characters, only send the Unicode event + mWindow->handleUnicodeChar(uni_char, mask); + } + else + { + gViewerInput.handleKey(key, mask, false); + if(key < 0x80) mWindow->handleUnicodeChar(key, mask); + } } } |
