summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-04-25 06:54:10 +0800
committerErik Kundiman <erik@megapahit.org>2026-04-25 06:54:10 +0800
commitd1f106774adcd850fca0bbe9167f6c214d4263a5 (patch)
treeb29e4db7e9f57edce25a669f1bf4ac8cb946dd0d /indra
parentdf9970272800a71c180aa73fe2f71eb2f1b95fd5 (diff)
parent4ccf6d90efe34475a39c89bf40f17c0d56a3ce1a (diff)
Merge tag 'Second_Life_Release#4ccf6d90-26.2' into 2026.02
Diffstat (limited to 'indra')
-rw-r--r--indra/llmath/v3math.h9
-rw-r--r--indra/llrender/llrender.cpp63
-rw-r--r--indra/llrender/llrender.h13
-rwxr-xr-xindra/newview/llviewerparceloverlay.cpp235
-rw-r--r--indra/newview/llviewerparceloverlay.h5
-rw-r--r--indra/newview/llviewerwindow.cpp20
-rw-r--r--indra/newview/llwindowlistener.cpp42
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);
+ }
}
}