From 9748ad36699c1d0b7efd108809b0b6c4688a674e Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:50:55 -0400 Subject: [PATCH 1/9] Text dropped on the window reaches the viewer as on Windows, so a dropped SLURL teleports SDL_EVENT_DROP_TEXT was thrown away, so dragging a SLURL or a URL onto the viewer did nothing on Linux and macOS. Its lines are now gathered and, on DROP_COMPLETE, sent through handleDragNDrop as DNDT_DEFAULT with the same start, drop and stop steps as files, which is how Win32 hands over CF_TEXT: a spatial SLURL teleports and a URL dropped on a face becomes its media. File drops are unchanged. There is still no live tracking. SDL reports where a drag is (DROP_POSITION), but every backend reads what it carries only at the drop, and the viewer's hover feedback depends on what is carried, so DROP_POSITION is left alone with a note saying why. A browser's link drag still delivers nothing on Linux: SDL 3.4.18's Wayland and X11 backends take its text/uri-list and discard every entry that is not a local file. Dragged text works there, and links work on macOS. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llwindow/llwindowsdl.cpp | 70 ++++++++++++++++++++++++++-------- indra/llwindow/llwindowsdl.h | 8 ++-- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 4ef7ad10a2..c1bde034b8 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2581,8 +2581,21 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) { // Drag-and-drop session starting. SDL3 doesn't populate event.drop.x/y // or deliver file paths until later (DROP_FILE between BEGIN and - // COMPLETE), so we can't START_TRACKING here — just reset the buffer. + // COMPLETE), so we can't START_TRACKING here — just reset the buffers. mPendingDropFiles.clear(); + mPendingDropText.clear(); + break; + } + case SDL_EVENT_DROP_POSITION: + { + // Where the drag is, but not what it carries: every backend reads + // the payload only once it is dropped (Wayland's data offer, X11's + // XdndSelection, Cocoa's pasteboard), so there is nothing to + // START_TRACKING or TRACK with. The viewer's hover feedback, a face + // lit for a URL or a texture, depends on what is dragged, and an + // empty payload would light faces for a file drag too. SDL stamps + // this last position on the DROP_FILE / DROP_TEXT / DROP_COMPLETE + // that follow, which is where the drop is dispatched. break; } case SDL_EVENT_DROP_FILE: @@ -2597,8 +2610,19 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) } case SDL_EVENT_DROP_TEXT: { - // The current handleDragNDrop pipeline is file-only (DNDT_FILE); SDL3 - // also delivers dropped text but we have nowhere to route it. Drop silently. + // Dropped text, a SLURL or a URL, goes to the viewer as DNDT_DEFAULT + // the way Win32 hands over CF_TEXT (lldragdropwin32.cpp): a spatial + // SLURL teleports, a URL dropped on a face becomes its media. SDL + // sends one DROP_TEXT a line; join them back into the one string + // Win32 passes, and dispatch on DROP_COMPLETE. + if (event.drop.data) + { + if (!mPendingDropText.empty()) + { + mPendingDropText += '\n'; + } + mPendingDropText += event.drop.data; + } break; } case SDL_EVENT_DROP_COMPLETE: @@ -2611,15 +2635,20 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) // DNDA_DROPPED — a DROPPED event with no preceding START_TRACKING is // a no-op (see indra/newview/llviewerwindow.cpp:1455+). // - // SDL3's drop API only surfaces file paths between DROP_BEGIN and - // DROP_COMPLETE, so we can't drive START/TRACK live the way the - // Win32 OLE backend does (DragEnter/DragOver/Drop). Instead we - // synthesise the same three-step sequence here so the receiver's - // state machine sees a well-formed transaction: + // SDL3's drop API only surfaces file paths and text between + // DROP_BEGIN and DROP_COMPLETE (see DROP_POSITION), so we can't + // drive START/TRACK live the way the Win32 OLE backend does + // (DragEnter/DragOver/Drop). Instead we synthesise the same + // three-step sequence here so the receiver's state machine sees a + // well-formed transaction: // // 1) DNDA_START_TRACKING with the file list -> mDragItems populated // 2) DNDA_DROPPED -> upload / apply // 3) DNDA_STOP_TRACKING -> mDragItems cleared + // + // Text runs the same three steps as DNDT_DEFAULT: the handler + // weighs the string on START_TRACKING and teleports or sets the + // media on DROPPED. Files win if a drop carries both. // event.drop.x/y are screen-coord units; scale to PIXEL units. const float scale = mCachedPixelDensity; // cached; see refreshPixelMetrics LLCoordWindow winCoord(llfloor(event.drop.x * scale), @@ -2627,25 +2656,34 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); const MASK mask = gKeyboard->currentMask(true); + LLWindowCallbacks::DragNDropType type = LLWindowCallbacks::DNDT_FILE; + std::vector data; if (!mPendingDropFiles.empty()) + { + data.swap(mPendingDropFiles); + } + else if (!mPendingDropText.empty()) + { + type = LLWindowCallbacks::DNDT_DEFAULT; + data.push_back(std::move(mPendingDropText)); + } + if (!data.empty()) { mCallbacks->handleDragNDrop(this, openGlCoord, mask, LLWindowCallbacks::DNDA_START_TRACKING, - LLWindowCallbacks::DNDT_FILE, - mPendingDropFiles); + type, data); mCallbacks->handleDragNDrop(this, openGlCoord, mask, LLWindowCallbacks::DNDA_DROPPED, - LLWindowCallbacks::DNDT_FILE, - mPendingDropFiles); + type, data); } // Always send STOP_TRACKING so any cached state (mDragItems, - // hover highlight) is cleared, whether or not files were dropped - // (text-only drops and cancelled drags both arrive here too). + // hover highlight) is cleared, whether or not anything was dropped + // (cancelled drags arrive here too). mCallbacks->handleDragNDrop(this, openGlCoord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, - LLWindowCallbacks::DNDT_FILE, - {}); + type, {}); mPendingDropFiles.clear(); + mPendingDropText.clear(); break; } case SDL_EVENT_WINDOW_CLOSE_REQUESTED: diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 2b9f9e8a7e..34f4913548 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -445,9 +445,11 @@ class LLWindowSDL final : public LLWindow LLMutex mSharedCtxMutex; std::set mSharedContexts; - // Files accumulated between SDL_EVENT_DROP_BEGIN and SDL_EVENT_DROP_COMPLETE. - // Each SDL_EVENT_DROP_FILE only carries one path, so we batch them and - // dispatch a single handleDragNDrop on COMPLETE. + // Files and text accumulated between SDL_EVENT_DROP_BEGIN and + // SDL_EVENT_DROP_COMPLETE. Each SDL_EVENT_DROP_FILE only carries one path + // and each SDL_EVENT_DROP_TEXT one line, so we batch them and dispatch a + // single handleDragNDrop on COMPLETE. + std::string mPendingDropText; std::vector mPendingDropFiles; // Currently-focused preeditor receiving SDL_EVENT_TEXT_EDITING composition From ff31b9b6d933ecc836fac0a6cd0f54af808787ed Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:51:56 -0400 Subject: [PATCH 2/9] A touchpad pinch zooms as Control+wheel does, as it does on Windows SDL 3.4 reports a touchpad pinch (Wayland's pointer gestures, XInput 2.4's, Cocoa's magnify) as SDL_EVENT_PINCH_*, and nothing handled them, so pinching did nothing. A Windows precision touchpad delivers a pinch as Control+wheel. The pinch now reaches the viewer the same way: wheel clicks at the cursor with Control held for the call, a click for every quarter octave of spread, which is the camera orbit's own step, with the fractions gathered so a slow pinch still makes its clicks. Spreading the fingers is a wheel rolled away, zooming in. SDL documents the scale as the change since the last update, and Cocoa sends that, but its Wayland and X11 backends pass on the scale since the gesture began, as their protocols carry it, so on those the ratio to the last update is taken. As on Windows, in the default third-person view Control+wheel raises or lowers the camera rather than zooming it. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llwindow/llwindowsdl.cpp | 61 ++++++++++++++++++++++++++++++++++ indra/llwindow/llwindowsdl.h | 7 ++++ 2 files changed, 68 insertions(+) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index c1bde034b8..e5f8bff143 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2016,6 +2016,67 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) break; } + // Touchpad pinch: Wayland's pointer gestures, XInput 2.4's, Cocoa's + // magnify. A Windows precision touchpad delivers a pinch as + // Control+wheel, so it zooms what Control+wheel zooms (a script's + // text, XUI Studio's canvas, a web page) and does to the camera what + // Control+wheel does: in the default third-person view, that raises + // or lowers the camera rather than zooming. Give it to the viewer the + // same way, as wheel clicks with Control held, at the cursor. SDL + // sends a pinch on its own stream with no wheel events beside it, so + // there is nothing to hold back. + case SDL_EVENT_PINCH_BEGIN: + case SDL_EVENT_PINCH_END: + { + mPinchLastScale = 1.f; + mPinchClickAccum = 0.f; + break; + } + case SDL_EVENT_PINCH_UPDATE: + { + // SDL documents the scale as the change since the last update, and + // Cocoa sends that, but SDL 3.4's Wayland and X11 backends pass on + // what their protocols carry: the scale since the gesture began + // (pointer-gestures-unstable-v1, XIGesturePinchEvent). Take the + // ratio to the last one there. Should SDL come to divide it itself, + // this must stop. + const F32 scale = event.pinch.scale; + if (scale <= 0.f || mPinchLastScale <= 0.f) + { + break; + } + const bool from_start = (mServerProtocol != Unknown); + const F32 ratio = from_start ? scale / mPinchLastScale : scale; + if (from_start) + { + mPinchLastScale = scale; + } + + // A click for every quarter octave of spread, the step the camera's + // orbit takes a click (2^(1/4), LLAgentCamera::handleScrollWheel): + // where Control does not change what the wheel does, fingers spread + // twice as far apart bring the camera in to half its distance. + // Spreading zooms in, as a wheel rolled away from you does, which + // is negative clicks. Fractions gather as the wheel's do, so a slow + // pinch still makes its clicks. + const F32 precise = -4.f * std::log2(ratio); + mPinchClickAccum += precise; + const S32 clicks = lltrunc(mPinchClickAccum); + mPinchClickAccum -= (F32)clicks; + if (clicks != 0 || precise != 0.f) + { + // The wheel's handlers ask the keyboard for Control, and + // LLKeyboardSDL::currentMask asks SDL_GetModState, so hold it + // there for the call, as a Windows pinch arrives with it down. + const SDL_Keymod held = SDL_GetModState(); + const SDL_Keymod added = (held & SDL_KMOD_CTRL) ? SDL_KMOD_NONE : SDL_KMOD_LCTRL; + SDL_SetModState(static_cast(held | added)); + mCallbacks->handleScrollWheel(this, LLScrollDelta(clicks, precise)); + SDL_SetModState(static_cast(SDL_GetModState() & ~added)); + } + break; + } + // Pen / stylus native events. SDL3 also emits mouse-emulation events // for these (with event.motion.which == SDL_PEN_MOUSEID) which our // mouse handlers already route through the usual input plumbing. The diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 34f4913548..f4f7fc6f49 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -385,6 +385,13 @@ class LLWindowSDL final : public LLWindow F32 mScrollWheelAccumX = 0.f; F32 mScrollWheelAccumY = 0.f; + // A touchpad pinch, given to the viewer as Control+wheel clicks (see + // SDL_EVENT_PINCH_UPDATE): the scale the gesture last reported, where a + // backend reports it from the gesture's start, and the clicks it has not + // yet made whole. Both reset with each gesture. + F32 mPinchLastScale = 1.f; + F32 mPinchClickAccum = 0.f; + // Mirrors LLWindowWin32::mAbsoluteCursorPosition. Set true while the // most recent mouse motion/button event was synthesised from a touch // screen (event.motion.which == SDL_TOUCH_MOUSEID) or a pen / stylus From 2c608fcbb0cf770dc1147319983fae12e80f6c0d Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:52:14 -0400 Subject: [PATCH 3/9] The IME's candidate window follows the caret in Script Studio and every other text view On SDL the text input area reached the IME only from LLLineEditor's and LLTextBase's draws, through setLanguageTextInput. ALTextView only allowed language input, so in Script Studio and the other ALTextView editors the candidate window opened wherever the last line editor had left the area, or at the window's origin. A bare caret also always took the 500x16 fallback, since every preeditor gives it bounds with no width. The backend now asks the owning preeditor where its caret and preedit are (placeLanguageTextInputArea, also the updateLanguageTextInputArea override) when a widget takes language input, after every composition update, as Win32 does after WM_IME_COMPOSITION, and from setLanguageTextInput. Bounds of no width are taken. ALTextView reports its caret from its draw, as the text fields do, while it holds language input and the caret is in sight. Its preedit bounds now lie on the caret's row when a composition wraps, rather than on its first row. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llui/text/altextview.cpp | 32 ++++++-- indra/llwindow/llwindowsdl.cpp | 132 +++++++++++++++++++++------------ indra/llwindow/llwindowsdl.h | 7 ++ 3 files changed, 119 insertions(+), 52 deletions(-) diff --git a/indra/llui/text/altextview.cpp b/indra/llui/text/altextview.cpp index 37c37394c7..e774392999 100644 --- a/indra/llui/text/altextview.cpp +++ b/indra/llui/text/altextview.cpp @@ -4395,12 +4395,20 @@ bool ALTextView::getPreeditLocation(S32 query_offset, LLCoordGL* coord, LLRect* } if (bounds) { - S32 row_begin, row_end; - const F32 x0 = lay().xOf(begin.line, begin.column, &row_begin); - F32 x1 = lay().xOf(begin.line, begin.column + mPreeditLength, &row_end); - if (row_end != row_begin) + // The preedit's span on the query's row, which is the row the top + // is of: from the row's start where the preedit began on a row + // before, to its end where it goes on to a row after. + S32 row_begin, row_end, row_at; + F32 x0 = lay().xOf(begin.line, begin.column, &row_begin); + F32 x1 = lay().xOf(begin.line, begin.column + mPreeditLength, &row_end); + lay().xOf(query.line, query.column, &row_at); + if (row_begin != row_at) { - x1 = lay().line(begin.line).rows[row_begin].width; + x0 = 0.f; + } + if (row_end != row_at) + { + x1 = lay().line(begin.line).rows[row_at].width; } LLRect local(static_cast(left + x0), top, static_cast(left + x1), top - row_h); LLRect screen; @@ -5653,6 +5661,20 @@ void ALTextView::draw() LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, text.getWidth(), nullptr, true); } } + // The input method's window at the caret, kept there as the caret, the + // scroll and the view move, as a text field keeps it from where it draws + // its caret: the caret's x, at the top of its row. Not while the caret + // is out of sight, where the window has nowhere to put it. + if (mLanguageInput && gFocusMgr.getAppHasFocus()) + { + LLCoordGL caret; + LLRect row; + LLWindow* window = getWindow(); + if (window && getPreeditLocation(-1, &caret, &row, nullptr)) + { + window->setLanguageTextInput(LLCoordGL(caret.mX, row.mTop)); + } + } drawBars(alpha); if (mModal) { diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index e5f8bff143..d7dde43310 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2405,9 +2405,11 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) mPreeditor->resetPreedit(); // An empty composition string means the IME cancelled or cleared - // the preedit; the reset above is the entire job. + // the preedit; the reset above did that, and the IME's area goes + // back to the caret the reset left. if (empty) { + placeLanguageTextInputArea(); break; } @@ -2439,6 +2441,12 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) const LLPreeditor::segment_lengths_t lengths { static_cast(preedit.length()) }; const LLPreeditor::standouts_t standouts { false }; mPreeditor->updatePreedit(preedit, lengths, standouts, caret); + + // The composition moved the caret, and with it where the + // candidate window belongs; the IME is told now rather than at + // the preeditor's next draw, as the Win32 backend does after every + // WM_IME_COMPOSITION. + placeLanguageTextInputArea(); break; } @@ -4182,68 +4190,94 @@ LLFontFallbackMatch LLWindowSDL::findFallbackFontForChar(llwchar wch) return result; } -void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position) +bool LLWindowSDL::placeLanguageTextInputArea() { - if (!mWindow) + if (!mWindow || !mPreeditor) { - return; + return false; } + // The preeditor's own caret and bounds — the line of text the caret is + // on, across the preedit, or at the caret itself when nothing is being + // composed — so the platform IME anchors its candidate window to the + // real text rather than a box guessed at the caret. Mirrors how the + // Win32 backend builds CANDIDATEFORM from the same query, in its own + // updateLanguageTextInputArea. + LLCoordGL caret_gl; + LLRect bounds_gl; + if (!mPreeditor->getPreeditLocation(-1, &caret_gl, &bounds_gl, nullptr)) + { + return false; + } + + // LLRect uses GL convention (Y up, mTop > mBottom). convertCoords + // flips Y so the GL-top-left maps to the window-top-left (the + // corner with the smaller window-Y), and likewise GL-bottom-right + // maps to window-bottom-right. + LLCoordWindow top_left; + LLCoordWindow bottom_right; + LLCoordWindow caret_win; + convertCoords(LLCoordGL(bounds_gl.mLeft, bounds_gl.mTop), &top_left); + convertCoords(LLCoordGL(bounds_gl.mRight, bounds_gl.mBottom), &bottom_right); + convertCoords(caret_gl, &caret_win); + // SDL_SetTextInputArea wants the rect and cursor offset in screen-coord // (logical) units, not pixels — that's the unit the IME backends - // (ibus / fcitx / IMM via SDL) speak. LLCoordWindow on this backend is - // in PIXELS (see the coord-space contract above), so we divide by - // pixel density at the boundary. + // (ibus / fcitx / text-input-v3 / XIM / Cocoa) speak. LLCoordWindow on + // this backend is in PIXELS (see the coord-space contract above), so we + // divide by pixel density at the boundary. const float density = SDL_GetWindowPixelDensity(mWindow); const float div = density > 0.f ? density : 1.f; - // If the active preeditor can give us its actual bounds + caret, feed - // those to SDL so the platform IME anchors its candidate-list popup to - // the real text input area (rather than a magic 500x16 box guessed at - // the caret). Mirrors how the Win32 backend builds CANDIDATEFORM from - // the same LLPreeditor::getPreeditLocation query — see - // llwindowwin32.cpp:4164. - if (mPreeditor) + SDL_Rect rect; + rect.x = llfloor(top_left.mX / div); + rect.y = llfloor(top_left.mY / div); + rect.w = llfloor((bottom_right.mX - top_left.mX) / div); + rect.h = llfloor((bottom_right.mY - top_left.mY) / div); + + // A widget that's still being laid out can return a default- + // constructed LLRect (all zeros), which would anchor the IME popup to + // the window origin. No width is fine, though: it is what every + // preeditor gives for a bare caret, before anything is composed, which + // is just when the IME first needs to know. + if (rect.h <= 0 || rect.w < 0) { - LLCoordGL caret_gl; - LLRect bounds_gl; - if (mPreeditor->getPreeditLocation(-1, &caret_gl, &bounds_gl, nullptr)) - { - // LLRect uses GL convention (Y up, mTop > mBottom). convertCoords - // flips Y so the GL-top-left maps to the window-top-left (the - // corner with the smaller window-Y), and likewise GL-bottom-right - // maps to window-bottom-right. - LLCoordWindow top_left; - LLCoordWindow bottom_right; - convertCoords(LLCoordGL(bounds_gl.mLeft, bounds_gl.mTop), &top_left); - convertCoords(LLCoordGL(bounds_gl.mRight, bounds_gl.mBottom), &bottom_right); - - LLCoordWindow caret_win; - convertCoords(caret_gl, &caret_win); - - SDL_Rect rect; - rect.x = llfloor(top_left.mX / div); - rect.y = llfloor(top_left.mY / div); - rect.w = llfloor((bottom_right.mX - top_left.mX) / div); - rect.h = llfloor((bottom_right.mY - top_left.mY) / div); - - // A widget that's still being laid out can return a default- - // constructed LLRect (all zeros); SDL_SetTextInputArea with a - // zero-sized rect would anchor the IME popup to the window - // origin. Fall through to the caret-based fallback instead. - if (rect.w > 0 && rect.h > 0) - { - const int cursor_x = llfloor((caret_win.mX - top_left.mX) / div); - SDL_SetTextInputArea(mWindow, &rect, cursor_x); - return; - } - } + return false; + } + + // The cursor is the caret's offset from rect.x. ibus, fcitx and XIM put + // the candidate window at rect.x + cursor, under the rect; text-input-v3 + // clamps that to the rect's right edge; Cocoa takes the rect alone. + const int cursor_x = llfloor((caret_win.mX - top_left.mX) / div); + SDL_SetTextInputArea(mWindow, &rect, cursor_x); + return true; +} + +void LLWindowSDL::updateLanguageTextInputArea() +{ + placeLanguageTextInputArea(); +} + +void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position) +{ + if (!mWindow) + { + return; + } + + // The active preeditor's caret and bounds where it can give them. + if (placeLanguageTextInputArea()) + { + return; } // Fallback: no preeditor (or it couldn't compute its bounds). Use a // single-line guess centred at the supplied caret position, in line with // the pre-improvement behaviour — enough for the IME to place its popup // roughly under the cursor. + const float density = SDL_GetWindowPixelDensity(mWindow); + const float div = density > 0.f ? density : 1.f; + LLCoordWindow caret_win; convertCoords(position, &caret_win); @@ -4276,6 +4310,10 @@ void LLWindowSDL::allowLanguageTextInput(LLPreeditor* preeditor, bool b) if (b) { mPreeditor = preeditor; + // Tell the IME where the new owner's caret is now rather than at its + // next draw: the first key composed can open the candidate window + // before then. + placeLanguageTextInputArea(); return; } diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index f4f7fc6f49..fb2f62a9e8 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -195,6 +195,7 @@ class LLWindowSDL final : public LLWindow void bringToFront(const std::string& activation_token); void setLanguageTextInput(const LLCoordGL& pos) override; + void updateLanguageTextInputArea() override; void allowLanguageTextInput(LLPreeditor* preeditor, bool b) override; void spawnWebBrowser(const std::string &escaped_url, bool async) override; @@ -474,6 +475,12 @@ class LLWindowSDL final : public LLWindow // just-the-commits from SDL3. LLPreeditor* mPreeditor = nullptr; + // Hand the platform IME the text input area of mPreeditor, the caret + // and the preedit around it, as the preeditor places them, so the IME's + // candidate window opens under the caret. False when there is no + // preeditor or it cannot place its caret (scrolled out of sight). + bool placeLanguageTextInputArea(); + enum EServerProtocol{ X11, Wayland, Unknown }; EServerProtocol mServerProtocol = Unknown; From 326f037d87a7f7c3c0e0ceffee6bd33ba0d7dbfd Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:53:18 -0400 Subject: [PATCH 4/9] The clause an input method is converting stands out in the composition on SDL The SDL backend handed every composition to the preeditor as one plain segment and read event.edit.start as the caret alone, so the clause a Japanese or Chinese input method was converting looked like the rest of the preedit. SDL marks that clause with start and length, in characters, from the highlight ibus, fcitx, XIM, text-input-v3 and Cocoa report. The composition is now split into what comes before the clause, the clause marked standout, and what comes after, as the Win32 backend does with its target clause; the editors draw a standout segment with the thicker underline. The caret goes to the clause's start, where the candidate window belongs, or to the IME's caret when there is no clause. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llwindow/llwindowsdl.cpp | 63 ++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index d7dde43310..2a033a94a0 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2414,33 +2414,54 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) } const std::string_view preedit(event.edit.text); + const S32 preedit_bytes = static_cast(preedit.length()); - // event.edit.start is the IME's caret inside the composition - // counted in CHARACTERS, or -1 when the IME hasn't reported one. - // SDL's own backends settle the unit: fcitx and the Wayland text - // input both run their byte position through SDL_utf8strnlen, - // which counts codepoints, before dispatching the event. The - // preeditor counts bytes, so the caret has to be walked out. - // start == 0 is a legitimate "caret at the beginning" value and - // must NOT be confused with the -1 default (the earlier `> 0` - // check did exactly that and pinned the caret to the end of the - // preedit whenever the IME started the cursor at the first - // character). - S32 caret = static_cast(preedit.length()); + // event.edit.start and .length mark the clause the IME has + // selected — the one being converted, which it highlights — or, + // with no clause (length 0 or -1), start is the IME's caret, and + // -1 when it reported none. start == 0 is a legitimate "at the + // beginning" value and must NOT be confused with -1. + // + // SDL settles the unit in each backend: ibus, fcitx, XIM and the + // Wayland text input count characters (fcitx and text-input-v3 run + // their byte positions through SDL_utf8strnlen), Cocoa counts + // UTF-32 units, which are the same, and Windows UTF-16 units, the + // same short of the astral planes. None passes a caret on as well + // as a clause — ibus and fcitx drop it, XIM sends the clause in + // its place — so the caret goes to the clause's start, under which + // the candidate window belongs. The preeditor counts bytes, so + // both ends are walked out. + S32 clause_begin = preedit_bytes; + S32 clause_end = preedit_bytes; if (event.edit.start >= 0) { - size_t at = 0; - for (S32 remaining = event.edit.start; - remaining > 0 && at < preedit.size(); - --remaining) + const size_t start = static_cast(event.edit.start); + clause_begin = static_cast(utf8str_offset_from_codepoint_index(preedit, start)); + clause_end = clause_begin; + if (event.edit.length > 0) { - at = utf8str_decode_at(preedit, at).next; + clause_end = static_cast(utf8str_offset_from_codepoint_index( + preedit, start + static_cast(event.edit.length))); } - caret = static_cast(at); } - const LLPreeditor::segment_lengths_t lengths { static_cast(preedit.length()) }; - const LLPreeditor::standouts_t standouts { false }; - mPreeditor->updatePreedit(preedit, lengths, standouts, caret); + + // What comes before the clause, the clause standing out as the + // Win32 backend has a target clause stand out, and what comes + // after; a part with nothing in it is left out. + LLPreeditor::segment_lengths_t lengths; + LLPreeditor::standouts_t standouts; + const auto add_segment = [&](S32 length, bool standout) + { + if (length > 0) + { + lengths.push_back(length); + standouts.push_back(standout); + } + }; + add_segment(clause_begin, false); + add_segment(clause_end - clause_begin, true); + add_segment(preedit_bytes - clause_end, false); + mPreeditor->updatePreedit(preedit, lengths, standouts, clause_begin); // The composition moved the caret, and with it where the // candidate window belongs; the IME is told now rather than at From d0ab70de23d9abbabf439cb16fa772c156f7f1ec Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:54:21 -0400 Subject: [PATCH 5/9] The main-row slash is the slash key on Linux and the Mac, and only the keypad's is Divide LLKeyboardSDL translated SDLK_SLASH to KEY_DIVIDE, the keypad's code, so the main-row slash fired the start_gesture binding DIVIDE has in key_bindings.xml: a / pressed in world, or with anything but a text field focused, opened the chat bar with a slash, which on Windows only the keypad's does. LL mapped VK_OEM_2 to '/' there for EXT-3650, and SDL now does the same; the keypad's slash stays KEY_DIVIDE and keeps start_gesture. The inverse map gives SDLK_KP_DIVIDE for KEY_DIVIDE and SDLK_SLASH for '/', and mapSDLtoWin already sent the two keys to plugins as VK_OEM_2 and VK_DIVIDE. alKeyAsBound still reads KEY_DIVIDE as '/', so Script Studio keymaps hear the keypad's slash and keep bindings saved as it. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llui/code/alkeychord.h | 7 ++++--- indra/llui/tests/alkeymap_test.cpp | 2 +- indra/llwindow/llkeyboardsdl.cpp | 6 +++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/indra/llui/code/alkeychord.h b/indra/llui/code/alkeychord.h index 38d931bdf2..332e134856 100644 --- a/indra/llui/code/alkeychord.h +++ b/indra/llui/code/alkeychord.h @@ -33,9 +33,10 @@ class LLView; -// A key as the studio's keymaps name it. SDL's windows -- the Mac's and -// Linux's -- say KEY_DIVIDE for the slash key, which is the keypad's -// slash on Windows, so a key bound as '/' is heard from either. +// A key as the studio's keymaps name it. The keypad's slash is KEY_DIVIDE, +// and was the slash key's too on SDL's windows -- the Mac's and Linux's -- +// before they gave it '/', as Windows does; so a key bound as '/' is heard +// from either, and a binding kept as KEY_DIVIDE reads as '/'. inline KEY alKeyAsBound(KEY key) { return key == KEY_DIVIDE ? KEY('/') : key; diff --git a/indra/llui/tests/alkeymap_test.cpp b/indra/llui/tests/alkeymap_test.cpp index e4324c0726..792dfa02e7 100644 --- a/indra/llui/tests/alkeymap_test.cpp +++ b/indra/llui/tests/alkeymap_test.cpp @@ -136,7 +136,7 @@ namespace tut template<> template<> void alkeymap_object::test<5>() { - set_test_name("the slash key is heard as the SDL windows name it: KEY_DIVIDE comments as '/' does, and binds as '/'"); + set_test_name("the keypad's slash is heard as the slash key: KEY_DIVIDE comments as '/' does, and binds as '/'"); ALKeymap map = ALKeymap::standard(); ensure("Control with the slash key as '/'", map.lookup('/', MASK_CONTROL) == C::ToggleComment); ensure("and as KEY_DIVIDE", map.lookup(KEY_DIVIDE, MASK_CONTROL) == C::ToggleComment); diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 7d07582951..bd643b4c9a 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -128,7 +128,11 @@ LLKeyboardSDL::LLKeyboardSDL() mTranslateKeyMap[SDLK_MINUS] = '-'; mTranslateKeyMap[SDLK_PERIOD] = '.'; mTranslateKeyMap[SDLK_GRAVE] = '`'; - mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; + // The main-row slash is '/', as Win32 maps VK_OEM_2: LL moved it off the + // keypad's code there because that broke typing into media prims + // (EXT-3650), and as KEY_DIVIDE it also fired the start_gesture binding + // the keypad's slash has. Only the keypad's slash is KEY_DIVIDE, above. + mTranslateKeyMap[SDLK_SLASH] = '/'; mTranslateKeyMap[SDLK_SEMICOLON] = ';'; mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; From 8756c96cd3ea157e236249bc7d6b71a937fbdf49 Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:56:29 -0400 Subject: [PATCH 6/9] A composition shows in the focused field after the window comes back from Alt-Tab on SDL The SDL backend forgot its preeditor whenever the window lost focus, on the belief that the focus manager clears keyboard focus then. It does not: setAppHasFocus leaves the field focused, and no editor allows language input again when the window returns, so every TEXT_EDITING was dropped and an input method composed blind, its text arriving only on commit, until the field was focused anew. The preeditor is kept now, as on Win32, and only a composition in flight is reset: SDL stops text input with the focus, and what the IME does with it after never reaches the window, so it would have stayed in the text. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llwindow/llwindowsdl.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 2a033a94a0..fe5dc8199e 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2572,13 +2572,24 @@ SDL_AppResult LLWindowSDL::handleEvent(const SDL_Event& event) break; case SDL_EVENT_WINDOW_FOCUS_LOST: mCallbacks->handleFocusLost(this); - // Drop the IME preeditor reference defensively. The viewer's - // focus manager normally clears keyboard focus on app focus - // loss, which triggers allowLanguageTextInput(nullptr) — but - // if any path leaves mPreeditor pointing at a widget that - // thinks it's defocused, a stray TEXT_EDITING event would - // update a non-active widget. - mPreeditor = nullptr; + // The preeditor keeps language input: keyboard focus stays on + // its widget while the window is away (setAppHasFocus leaves it), + // and nothing allows language input again when the window comes + // back, so forgetting it here dropped every composition after an + // Alt-Tab until the widget was focused anew. As on Win32, only + // what is being composed goes. SDL stops text input as the window + // loses focus, and what the IME then does with the composition + // reaches no window, so the preedit would stay in the text. Win32 + // commits it (interruptLanguageTextInput); SDL can only cancel. + if (mPreeditor) + { + S32 preedit_pos = 0, preedit_len = 0; + mPreeditor->getPreeditRange(&preedit_pos, &preedit_len); + if (preedit_len > 0) + { + mPreeditor->resetPreedit(); + } + } // Sync our relative-mode state to SDL3's. SDL3's keyboard // layer auto-disables relative mode on focus loss; if we don't // mirror that, our member stays true and setCursorPosition From f4519739c2120278e812ea77e6b7c61d38c85232 Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:52:50 -0400 Subject: [PATCH 7/9] The SDL resource tree carries only the cursors the SDL window loads res-sdl/ held sixteen BMP cursors nothing reads: arrow, circleandline, cross, hand, ibeam, llarrow, llarrowdrag, the five size* cursors, toolpickobject, toolpickobject2, wait and working. The SDL window takes the arrow, hand, I-beam, crosshair, resize, wait and working cursors from the system theme, and LLWindowSDL::initCursors names none of the others, yet the Linux tree shipped them all. They are removed. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/newview/res-sdl/arrow.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/circleandline.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/cross.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/hand.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/ibeam.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llarrow.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llarrowdrag.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/sizeall.BMP | Bin 630 -> 0 bytes indra/newview/res-sdl/sizenesw.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/sizens.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/sizenwse.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/sizewe.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/toolpickobject.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/toolpickobject2.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/wait.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/working.BMP | Bin 2102 -> 0 bytes 16 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 indra/newview/res-sdl/arrow.BMP delete mode 100644 indra/newview/res-sdl/circleandline.BMP delete mode 100644 indra/newview/res-sdl/cross.BMP delete mode 100644 indra/newview/res-sdl/hand.BMP delete mode 100644 indra/newview/res-sdl/ibeam.BMP delete mode 100644 indra/newview/res-sdl/llarrow.BMP delete mode 100644 indra/newview/res-sdl/llarrowdrag.BMP delete mode 100644 indra/newview/res-sdl/sizeall.BMP delete mode 100644 indra/newview/res-sdl/sizenesw.BMP delete mode 100644 indra/newview/res-sdl/sizens.BMP delete mode 100644 indra/newview/res-sdl/sizenwse.BMP delete mode 100644 indra/newview/res-sdl/sizewe.BMP delete mode 100644 indra/newview/res-sdl/toolpickobject.BMP delete mode 100644 indra/newview/res-sdl/toolpickobject2.BMP delete mode 100644 indra/newview/res-sdl/wait.BMP delete mode 100644 indra/newview/res-sdl/working.BMP diff --git a/indra/newview/res-sdl/arrow.BMP b/indra/newview/res-sdl/arrow.BMP deleted file mode 100644 index a8f6da64b573f4136d742e98fbce372b389fa966..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH`XE+vY6vuyxtcp<4qG2>iQnXP@k=Y(r3Z+7%U0O6KLMas*geL7}_0XVFv}h`{ zl=ga`=gIYc;_>DE_@3*!$94bi|GCb6&biI3jpY!Vu{7ujcUrYWidrD1wUd-^6%ElM zB}Jn~jcDAsG1Ah~$jHdhq)8KGWo40*lS5u!9t8yj6crU|+O#Rnnl+<&^X4ciDWR;a zOp6vRP*G7qRaF%=H8oncY)PwDt!Ul4HR|f>XlQ8ArcE2#wrxwhcI{~2zC9f}bU;&6 z6D=(*I(F(-6#-MiDHM-O`T>`AX) zz0lX!$H2gV-o1NcXlO{EK7BAUGNNzaz8D)D)30AY`uFdTiHQlOrlt%SFo1yr2Qp~T zAO;T}%#a~N7&>$)!-fsR%*+gPb8{>#EEqm~I3q@kz|zu^kt0VkYSbvKtgIM4dNgCk zjKSL48XFrM#*Q6}t*tF~c6Qj?+vDKifTN=$PEJmY8#j*eC>mm*_UzfrnKK6;A0OtKEA%b`1$$a@9)oo1q%oW2p}*pkcA5u5)>4~ zqD6~Xym&E7mMmfE(xoh0wv6S=m$PEU3RbRM$*NVW2o4Tr_3G8ES+j<J9n~c*Dm7X;@G`=H+%N%Vej6(#K*^zkdQ!PVj}zY?PLG` z{Tw)OfP)7Ql9ZH0a&j_<4jm#TC56<~RMOJYIDGgpM~)of=+UDbJ9doY$B%R3#0k>V z)5*xl;N;1ZoH})i)2B~!=FAz+o;}OCbLTjJ{yY~hT;Srxi(I;NiOZKSlbM-GR#q0- z+1cdeir|pU>5+SGjiW8rQF1=f;g26ciLtSXju-n>V?2>lU|f z-=?Ujh&y-gaQE(Aii?XWDJkLJy?flhf1d{r9`NwtLmoYPL}_U$Wo2bNe*BmxPoD7f z=~JFPd&cwU&w26U1?A=CynOkRSFc`CQBgrLn-o1Or`}gmu zuCC_8hYx)G_>r2L8a{pc#OKeS`SRrpU%!6k+qZ9g|NfmHKYsA@=TCn9`o-_xzxng$ zkLZ2>+kcP&Bxh2XYl$}+s6_)esK2q@*NLQc^T%(13;w8zL<&O`}GQXxz9lO`0^JY15|2$jH#FSu zI(0%(Q4u92B|3NROqVWQP*zr^YuB!H>(-6#-MgcrqJpZbDr#zKsH>}^p`k&K9zD?1 z)TC$6o@i-l(W_T4diU;4pFVx)+qW;;+S>H%*AE>X9dvbd>EFLU0|pF0Pfw450|zo_ z&>#j69?Xy-L(tdPXXwzO7#J8}XlTf=VZ#_cd^jUUj9}!*kr){nF>2H(MvorNm@#88 zHa2GL*s++Hm@sbKIL413kEy9CW@cuXo0~IX!UQZVEU>h+Wa7k$Oqw(aD=RCkt*x=K zv0?J$$=KT3GG)pXrcRy8v}x0rK7BfNc6Q8|F@u>iXEJNnEbQ&=nLT?pbLPy!!NCDX zM@O8ToR~XzF7xKi!`a!H`Sa(qV8H@hTwHKE%^KFOUCX+4>sY^jJsUP`VB^M( zY}&Mm&6_u~Wy=<}ZrzHPmlxjN-fY{pjqTgF*g9e|GNN$*x_y z*u8r<0RaI71_rWc&mQ*f-OIjx``EvKKL-vR;NZc796EG}!-o$O6cj{oa4<)X9O3BE zqlAQn5E>fFv17+Le*8FLVPS-ahjZe@2~M6oNkl{hr%s*X^y$-_Idg`{$Vj51qKJ-; zCMG6^*w|R&;^K&pk0&7^fwO1Nl9-rCQc@D<&Yk1@`SV=3aDj^#FLLS9B`#mS%#|xw zNKQ^BB_)N_)Kt>a(ztr{D(UIzT)TFS>({SyfmDJkLg>({(_^M+yzU-(?)S|Nc#R zc{vpo6~g!ZKmPj_5VW$Q&Q}QgEEsi3L{KOYNNUL;#KQEIIcf+*SQM>YAc$6G72%o= zVlKqueKiwtNQBeHr$2(KNF}b5SK+$27}vr@A#r7@%>K9wcEY>Wo>-%TBL1fWHF#wL cae-@Mu|qYRzxfM);oti!lne9!^P1@V7thjLp8x;= diff --git a/indra/newview/res-sdl/cross.BMP b/indra/newview/res-sdl/cross.BMP deleted file mode 100644 index 0b4672d4d61f54cbc0a4cb603e9081525bd3e0d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH|cQ6oa9LGOOMnoBr22CS`N=rngDJi3b>~>0ngd|Nug9Z)Jpv($cm8>$Fv`b5S z(4-{N-TOy(ulJAlu6ys^@7?#F-~E2~{C@ZSKF>Xmk%_JdKcOoKDvgoSFADIh(3qDN zYbFAX#U?f_0s^#Z)r!`wTO%kaNSiio5E2qXSXdYl5fMa1MQPi%En;F~h>MHUu3bAM zBqWfOl%#$8_H^jb0Vyddq@|^ik&!`GR+f$(J0d41hrGNzojP?wK|z7eojcQ|OBcF! z?Mk<9-B46iL`g}B?%li7qel;V_UuWoUcKnuyElFM^g&r!85I>3R8>_`Q&XdF-@d4; ztD~Wzfu^P={rdGoOG^uFZEbXPbm-r|KLZ8~VBo-k=<4b+XwV=A4<5{rAww8CbST4y z4MR^)kKx0Iqpz=zfq?-dMvTDF&=4adBSwxK$*57I7(IG4#>U2s88e2lW5+UX+&IRM zAJ2pd6PP%0A|@s#Oqw(aQ&UqWPo9jKnHf{2OkwKOshFFaV_{)|rKKfSR#r@#HjU}i zr(X3w6@ zoH=utJ9jSg=FMaN{P`?cuz-aN7vkpT#-c@wSiE>K?(Xg^S+azsOP8{2*)oLgMKKT0jvTD^T{QUe_y?QnN{{F04vxb0x0M@Qu%er;z zSigQf8#ZiUSbt~JpZDafP?SzGe z5gs1SjvYJLxpODGcI{&K?%hO0L=YJn$(}uX*t>Tx`}XZ)|Ni|%MMZJozyYG8qlt-$ z;o!l896EG}!-o%ZZf-8; z&YdGKFOU5EdtxDk>_te*HQ(ZrtGJ&70i1b&K1#Z*%9)9q!(}%e{N|xPSjXm6eq| zc<_LS4;>8PIzI@56SFd>e`ZaIfyy5NJ zx4e7zj_T@aYHDhD|NcE6K78Qg$B%sa^oh@(KlA0w7iw#3sjI8w>({S*`}U3c`g*>9 z|4u_gLzBM$@$Wg%_?rH0Gg@%`&((ka1T@ZX#&0T`Zp&ZzU1dxAn;ZT)egANN3+MNn IE&uhz4{@k^761SM diff --git a/indra/newview/res-sdl/hand.BMP b/indra/newview/res-sdl/hand.BMP deleted file mode 100644 index 2a092fbb7feb8f112168a0b95d50401a4db897b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 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 diff --git a/indra/newview/res-sdl/sizeall.BMP b/indra/newview/res-sdl/sizeall.BMP deleted file mode 100644 index 03d9bf4654030a405d8553640c77c19072c85f89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmd6hy%B&g2!#n}XA{l^kjgpiT_-bUs|eBjc6PqIm%srZoL4}|3i=*ue(hk<=+U+U zn7yWERf;htlf_?6KM}g&5HCFBDAG50k)Z*Bxg&V7yb*NTR0)#nvX>Q@%dI}o)5NEF SKPjQojXK{?-F0Q_Fa8^oL^|65 diff --git a/indra/newview/res-sdl/sizenesw.BMP b/indra/newview/res-sdl/sizenesw.BMP deleted file mode 100644 index 559579f40e4b563d75af4507d21f53967706a048..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{XIKwv7{-4oM5JVts8p1Z6p}(p8X8o{UL_JjR1^(6nxuh@qG3f*q>PNL3eiNi ztd>!sPJcSzPM!1VeDYk^bG`5N-1l=|*ZceM8dzwF@~gB&K(+Cv(9}XS35|0pvEPkQ zqbO*>AtXerR;>^g7Dhxwgx0NF)22-u+O}p=;N!bnDiQ?%lg1EiH|Vj0`<`^gvctmYzL((yLc5 zC=b4efy%KqJpZbD*gKPqksSY3>YwgfddDk zrl!WAL4#0NS7-3x!Dwh`psA_JkRd}DI&>(*h7ChYON-&dhoh~n&4>{r(9zLBS67#j zBS$i7)F?)e9*v%!9%IIgL0?}V0|Nubjvb4kp&{eOjl;;u2xDVoOiWBLH8o}Y`0<#T znPF~jj)jE z>CBihgPAjDGHcc>X3w6@oH=utJ9jSg=FMaN{Q20~*RDaBy&7;lhP1TC@m9 zM@JSfUW}8I6HAsXVd>JPEL*k=XJ==YFJI1z6)RY|awRS6*W%&ffv2Y@>(;Gf{rdHId3oXO?TwF*55B&>Y}l}YjT<+zY11Y)Z{Ez7 zEnC>Sbt~JpZNtyckL}yHvt!2&{Qdn22nZlBFp!|2AcBK~2?+^d=gyt%+O><&&`@^o z-c49o7~$dJL_|ao85zl*J$u-@cQ5<)?IS8Giv9cdbKt-M4jw$np+kp=j*ccKCWga@ z4|C+m5n^LwiHnOPK0cm=ganQrJ<73T$2flcI44e=;N;1ZBqkeMMtpFT}eQWD9@ z$(%WJhO=kSl9G}_YHBLy&Yk1@`SYZurE%fH1=7>g$;imy;>C+xx^#)lmoIbW$`vv* zGr4;8D%Y-E&WF=e&6Ff|oB}^6J$qUcY|Ln>TNG`}QqmWo5j3_m21P-}B+a2R?rM$fr-AC@(Lk zqN0Mz%1WxLs;I86=JV&zeEIT)uV26N?b|nMYHFyht);H6j_=>U^W(=4e*XMPeSJL* z4Gn_#{i!AbzkkDKaR_*|MC_N|0?_}m-{@&Jfd+vpFz}C_#%YtGr3^tr^ZMTj%|Z|u T{$;;q{TJls(;H2laoVUULFMn1=_S}gQB7$ZQHh`UAuO)Z{MB{9Xg<-q=d4vGAb%6bnMuXPMtc@ zxpQY!RaNQIr3+oVc12B1jc(n#(YDR9x{rmSvQ&W=x0|qc~;6Mfq8pPnigVEB`LR(v#Awz~Rbm&lYbac?w)n(YQVGJKW z96dcfMvNGNzP>&N1_l@!8e(K*#K@5&88vDYqeqX%*w~mcW5zIc>{!N)8^`$Z<1sNY zVZww7n3|e0apFWKO`3$6nHiHOPsZHboGDYLFm>uwrcIm1^y$-?F=GZZXU=5StXa&S zJsS%P3+Bw3!`!)ZnKy49mX?;xpFf`k3l?ByWrel1H47ImWYMBUEMB~rB}xT zY;3T#wPo3|W!Tx-v3&V*?CtGwaByJ7iWRI}xsp|@R^jOAh?A2Ot5>ha+1VKv7Z=v7 zS;N}3YjJgT#m&tPcXxNzty_nOhX?D|uV=%C4S0Hb;^pOqx3@PNH*Uno#|K|uUp8&p z#OBSL*|KE|Teoh-&(9Bke}A@Z+eSb@0Nb~3XUC2m?A*DNUAuM>7#PUz-Ma}23L-c- zn2?YVLPJB@vu6)`_wHrizJ2W9zn=pK4sh_`LBhhqICSU`;o;##L_~1-@L`S|Il|GS zM~RG#Bq}P3=;&yU9XrPH+O=z3zkZz?H*RqA=1p$hy2b6=w~333=rW+qu#S!8EtlarG} zZf-7b-@fJDyLY^Q|DL?OJo5ANDJUqQu&|I1A3pH$<41~$iYP8F=F_K7l$4ZET3Sk3 zSs9-{f9A`VFO-*;Q&CaD*RNlxtgNJ}s*39BYHDg~`1b7^wY9a>)z$I+`*-T=>uG3c zXzcG_{6>JLku<}s(QX3jPy6o&1b=aZVDR@_`QiUo?w{%Z>o-?_bNwea!%y%Qo5I@& OLjd4UCjZt=5cm)KU57CM diff --git a/indra/newview/res-sdl/sizenwse.BMP b/indra/newview/res-sdl/sizenwse.BMP deleted file mode 100644 index 6d069fa7658e571f4bd1f7cd71e0fa3b6708f8d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{XIKwh7{-68RI-aQA`zizi6W&%$X;!dBxIIRMB1`tg;12eD$&rAtV$^gWfx7O zLgDRSK9=|W@_zGN=ef?gp8I~D`<(m3F)-5-r!lldK&jy*|2u{F4K&oHB%2bU22hZK zO-P7Vty&>0ER2YV2%@5*v~JxRF)=a3#l?}3kf2SQHb_cJ(zb0|+O=y(`}XbW(4hkz zJ9eZ~r%rV4+!-k;DWs*P>C&YOUAuNgMn(o%Sy{Su>qhtP-RaSz2R(cCL{3hQUcGwJ zyLWHo<>l$qrwmN=ghIIFLbu1~GW>V3d`WQBhH0 z$dDln9Xb?MRaMl~)KFJfM?*scO-)UP4I74*mKMW@4`;-P5ol{`qobq4$dMx%HEI;P zy1I-WJsLedJ@obU88c=K1_lNg8X96`WQ4J?F(xJ^j2%0capT5eYHG^(@#C2=VFD8; zPQ=X2j7gIwF?sT2rc9Z_)TvXMHf_~B>uy^lXf`WqBw{IW& z_wVPxfdd>oc#uPf4iOw2%;Cd_IdbF(M~@yQBqW4m$BuFQ_;F60I6-J=C}Ck?oIH7w zQ>RW59v)6aLyE?l_4#fulYbmn? zNTQ;mh>nit+O=!M#Kds@`gLyHxIt`eEOBvh#K*^zkdVO5n>R^JOe85OiR9#DQc_Y# zO-<$2ty`p}rE&ZAZPL@zxpU_ZckkZi-o1O=zkiL@%Zs$o;-O%ettd$1qD2P`jltSp7H$oa|#O!DJm-B#fulbeEE`B zuU_%`^=sa|dBfYcZ+Z9b9mU1Pl$4b4{{4GCeE2|VX(?r8Wt5kfQ&CYtWo0E*RaJca z_>oVaKJoeUXTE&-LUnaDH8nNV*4Fa%>sP*g`^NY0->IvsqrSeLA3uKZ^XE@~{rV+% z-{1JJ4m5q2EwcrV{?XG$Ld%{vz=GA1Koi_N4(Y$UTfiG93x+o^n~8?zf7AZs(**s^ WD>sQX;(sJGn%m6H{+9kv2mS$!#fbO- diff --git a/indra/newview/res-sdl/sizewe.BMP b/indra/newview/res-sdl/sizewe.BMP deleted file mode 100644 index 878df453a4a9ed6ff177d690f1aab46e51c71dfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{cT^8-6vsa)lqjhbp^$`7p)%4i8dMUZ$S9d9*%TEO$|wzGRfN#8nzFT!UC5|Z z%AQ4$e)M|J(R)sRzvsB;+;i`9zjr?OIgg>4mMA|-O9WKwHKhg?q5-J4ON;+vgz7;7 z3xtpm&6+hsSXdYl5fPd3~Os#Pn*#l>mex;1Uuv_V2b0!c|p z+O}+AJo*;=-an1 z{rdHzfB*idtE;1-p@F8RCIbcxVBo-k3>q{DEiEmywYAaF(P8l5!3-HPgrP%+GHlo| zbaizZK72TOdV1*V>tkSGfT5uwBSws1IM8#>NI) zTU(}1oyxRn)3CF%WBT;z%$PBQnKNfHYt}66?d@@JaA5ZA**H2nGH1>l=FXkVym|AO zKYu<87A#=l!i6|FIk9NbBAlI_adB~B@#4j}y1KGt$r6?>UCOd$%UHgAIV)DIVCBk{ ztXj2-)vH&tX3ZMh+}vXX<=ZC+)KU=nJVe8hdY}>Yt?c28#5D-9MU?4ko>>wy8h~VI0LPA0a z4Gm@I&YgsXg%KVe&aPd%*u8r&Cr+H;TNA>((u9 z-@eVAJ9oHy_b&JD-6KCgpMrt{?%%)9g9i_I`0ycxg@rtN^oYlgAM@nN6P`YON>Nb} z#l^*xl$7x7*)vK@ODQWWqrAMF=g*&0QBgr({T;)YMR0Tg$g^-}wIhJ9Tw+ zg8BZ^|KtYvwXFuxsA(Fu`H%d=p?=-JzI%c42UdR+yoP_Nv4a5n9bZ@1C_z*4f&#ze a8>j!-LBo9i)t;bU6Z1D}>93*b8~6b<0EaOE diff --git a/indra/newview/res-sdl/toolpickobject.BMP b/indra/newview/res-sdl/toolpickobject.BMP deleted file mode 100644 index 25469fc3a86c94b64c87866a6c1fdc227d41e7d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmdUvcQn^)7{EVDqN2T#kTjH3N=qpc(NHQXWktIrG?CKKBGS&Nv}h{HY9d9_FxmrA zMn*<;e?Q!=dk*ej_uO-zbKdX!eBaOWJnu8kd9@7G#iD8Rq)8LR#KdUYv?=1^;z&qH(5zWAnm2Dwixw@Al$1nDN{W^( zThgjkD_Xa1O`A4tXxp|e?b@}Yef#!w=+J?V9XrygQztri?o5|1UFh1iE7H=^$jHbb zD=SO4ZrzZRlcRh0?#Ro_qoAOGqM{-_dh|d^Nr|34d!nqYOs`(O=-sA&37__vs7&~?>or{^78T01NWB&a4n46npVPS!#r6pEYR#;nGvtYpjY;0_> zwY6p8!i6kaw1~xv7qeu^5|%Dq%Ccq4SiXEYD^{#v<;s=V+1asb)hg`m?ODBgH4Y9A zI66Aw(;Go+qRAE+qbi0#|}I^JlMH&C%bm-V)yRd?Af!2y?giK>FJ4=mlyl??ZeyK z8y_DZ_V3@1udgo$4jka%!Gjz+bcn-;4|C+m5sn@`%CTd|IDY&%etv%V`}-3R5I|sH zASX_o;N;1ZoH})ipr9a5pFYi*GiNw^_AKYlo#XuZ^8^P66A}`_g$ozBc<~~aE?wgC z<;z^Ta)ql`uM!#>%C&3PxPJXQVPRq1xN(E<@NjP4yh%hv1d)-EL`6jr9UVJvc=+%kj~+cDF)@*(q$D0c zeoS(5GEbg7Atfb+r%#{q?AbG(KYz}P7cWRnO(iWYjr8<%GBPrF`SK;NUcKV=>({(_ z^Mb zULN`R`4kisP*_;Vw{PDlDk`G5xR{cX5=u);`TqSoWo2cQmzPsfQ9)&8B|m=r;OEbu z{QC7vSl|CoXgF;_VGSDm18)FVg>8rn3>v@!Mm@Z`B%yDe$qS!p!JGt8IJBC-T7&x= zuWPQq<5x$h^I>?0 P799T9yuQ5t_47XfnucV} diff --git a/indra/newview/res-sdl/toolpickobject2.BMP b/indra/newview/res-sdl/toolpickobject2.BMP deleted file mode 100644 index 09df69e675e89c8797bf03c3a96095248e45fd3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{cUX>X7>Ca^iHf9*hP04Ph&D+}*`ts>%c!griX??78D&&bX2VK$l)X0O|+xo$1o03thW*rCYad7#SJSy?b|h^yop)o;@)(Hl|mvUi9wW z8xs=~OifKOGc&{7+#CxF3oI=yv9hwFPoF;Y?b{b?Yis)T>xYev4gLG~$JW*sJ3Bk< z?d@@JaKO>gkpTk+;N;|lv$Hb;2M%P=pg{~CJeVOvhA?#KP=*Z~#_-|888Ko6BS(&8 z)TmLoxVYfz>dNTRqZu=13}eTR#m&u)apT4@e*AbQOqjsLi4&PLX%dqsPiD%LDNLO@ zm1)zaF@5@UX3Utu%$YNBcX!9b!-H9~W-)vAZ05|F!`!)Z@$~e>%gYOIZ*S(!o5%e5 z^I5Q90Sgx{WYMBU`1ts+c=2Lu!NI|-UcH)-kPt#cLs_$C4Qtn~W!<`UgoTB%e*JnjY}i0}csLOe z5p3MJk;uqMHf`F(=FOYgvSkZfw{9gWDvIdnXtr(J#`f*o*|B2>J9q9RCMJg1*jVD? z;@Guo7xD4&?B2bbgoFeV6BF69XAgV#?q%P;eeB=Ap92RDaPZ(kl9G~0PEIBzC56<~ zR1O_F#Noq-IdbF(M~@!m*s)`zrKNHF_;J$H(>ZbC1Se0Pg|^7Hd~@!|z9U%uqkt5>{!{hBv#-cV3bz}vTPDJ(3csHlkI;$lil zN+>NY<=wk?ynp|m4jA4RWHJ|>#OlE#x*x0|Jt#zcCknE UckzG9F6^zCV!Z diff --git a/indra/newview/res-sdl/wait.BMP b/indra/newview/res-sdl/wait.BMP deleted file mode 100644 index 26dec59afe10818db0cff219f91d41dc647dd754..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{cQ}`87{@q>0cll2lSDEkz`0Xi2opc9gb4SeLA(B_%p{?o5|1T~Jn5Mny%1u3fvLs;Wx2ZrxB*Q=@zL?)2!Ua6&Wsr|m^pJMvu4d=_Uzf%+S)Q_&K%~>or|5F z9rpJ2%$qk42L}fn9UYlJe?Cr5PApik0B2`s7A{9dkvV^5em*VQ` z%Ccq4SiXEYD^{#v<;s<;TD1x{H#b(VUX8oEJ8Rag!NbD?Pft(Qu3gKzb?aEaemxsD zY+&QYjd*!^;qC2>kB<+&zP|YR`Qh*H&!$bA*t~f&TefUr>(;Go+qRAE+qbi0#}0Px z+(|${0D*yl?Ao=9-Me=a6cogsJ$u-@cQ5<)?PLG`{Tw)OfP)7Qa_G<@f`fxOeE2X& zjvOH*B!tk=P{P8(IC}Ib$BrE%JUpC;hzKGhBZ-QNB04&nTwEOS@$n=iByjHBInJLy&xH#YxOnj*mo8l*F)@*(q$Dn1 zzRZ;?S4d7y=IYg}T)TFS>({SyFM0NcaQt`@AKfn10Ftn$fHM($jHbbGc%K{tSqv#vw8gZF;AX6Atxt?+}vF9^7454 z^eNAtJtIFqpXbk?^Wwz|3JMA+EG(p`sEC&@U-IhJD~gMYDJdzTw6v76vNB%3eoc9K zITaNZym|A6%F0Trs;YSV_AT$;z2p7+_k8&9fsY?Q^6AqjK7anqmoH!V`t>W{zI~&* zx|*7r8ft56h4cL%DJivee?q7g{Wbn2|Fc}QfdC8c;zx)S2=N~Z;r`bif3Tl|-!8Qd z2}TrJ2o{m`Lh!e|z6DYB^#*n2zxP)^pHL<6_|;wTEcC7qQTQ(c(fH>J{vj99(|_aW EJFbFWmH+?% diff --git a/indra/newview/res-sdl/working.BMP b/indra/newview/res-sdl/working.BMP deleted file mode 100644 index 26dec59afe10818db0cff219f91d41dc647dd754..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{cQ}`87{@q>0cll2lSDEkz`0Xi2opc9gb4SeLA(B_%p{?o5|1T~Jn5Mny%1u3fvLs;Wx2ZrxB*Q=@zL?)2!Ua6&Wsr|m^pJMvu4d=_Uzf%+S)Q_&K%~>or|5F z9rpJ2%$qk42L}fn9UYlJe?Cr5PApik0B2`s7A{9dkvV^5em*VQ` z%Ccq4SiXEYD^{#v<;s<;TD1x{H#b(VUX8oEJ8Rag!NbD?Pft(Qu3gKzb?aEaemxsD zY+&QYjd*!^;qC2>kB<+&zP|YR`Qh*H&!$bA*t~f&TefUr>(;Go+qRAE+qbi0#}0Px z+(|${0D*yl?Ao=9-Me=a6cogsJ$u-@cQ5<)?PLG`{Tw)OfP)7Qa_G<@f`fxOeE2X& zjvOH*B!tk=P{P8(IC}Ib$BrE%JUpC;hzKGhBZ-QNB04&nTwEOS@$n=iByjHBInJLy&xH#YxOnj*mo8l*F)@*(q$Dn1 zzRZ;?S4d7y=IYg}T)TFS>({SyFM0NcaQt`@AKfn10Ftn$fHM($jHbbGc%K{tSqv#vw8gZF;AX6Atxt?+}vF9^7454 z^eNAtJtIFqpXbk?^Wwz|3JMA+EG(p`sEC&@U-IhJD~gMYDJdzTw6v76vNB%3eoc9K zITaNZym|A6%F0Trs;YSV_AT$;z2p7+_k8&9fsY?Q^6AqjK7anqmoH!V`t>W{zI~&* zx|*7r8ft56h4cL%DJivee?q7g{Wbn2|Fc}QfdC8c;zx)S2=N~Z;r`bif3Tl|-!8Qd z2}TrJ2o{m`Lh!e|z6DYB^#*n2zxP)^pHL<6_|;wTEcC7qQTQ(c(fH>J{vj99(|_aW EJFbFWmH+?% From ca02a781379170eadc0440f8edb15063fec8f2ba Mon Sep 17 00:00:00 2001 From: Rye Date: Sat, 10 Oct 2026 05:56:54 -0400 Subject: [PATCH 8/9] Linux cursors are PNGs with real alpha, drawn sharp at every scale The tool cursors were 32x32 BMPs keyed on (200,200,200). The anti-aliased ones (sit, buy, open) had edge pixels blended against that grey, which the key missed, so they wore a dark stair-stepped halo; and one 32-pixel image was all there was, so a Wayland compositor at 200% scaled it up blurred, and an X11 HiDPI desktop showed it half the size of the theme's cursors. Each cursor is now an RGBA PNG in res-sdl/, loaded with SDL_LoadPNG. Most come from the Windows .cur, which is the same art as the BMP, pixel for pixel, or for sit, buy and open the same art with its real alpha. toolplay takes the .cur's boxed play button, as pause and media-open have, over the BMP's older dithered triangle; toolpickobject3 keeps the BMP's own drawing, which is black and white only. The hot-spots are the ones the BMPs were loaded with. Under Wayland each cursor carries 2x and 3x nearest-neighbour copies as alternate images, which SDL picks among by the window's scale; under X11, where SDL sends only the surface itself, the surface is scaled to XCURSOR_SIZE over 24, or failing that to the display's content scale. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/llwindow/llwindowsdl.cpp | 223 ++++++++++-------- indra/newview/res-sdl/arrowcop.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/arrowcop.png | Bin 0 -> 241 bytes indra/newview/res-sdl/arrowcopmulti.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/arrowcopmulti.png | Bin 0 -> 263 bytes indra/newview/res-sdl/arrowdrag.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/arrowdrag.png | Bin 0 -> 223 bytes indra/newview/res-sdl/llarrowdragmulti.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/llarrowdragmulti.png | Bin 0 -> 251 bytes indra/newview/res-sdl/llarrowlocked.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llarrowlocked.png | Bin 0 -> 243 bytes indra/newview/res-sdl/llgrablocked.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llgrablocked.png | Bin 0 -> 264 bytes indra/newview/res-sdl/llno.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llno.png | Bin 0 -> 213 bytes indra/newview/res-sdl/llnolocked.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/llnolocked.png | Bin 0 -> 247 bytes indra/newview/res-sdl/lltoolcamera.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolcamera.png | Bin 0 -> 201 bytes indra/newview/res-sdl/lltoolcreate.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolcreate.png | Bin 0 -> 210 bytes indra/newview/res-sdl/lltoolfocus.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolfocus.png | Bin 0 -> 161 bytes indra/newview/res-sdl/lltoolgrab.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolgrab.png | Bin 0 -> 244 bytes indra/newview/res-sdl/lltoolland.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolland.png | Bin 0 -> 198 bytes indra/newview/res-sdl/lltoolpan.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolpan.png | Bin 0 -> 211 bytes indra/newview/res-sdl/lltoolpathfinding.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/lltoolpathfinding.png | Bin 0 -> 250 bytes .../res-sdl/lltoolpathfindingpathend.BMP | Bin 3126 -> 0 bytes .../res-sdl/lltoolpathfindingpathend.png | Bin 0 -> 295 bytes .../res-sdl/lltoolpathfindingpathendadd.BMP | Bin 3126 -> 0 bytes .../res-sdl/lltoolpathfindingpathendadd.png | Bin 0 -> 312 bytes .../res-sdl/lltoolpathfindingpathstart.BMP | Bin 3126 -> 0 bytes .../res-sdl/lltoolpathfindingpathstart.png | Bin 0 -> 286 bytes .../res-sdl/lltoolpathfindingpathstartadd.BMP | Bin 3126 -> 0 bytes .../res-sdl/lltoolpathfindingpathstartadd.png | Bin 0 -> 303 bytes indra/newview/res-sdl/lltoolpipette.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/lltoolpipette.png | Bin 0 -> 213 bytes indra/newview/res-sdl/lltoolrotate.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolrotate.png | Bin 0 -> 254 bytes indra/newview/res-sdl/lltoolscale.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolscale.png | Bin 0 -> 246 bytes indra/newview/res-sdl/lltooltranslate.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltooltranslate.png | Bin 0 -> 268 bytes indra/newview/res-sdl/lltoolzoomin.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/lltoolzoomin.png | Bin 0 -> 183 bytes indra/newview/res-sdl/lltoolzoomout.BMP | Bin 630 -> 0 bytes indra/newview/res-sdl/lltoolzoomout.png | Bin 0 -> 172 bytes indra/newview/res-sdl/toolbuy.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/toolbuy.png | Bin 0 -> 1725 bytes indra/newview/res-sdl/toolmediaopen.BMP | Bin 3128 -> 0 bytes indra/newview/res-sdl/toolmediaopen.png | Bin 0 -> 253 bytes indra/newview/res-sdl/toolopen.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/toolopen.png | Bin 0 -> 1640 bytes indra/newview/res-sdl/toolpause.BMP | Bin 3128 -> 0 bytes indra/newview/res-sdl/toolpause.png | Bin 0 -> 257 bytes indra/newview/res-sdl/toolpickobject3.BMP | Bin 2102 -> 0 bytes indra/newview/res-sdl/toolpickobject3.png | Bin 0 -> 217 bytes indra/newview/res-sdl/toolplay.BMP | Bin 3128 -> 0 bytes indra/newview/res-sdl/toolplay.png | Bin 0 -> 311 bytes indra/newview/res-sdl/toolsit.BMP | Bin 3126 -> 0 bytes indra/newview/res-sdl/toolsit.png | Bin 0 -> 1492 bytes 65 files changed, 126 insertions(+), 97 deletions(-) delete mode 100644 indra/newview/res-sdl/arrowcop.BMP create mode 100644 indra/newview/res-sdl/arrowcop.png delete mode 100644 indra/newview/res-sdl/arrowcopmulti.BMP create mode 100644 indra/newview/res-sdl/arrowcopmulti.png delete mode 100644 indra/newview/res-sdl/arrowdrag.BMP create mode 100644 indra/newview/res-sdl/arrowdrag.png delete mode 100644 indra/newview/res-sdl/llarrowdragmulti.BMP create mode 100644 indra/newview/res-sdl/llarrowdragmulti.png delete mode 100644 indra/newview/res-sdl/llarrowlocked.BMP create mode 100644 indra/newview/res-sdl/llarrowlocked.png delete mode 100644 indra/newview/res-sdl/llgrablocked.BMP create mode 100644 indra/newview/res-sdl/llgrablocked.png delete mode 100644 indra/newview/res-sdl/llno.BMP create mode 100644 indra/newview/res-sdl/llno.png delete mode 100644 indra/newview/res-sdl/llnolocked.BMP create mode 100644 indra/newview/res-sdl/llnolocked.png delete mode 100644 indra/newview/res-sdl/lltoolcamera.BMP create mode 100644 indra/newview/res-sdl/lltoolcamera.png delete mode 100644 indra/newview/res-sdl/lltoolcreate.BMP create mode 100644 indra/newview/res-sdl/lltoolcreate.png delete mode 100644 indra/newview/res-sdl/lltoolfocus.BMP create mode 100644 indra/newview/res-sdl/lltoolfocus.png delete mode 100644 indra/newview/res-sdl/lltoolgrab.BMP create mode 100644 indra/newview/res-sdl/lltoolgrab.png delete mode 100644 indra/newview/res-sdl/lltoolland.BMP create mode 100644 indra/newview/res-sdl/lltoolland.png delete mode 100644 indra/newview/res-sdl/lltoolpan.BMP create mode 100644 indra/newview/res-sdl/lltoolpan.png delete mode 100644 indra/newview/res-sdl/lltoolpathfinding.BMP create mode 100644 indra/newview/res-sdl/lltoolpathfinding.png delete mode 100644 indra/newview/res-sdl/lltoolpathfindingpathend.BMP create mode 100644 indra/newview/res-sdl/lltoolpathfindingpathend.png delete mode 100644 indra/newview/res-sdl/lltoolpathfindingpathendadd.BMP create mode 100644 indra/newview/res-sdl/lltoolpathfindingpathendadd.png delete mode 100644 indra/newview/res-sdl/lltoolpathfindingpathstart.BMP create mode 100644 indra/newview/res-sdl/lltoolpathfindingpathstart.png delete mode 100644 indra/newview/res-sdl/lltoolpathfindingpathstartadd.BMP create mode 100644 indra/newview/res-sdl/lltoolpathfindingpathstartadd.png delete mode 100644 indra/newview/res-sdl/lltoolpipette.BMP create mode 100644 indra/newview/res-sdl/lltoolpipette.png delete mode 100644 indra/newview/res-sdl/lltoolrotate.BMP create mode 100644 indra/newview/res-sdl/lltoolrotate.png delete mode 100644 indra/newview/res-sdl/lltoolscale.BMP create mode 100644 indra/newview/res-sdl/lltoolscale.png delete mode 100644 indra/newview/res-sdl/lltooltranslate.BMP create mode 100644 indra/newview/res-sdl/lltooltranslate.png delete mode 100644 indra/newview/res-sdl/lltoolzoomin.BMP create mode 100644 indra/newview/res-sdl/lltoolzoomin.png delete mode 100644 indra/newview/res-sdl/lltoolzoomout.BMP create mode 100644 indra/newview/res-sdl/lltoolzoomout.png delete mode 100644 indra/newview/res-sdl/toolbuy.BMP create mode 100644 indra/newview/res-sdl/toolbuy.png delete mode 100644 indra/newview/res-sdl/toolmediaopen.BMP create mode 100644 indra/newview/res-sdl/toolmediaopen.png delete mode 100644 indra/newview/res-sdl/toolopen.BMP create mode 100644 indra/newview/res-sdl/toolopen.png delete mode 100644 indra/newview/res-sdl/toolpause.BMP create mode 100644 indra/newview/res-sdl/toolpause.png delete mode 100644 indra/newview/res-sdl/toolpickobject3.BMP create mode 100644 indra/newview/res-sdl/toolpickobject3.png delete mode 100644 indra/newview/res-sdl/toolplay.BMP create mode 100644 indra/newview/res-sdl/toolplay.png delete mode 100644 indra/newview/res-sdl/toolsit.BMP create mode 100644 indra/newview/res-sdl/toolsit.png diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index fe5dc8199e..f88248fe1d 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -196,11 +196,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, } #if LL_LINUX -// The BMP cursor/icon tree (res-sdl/) is only shipped in the Linux bundle. -// macOS loads cursors from cursors_mac/*.tif (makeSDLCursorFromMacTIF) and -// Windows from the exe's embedded .cur resources (makeSDLCursorFromWin32), so -// this helper would be unused on those platforms — and the build is -Werror -// on unused static functions. +// The window icon BMP (res-sdl/) is only shipped in the Linux bundle, so this +// helper would be unused on the other platforms — and the build is -Werror on +// unused static functions. static SDL_Surface *Load_BMP_Resource(const char *basename) { const int PATH_BUFFER_SIZE=1000; @@ -2818,9 +2816,8 @@ SDL_AppResult LLWindowSDL::handleEvents(const SDL_Event& event) #if LL_DARWIN // On macOS the viewer ships TIFF cursor art in /Contents/Resources/cursors_mac/ -// (see viewer_manifest.py). The legacy res-sdl/*.BMP tree is Linux-only, so on the -// SDL build for Mac we load the native TIFFs via SDL3_image. The TIFFs already carry -// proper alpha, so unlike the BMP path we skip the color-key step. +// (see viewer_manifest.py). The res-sdl/ PNG tree is Linux-only, so on the SDL +// build for Mac we load the native TIFFs, which carry their own alpha, via SDL3_image. static SDL_Cursor *makeSDLCursorFromMacTIF(const char *basename, int hotx, int hoty) { std::string fullpath = gDirUtilp->add( @@ -2869,83 +2866,114 @@ static SDL_Cursor *makeSDLCursorFromMacTIF(const char *basename, int hotx, int h #endif // LL_DARWIN #if LL_LINUX -static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty) +// The Linux cursors are 32x32 PNGs in res-sdl/, with their alpha. Under +// Wayland that is the cursor's size in logical pixels, and SDL hands the +// compositor whichever of the surface's alternate images suits the window's +// scale, so each cursor carries nearest-neighbour copies of its art at the +// integer scales up to this one. (SDL 3.4 picks the smallest copy whose area +// is at least the art's times the scale, not times its square, so a 3x output +// gets the 2x copy and the compositor scales it the rest of the way.) +static const int MAX_CURSOR_SCALE = 3; + +// The integer scale the cursors are drawn at under X11. SDL gives Xcursor the +// surface alone, at its own pixel size, and ignores its alternates; the themed +// cursors beside it are drawn at Xcursor's size (XCURSOR_SIZE, the +// Xcursor.size resource, or one from Xft.dpi), which is 24 at a scale of 1, +// where the 32-pixel art belongs. Without XCURSOR_SIZE the display's content +// scale, which SDL reads from Xft.dpi, stands in for the size: the resource +// can't be read without Xlib. +static int x11CursorScale(SDL_Window *window) { - SDL_Surface *bmpsurface = Load_BMP_Resource(filename); - if (!bmpsurface) + F32 scale = 0.f; + if (const char *size = getenv("XCURSOR_SIZE")) { - LL_WARNS() << "Cursor BMP failed to load: " << filename << LL_ENDL; - return nullptr; + scale = (F32)atoi(size) / 24.f; + } + if (scale <= 0.f && window) + { + scale = SDL_GetWindowDisplayScale(window); } + return llclamp(ll_round(scale), 1, MAX_CURSOR_SCALE); +} - LL_DEBUGS() << "Loaded cursor file " << filename << " " - << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL; +// x11_scale is x11CursorScale's under X11, and 0 elsewhere, where the cursor +// takes its scaled copies as alternates instead. +static SDL_Cursor *makeSDLCursorFromPNG(const char *filename, int hotx, int hoty, int x11_scale) +{ + std::string fullpath = gDirUtilp->add( + gDirUtilp->getAppRODataDir(), + "res-sdl", + filename); - // Normalise to RGBA32 (byte order R,G,B,A in memory regardless of - // host endianness) so we have a predictable layout to color-key - // against, and so SDL_CreateColorCursor gets a surface with alpha. - SDL_Surface *rgba = SDL_ConvertSurface(bmpsurface, SDL_PIXELFORMAT_RGBA32); - SDL_DestroySurface(bmpsurface); - if (!rgba) + SDL_Surface *png = SDL_LoadPNG(fullpath.c_str()); + if (!png) { - LL_WARNS() << "Cursor RGBA conversion failed for " << filename + LL_WARNS() << "Cursor PNG failed to load: " << fullpath << ": " << SDL_GetError() << LL_ENDL; return nullptr; } - // Color-key the legacy (200,200,200) "background" pixels to fully - // transparent. The viewer's cursor BMPs were authored against this - // exact gray as the transparency key (same convention the old SDL2 - // path used), so the assets stay drop-in compatible. Unlike the - // legacy path we keep the rest of the pixel data intact — the old - // code quantised everything to 1-bit black/white, which is why - // multi-colour cursors looked degraded vs Win32. - // - // A converted SDL3 RGBA32 surface shouldn't need locking, but the - // pair is cheap and defends against future SDL changes that flag the - // surface as RLE / GPU-backed. - const bool must_lock = SDL_MUSTLOCK(rgba); - if (must_lock && !SDL_LockSurface(rgba)) + LL_DEBUGS() << "Loaded cursor file " << fullpath << " " + << png->w << "x" << png->h << LL_ENDL; + + // ARGB8888 is what SDL makes every cursor from; converting once here + // spares it converting each scaled copy. + SDL_Surface *art = SDL_ConvertSurface(png, SDL_PIXELFORMAT_ARGB8888); + SDL_DestroySurface(png); + if (!art) { - LL_WARNS() << "SDL_LockSurface failed for cursor " << filename + LL_WARNS() << "Cursor ARGB conversion failed for " << fullpath << ": " << SDL_GetError() << LL_ENDL; - SDL_DestroySurface(rgba); return nullptr; } - for (int y = 0; y < rgba->h; ++y) - { - U8 *row = (U8*)rgba->pixels + (size_t)y * rgba->pitch; - for (int x = 0; x < rgba->w; ++x) - { - U8 *px = row + (size_t)x * 4; - if (px[0] == 200 && px[1] == 200 && px[2] == 200) - { - px[3] = 0; - } - } - } - if (must_lock) - { - SDL_UnlockSurface(rgba); - } // Clamp the hot-spot — out-of-range coordinates are undefined behaviour // on most platforms and at minimum produce a cursor that "clicks" // nowhere near the visible tip. - if (hotx < 0 || hotx >= rgba->w || hoty < 0 || hoty >= rgba->h) + if (hotx < 0 || hotx >= art->w || hoty < 0 || hoty >= art->h) { - LL_WARNS() << "Cursor " << filename << " hot-spot (" + LL_WARNS() << "Cursor " << fullpath << " hot-spot (" << hotx << "," << hoty << ") is outside " - << rgba->w << "x" << rgba->h << "; clamping." << LL_ENDL; - hotx = llclamp(hotx, 0, rgba->w - 1); - hoty = llclamp(hoty, 0, rgba->h - 1); + << art->w << "x" << art->h << "; clamping." << LL_ENDL; + hotx = llclamp(hotx, 0, art->w - 1); + hoty = llclamp(hoty, 0, art->h - 1); } - SDL_Cursor *sdlcursor = SDL_CreateColorCursor(rgba, hotx, hoty); - SDL_DestroySurface(rgba); + // Nearest-neighbour, so the art's pixels stay hard-edged. A copy that + // can't be made leaves the cursor at the scales it has. + if (x11_scale > 1) + { + SDL_Surface *scaled = SDL_ScaleSurface(art, art->w * x11_scale, art->h * x11_scale, + SDL_SCALEMODE_NEAREST); + if (scaled) + { + SDL_DestroySurface(art); + art = scaled; + hotx *= x11_scale; + hoty *= x11_scale; + } + } + else if (x11_scale == 0) + { + for (int scale = 2; scale <= MAX_CURSOR_SCALE; ++scale) + { + SDL_Surface *alternate = SDL_ScaleSurface(art, art->w * scale, art->h * scale, + SDL_SCALEMODE_NEAREST); + if (!alternate) + { + break; + } + // The surface takes a reference of its own, released with it. + SDL_AddSurfaceAlternateImage(art, alternate); + SDL_DestroySurface(alternate); + } + } + + SDL_Cursor *sdlcursor = SDL_CreateColorCursor(art, hotx, hoty); + SDL_DestroySurface(art); if (!sdlcursor) { - LL_WARNS() << "SDL_CreateColorCursor failed for " << filename + LL_WARNS() << "SDL_CreateColorCursor failed for " << fullpath << ": " << SDL_GetError() << LL_ENDL; } return sdlcursor; @@ -2956,7 +2984,7 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty // Convert one of the viewer's embedded Win32 cursor resources (the same // branded .cur/.ani assets the native backend loads in // LLWindowWin32::initCursors) into an SDL color cursor. The hot-spot is taken -// from the resource itself via GetIconInfo, so — unlike the BMP path — there +// from the resource itself via GetIconInfo, so — unlike the PNG path — there // is no hand-maintained hot-spot table to keep in sync. Returns nullptr if the // resource is missing or can't be converted, letting initCursors fall back to // the SDL system arrow. @@ -2983,7 +3011,7 @@ static bool win32ReadDIB32(HBITMAP hbm, int width, int rows, std::vector& ou // Convert one of the viewer's embedded Win32 cursor resources (the same // branded .cur/.ani assets the native backend loads in // LLWindowWin32::initCursors) into an SDL color cursor. The hot-spot is taken -// from the resource itself via GetIconInfo, so — unlike the BMP path — there +// from the resource itself via GetIconInfo, so — unlike the PNG path — there // is no hand-maintained hot-spot table to keep in sync. Returns nullptr if the // resource is missing or can't be converted, letting initCursors fall back to // the SDL system arrow. @@ -3171,7 +3199,6 @@ void LLWindowSDL::initCursors() // Pre-make an SDL cursor for each of the known cursor types. // We hardcode the hotspots - to avoid that we'd have to write // a .cur file loader. - // NOTE: SDL doesn't load RLE-compressed BMP files. mSDLCursors[UI_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT); mSDLCursors[UI_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); mSDLCursors[UI_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER); @@ -3185,7 +3212,7 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED); mSDLCursors[UI_CURSOR_WORKING] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_PROGRESS); #if LL_DARWIN - // The macOS bundle ships TIFF cursors under cursors_mac/ (not the res-sdl BMP + // The macOS bundle ships TIFF cursors under cursors_mac/ (not the res-sdl PNG // tree), and uses Mac-specific hot-spots — keep these in sync with // LLWindowMacOSX::initCursors() so the SDL build matches the native client. // ARROWCOPY/ARROWCOPYMULTI/ARROWDRAGMULTI have no TIF counterpart (the native @@ -3257,38 +3284,40 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromWin32("TOOLPATHFINDINGPATHENDADD"); mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromWin32("TOOLNO"); #else - mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13); - mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6); - mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5); - mSDLCursors[UI_CURSOR_TOOLCREATE] = makeSDLCursorFromBMP("lltoolcreate.BMP",7,7); - mSDLCursors[UI_CURSOR_ARROWDRAG] = makeSDLCursorFromBMP("arrowdrag.BMP",0,0); - mSDLCursors[UI_CURSOR_ARROWCOPY] = makeSDLCursorFromBMP("arrowcop.BMP",0,0); - mSDLCursors[UI_CURSOR_ARROWDRAGMULTI] = makeSDLCursorFromBMP("llarrowdragmulti.BMP",0,0); - mSDLCursors[UI_CURSOR_ARROWCOPYMULTI] = makeSDLCursorFromBMP("arrowcopmulti.BMP",0,0); - mSDLCursors[UI_CURSOR_NOLOCKED] = makeSDLCursorFromBMP("llnolocked.BMP",8,8); - mSDLCursors[UI_CURSOR_ARROWLOCKED] = makeSDLCursorFromBMP("llarrowlocked.BMP",0,0); - mSDLCursors[UI_CURSOR_GRABLOCKED] = makeSDLCursorFromBMP("llgrablocked.BMP",2,13); - mSDLCursors[UI_CURSOR_TOOLTRANSLATE] = makeSDLCursorFromBMP("lltooltranslate.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLROTATE] = makeSDLCursorFromBMP("lltoolrotate.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLSCALE] = makeSDLCursorFromBMP("lltoolscale.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromBMP("lltoolcamera.BMP",7,5); - mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5); - mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5); - mSDLCursors[UI_CURSOR_TOOLZOOMOUT] = makeSDLCursorFromBMP("lltoolzoomout.BMP", 7, 5); - mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0); - mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28); - mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",20,15); - mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",20,15); - mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",20,15); - mSDLCursors[UI_CURSOR_TOOLPATHFINDING] = makeSDLCursorFromBMP("lltoolpathfinding.BMP", 16, 16); - mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START] = makeSDLCursorFromBMP("lltoolpathfindingpathstart.BMP", 16, 16); - mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathstartadd.BMP", 16, 16); - mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16); - mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16); - mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8); + // Hot-spots are in the 32x32 art's pixels, and scale with it under X11. + const int x11_scale = mServerProtocol == X11 ? x11CursorScale(mWindow) : 0; + mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromPNG("lltoolgrab.png",2,13,x11_scale); + mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromPNG("lltoolland.png",1,6,x11_scale); + mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromPNG("lltoolfocus.png",8,5,x11_scale); + mSDLCursors[UI_CURSOR_TOOLCREATE] = makeSDLCursorFromPNG("lltoolcreate.png",7,7,x11_scale); + mSDLCursors[UI_CURSOR_ARROWDRAG] = makeSDLCursorFromPNG("arrowdrag.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_ARROWCOPY] = makeSDLCursorFromPNG("arrowcop.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_ARROWDRAGMULTI] = makeSDLCursorFromPNG("llarrowdragmulti.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_ARROWCOPYMULTI] = makeSDLCursorFromPNG("arrowcopmulti.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_NOLOCKED] = makeSDLCursorFromPNG("llnolocked.png",8,8,x11_scale); + mSDLCursors[UI_CURSOR_ARROWLOCKED] = makeSDLCursorFromPNG("llarrowlocked.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_GRABLOCKED] = makeSDLCursorFromPNG("llgrablocked.png",2,13,x11_scale); + mSDLCursors[UI_CURSOR_TOOLTRANSLATE] = makeSDLCursorFromPNG("lltooltranslate.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLROTATE] = makeSDLCursorFromPNG("lltoolrotate.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLSCALE] = makeSDLCursorFromPNG("lltoolscale.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLCAMERA] = makeSDLCursorFromPNG("lltoolcamera.png",7,5,x11_scale); + mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromPNG("lltoolpan.png",7,5,x11_scale); + mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromPNG("lltoolzoomin.png",7,5,x11_scale); + mSDLCursors[UI_CURSOR_TOOLZOOMOUT] = makeSDLCursorFromPNG("lltoolzoomout.png", 7, 5, x11_scale); + mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromPNG("toolpickobject3.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromPNG("toolplay.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromPNG("toolpause.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromPNG("toolmediaopen.png",0,0,x11_scale); + mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromPNG("lltoolpipette.png",2,28,x11_scale); + mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromPNG("toolsit.png",20,15,x11_scale); + mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromPNG("toolbuy.png",20,15,x11_scale); + mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromPNG("toolopen.png",20,15,x11_scale); + mSDLCursors[UI_CURSOR_TOOLPATHFINDING] = makeSDLCursorFromPNG("lltoolpathfinding.png", 16, 16, x11_scale); + mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START] = makeSDLCursorFromPNG("lltoolpathfindingpathstart.png", 16, 16, x11_scale); + mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD] = makeSDLCursorFromPNG("lltoolpathfindingpathstartadd.png", 16, 16, x11_scale); + mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromPNG("lltoolpathfindingpathend.png", 16, 16, x11_scale); + mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromPNG("lltoolpathfindingpathendadd.png", 16, 16, x11_scale); + mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromPNG("llno.png",8,8,x11_scale); #endif // LL_DARWIN } diff --git a/indra/newview/res-sdl/arrowcop.BMP b/indra/newview/res-sdl/arrowcop.BMP deleted file mode 100644 index 1a26a0df34166f5bb159625bd2b424c7e5296a7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmeIuF%H5o36UyHANIqv-#IQ>bu`SWn|@thY=;PuCf diff --git a/indra/newview/res-sdl/arrowcop.png b/indra/newview/res-sdl/arrowcop.png new file mode 100644 index 0000000000000000000000000000000000000000..f9034179773d9aeb8ad7f5640d1d31614ef61e61 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ9iA?ZAr-gYPW9$Htia=vzUI#V zQ}5I~TBaTGoLd-DYR1v?Vg>)A2&)JvXj+P%t;Gy zyfH73G0|Q8UE78eORW{B*(#qj7h{;hXu=oCKjDsxZtkJ0hKgdlId;CaZf80tQo8R} z!XzDuF4OK4?b8irbI03XFJR-F^PGQ?SY`2@bR}WEFOt0m_E%d@-~8q7HHq)SbcNF& olf4SK6s&(;Q1Fs^U2hw%?;IDXxHh_YD$oxMp00i_>zopr0HWMk$N&HU literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/arrowcopmulti.BMP b/indra/newview/res-sdl/arrowcopmulti.BMP deleted file mode 100644 index 48f153cef662b9cfab38df3ab11264837c3fdbc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmeH@F%H5o3`N5X8w(>NC+Gp#xi`0hFMjz-<0P$BM`FNIT-&jqe{+9Kr}VK2{)Tg% z&mmn9!Ek>*^01K7^KYIP_&(dp*MnU2g8N!C^ekpPiRD)-D8fA8xffG~{8nW@AB5br z7e&Ona{UEog(4?URneB;I2V+CRtr`4P@ z^}ujP)HVo`)KL2=Kd;o3#U@j3{v;_bF N002ovPDHLkV1g|BY54#E literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/arrowdrag.BMP b/indra/newview/res-sdl/arrowdrag.BMP deleted file mode 100644 index cd868eec2008229506cca29e6a706325996b5916..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmdUvcUVq+7{@;;NoiQ2L1kr>5m6#qX2_UrKjT+j3T_x|zT*Y*3|=bX>EzxVh4o$ER_j^-*{F9pP)ii$Ud zKUr8pQc$2qjT$H_Dx##MM9rEtQC3!_R;^m7sHjl8c5PHuRZ&w@qfVVVsH>}^p`n4M zrY2fiTGXvumwNT;QNMnD8Z>A?!-fsf*4Cy`qee7t+?Xa!nxLbjgRZVFdU|^3>+93B zX;YdtYleY=0fvT#7#SJSym@n4v}i%gmMv-3suitUx5n7mm^N+N(6((`+O=y(`}XZI zF)_i^)RYb#I?%CWM>=)tMCZ<(F*7rxOP4Nm?b;P{b91_N>qhtP-LbH+z|zu^9zA+s zWo1Rro;~T+s~6VR*7WY(n?8N|U}Iy0t*tF~c6Qj?+vDKiK;OQ7>DR9x{rmT4z<>b^ z95|3cg9hQ~=*Zx~gBdbp2t$Vs#mUKuVZ(+oeE4uij2OYlks}#3Y80bKk7mr6F^nBM zmT}|8;q2^;i;D~6$B)O=)fG24HzrJ&fV;ap6DLk&(xgdDo;(>34-Y&&J@NAL!rR*$ zA0Hp4OqqhOuP=UneoUP@6@Pz!rcIm1^y$-?F=GZZXU-%bAb`NYKxWOFMNm)>vuDp{ z&YU^SojaF#^X4&s{(KfJSir)C3t6;i5sMcuCO9~lB}x-EnCL&<;w{P2_ZBz zlocyhuyW-}!otD`4-Y3IB7(@sNLH;{#p>0oiHeG1&6+i=UAvZb>(;S;{dzWR*uch( z8`-pJ6VcJp#Kgp~dGltrY}vxrty|f)Z5!LSZ)eAj9qin>lU=)Zv3vJ!_Uzfi-o1N? zjg4jBzJ2W9zn=pK4sh_`K@J@{#Noq-IdbF(M~@!m*s)_AKYpAOCr)tkqVJ zr#W-x3}?@tB`z+G`1p9vojXTDLIUT{pXb7b3tYT-kxQ2@aryFP5)%_iN=hO*IhiY0 zu5k70RjysT#`WvhNl8iJ#*G`?ym=FmNW`sMx43=#HmRwpq@|^io}NxdMh2OgnPg>U zap%q*?%uu2y?gh#fB!z&+1WgJ@PLO8AM)tYBXV+b$j!~=@#DuldGds(PoMJa*)yI$ zf6j{+FL?R#C9ht+;`Qs-ym|A6w{PF_?%g}`^76>f&*%O7_k8&9fsY?Q^6AqjK7am9 zK|uk9g@t_i@`a+JB8rQPDJdzTw6v73U%&G0+c(O}%J}~MJLTo&R8&;(I0_(LXq?b(sJF diff --git a/indra/newview/res-sdl/arrowdrag.png b/indra/newview/res-sdl/arrowdrag.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d47b0816e5b5f5f2b7acf1c06d8072c4892776 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJWu7jMAr-gYPW9$HqQK*vyZZb7 zqFtIoe=jVOd{xqD-oc`&ugJo{q2hI0Y9)iC D7dn)m diff --git a/indra/newview/res-sdl/llarrowdragmulti.png b/indra/newview/res-sdl/llarrowdragmulti.png new file mode 100644 index 0000000000000000000000000000000000000000..6bd32fbb0debcda448f33655a2c12ffdd40e6433 GIT binary patch literal 251 zcmVrkxPhONz(`3jj$2aE>$&h{#EGstJ$6g5;1!p`3lk zo)_@c=xkrF)YR0dU%x);>gqIT&;Sh$4H`CVh^D3{jT$wgapT4`Y0?BO zEiIZhZA!Cd&1l}dIW1bWpk>RJv})Cg)~#Ekt*uR)Hf_++(V=bIwzO;4j`r=_qpPb+ zhYlU+*s&v>I(0%%Pmj)>JJY307rJ)sioU)+1_lNg8X96`WQ4J?F(xJ^bnDiQ?%li7 zqel;V_UuWoUcKnuyEmq$rkI(T(Wg%z%+1Z|+qWSLx(bK*f6ZDtQbCgI3q@kVC2Y=SX)~&YSbu3j~>mKF=H4zb}Zw@ zjbr@y@l2R70UH||Y;A3sIB_DACQZW5&W_2GCo^Tr6sAs{%Cu?Im_B_vGiJ%?(TSa zc(7o>0v0Y@$f8Ay@bvU#@#4iSS+azsOP8{2*)o({ek!v;2P z+{mU)o7lX0GohiOY}vAfty{OUZQC}sZ{JQ>SQz2q;q2J4gPl8fvTN5acJJQJo;`cm zyLT`9_U&W;{{0*{aDamc4|3?xAr2ot%#kBUIC}Ib5fKqYMn-b%*fEYDKhB90CpdZX zB&SZD;`Hg$L`6k$=FAzQqoaw5iQ(+ovz$A3j`Qcw6B`@Lg$oymi;Lsp#fx0JbcxHC zFLUL}6|P>rN_>1g*REYdB9V}gkU(N$BG<29=f;g2+`M^{Teog;`}S?_+_}TuyLY*F z?;iK>-{--D2RwZEkVlUm@%Zs$o;-QN)2B~KN=o9{vu8Yi{+t&tUhwkeOOlh5Nl8f| zH8qvAv^3Jw(|Psk6|Y~v=FOWoynXwYjEoF2Gc(D`$|5^Eo1B~+a&vQe_wF6<-@oU> zhYx)G_>oVaKJoeUXTE&-LS9}TU%!6k+qZ9g|Nfo){Co-u3Mecrq^PKf;^Ja{{P;mh zNr_nB|HXuK%S=kbC1rmzO8yHDlFH%>z2+}m+#u9fVftmG`a2gp@O$~C1O7Q_F@xW+ zM95n>;bL5|Yl8oyc|uaZ@E=Tk6r{p8%jFewfl5DTqE_UhRUj{oUB0Cv{EJtpE-S4x nK!xgmxfJzJE)|!>mySz$C0OK@VS!hQ%jPGgHt}`kYKi0@sG()n diff --git a/indra/newview/res-sdl/llarrowlocked.png b/indra/newview/res-sdl/llarrowlocked.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad4250b9da16e8d8f612fb53457ad39a7c9c3ac GIT binary patch literal 243 zcmVptpi~YR=z|)Sbg9P zVXZ??2>aylg0P;`1HwiDS3}sDperF#&q?yY0)TD+8;6?)Nbah36=6(sKfj3Ru@O8m?st{B&E2ldj$t$c tl2l`3Zh8}j{*?YLK>B9?AA9T;_5wroT_uEMW2XQB002ovPDHLkV1m$kX5at- literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/llgrablocked.BMP b/indra/newview/res-sdl/llgrablocked.BMP deleted file mode 100644 index 847439670f94de1aedda70d2cbcd3ad27d31c8dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmd^*7{@<~lBj4SR7g7&qEOP5_TGv_Qc9Bw?L^U(iuRygb#aRYO5Rf$G((qo}Bel9CcNYSf@+&6?Dz zRSRWhWmHsDs9n1@b?VfiZr!@nt5=Wu_3P81K?52#Y>29=Dr#zKsH>~fs8J&{G&IoE z)I>{5i^h!`)1*lgnl^2Uwzf7pIy&g;>e8%PGxYTIXx_XzEn2joWy_YdYSoI?ty|Nk zO&i*_ZA-g$?a>_Ms(`b31eepOiWDZ+_^Jdx^%(R z)D$x_GtAA+>Dsj`-MV$d!oq^?-MeFHX-SVBJ?Po9C%t<0qId7!^y$-wzJ2>*Wo1Rb ze*Lhvwx)mo{tOr}fPn)CGHB2s1`i(0kRd}DI&>(*h7Du*@ZpRYF@ljJM>1;EC`OMS z&6qJ`7&~?>iXX4`G!mL@dm_2(ouCA`knKOsEbLTQ|-aO{d zpU;8?3s|^tA#QGNxVyWvXwf1TFJ8=&B}?$|@W9j46E80>mM&e&vSrIyzI-_=R;*y< z%9X5IwTjiNSF>i#8oa%|S-W;EK0ZG9`uehN-8$BSbt?e@0c_j0jljS_wr}6gjvYJLxpOB$K|uru2eWI}E_UzU&7M7b*t>Tx z`}XZ)|Ni|PIB;>VKFpCLM>u-)C?O#sgocK4?AS4mA3x5C6DK%%@+7BD zo#OQA)0{bThO=kSa_-zY&YwTeg$ozBc<~~aE?wgC<;z^Ta)ql`uM!p(#Zr{GmojZ3(NJt7Kj;N2u38d*`WMl^aw)Bl3y#HYi4O=#M537D z>nR5%OyDKBR4G{%)mMUJB+in}k^`k!{EG=8p33Mh6sX%IvVC|E9* zxmV)M{OoresK2q@*NLQc^T%(13;w8zL<&O`}GQXxz9lO`0^JY15|2$jH#FSu zI(0%(Q4u92B|3NROqVWQP*zr^YuB!H>(-6#-MgcrqJpZbDr#zKsH>}^p`k&K9zD?1 z)TC$6o@i-l(W_T4diU;4pFVx)+qW;;+S>H%*AE>X9dvbd>EFLU0|pF0Pfw450|zo_ z&>#j69?Xy-L(tdPXXwzO7#J8}XlTf=VZ#_cd^jUUj9}!*kr){nF>2H(MvorNm@#88 zHa2GL*s++Hm@sbKIL413kEy9CW@cuXo0~IX!UQZVEU>h+Wa7k$Oqw(aD=RCkt*x=K zv0?J$$=KT3GG)pXrcRy8v}x0rK7BfNc6Q8|F@u>iXEJNnEbQ&=nLT?pbLPy!!NCDX zM@O8ToR~XzF7xKi!`a!H`Sa(qV8H@hTwHKE%^KFOUCX+4>sY^jJsUP`VB^M( zY}&Mm&6_u~Wy=<}ZrzHPmlxjN-fY{pjqTgF*g9e|GNN$*x_y z*u8r<0RaI71_rWc&mQ*f-OIjx``EvKKL-vR;NZc796EG}!-o$O6cj{oa4<)X9O3BE zqlAQn5E>fFv17+Le*8FLVPS-ahjZe@2~M6oNkl{hr%s*X^y$-_Idg`{$Vj51qKJ-; zCMG6^*w|R&;^K&pk0&7^fwO1Nl9-rCQc@D<&Yk1@`SV=3aDj^#FLLS9B`#mS%#|xw zNKQ^BB_)N_)Kt>a(ztr{D(UIzT)TFS>({SyfmDJkLg>({(_^M+yzU-(?)S|Nc#R zc{vpo6~g!ZKmPj_5VW$Q&Q}QgEEsi3L{KOYNNUL;#KQEIIcf+*SQM>YAc$6G72%o= zVlKqueKiwtNQBeHr$2(KNF}b5SK+$27}vr@A#r7@%>K9wcEY>Wo>-%TBL1fWHF#wL cae-@Mu|qYRzxfM);oti!lne9!^P1@V7thjLp8x;= diff --git a/indra/newview/res-sdl/llno.png b/indra/newview/res-sdl/llno.png new file mode 100644 index 0000000000000000000000000000000000000000..a0068fdbbf5f029de0b98be2291d7c267d9465e3 GIT binary patch literal 213 zcmV;`04o29P)8D+>$|iP=$Ka~;q|~4 z6PJ5NcO?^-?^^yobma7&wcLuT-Rf2X&{HF8OVTU=}cYRr4R!V6@R2kN1+RY zloZm^(p0Nf4H+33s#mX$tgI|GYSchZPL7&2Yf`ILE#&3psa?A^b?VeXK|z7Kb?c(2 zs7Sqf^{8LJK1xbTG-%L(h7B8{tgMWRiVCW#sx)fUh{lZ@)1*lgnl^1pvu4duQ&XdP z^X90ltJ9)I3tF~pNvl?^Xx+Ls8X6k3Y14+bZQG)$sY$zb?a(Px^%(7zyL!-L%MeDijk2K-MV$7d-v}2=+OgX zV`F;u?1_nq3B7vtqId7!n3|emW@bj8K7Huhw=ezr^`n3P{tOr}fPn)CVs38Eph1JM zu&}_=(h@5xE3B=p89aC}Lxv2&#>NI)TU&+>9g3Zu9rpJ23>!9#;lqbBV#EkWjvUFT zQKJ|=dNgCkjA889u{bz5;OOYcxN+lfa&p4i*_rX<$1`EV1SU?L$fQY=aB*>A^5n_5 zy1FuD$`qzfoyxRn({OWhWBT;zxVyXK;o-rI88etUb0)K9&0_ZK+02KK0ZG9`uehD$r6?>UCOd$%UHgAIV)DI zz|YT*l`B`WYSk+I{rw3D2w?T<)vQ^whQPo;)~;PkP*4!T!NIIsw~qDe*Rx^620}tY z2n`J-EG&$T8#fXj9!^9=1d)-EL`6jr9UaZ4O`F)fc{4FFF>Kkgg{@n+vTfTowr}6g zjvYJLxpODGcI_fIHkRGHce7{D9^&HS*t>Tx`}XZ4K0cm=gar2Q-_L;q2S`jzC>D!bB42L z&vNeEInJLyPikr^7cN}j;>C-krKNG{(j_imzRZ;?SGaohD%Y-ETNg zo}SLFTerA<`!;v(+~MxsyWG2XkNfxUlaY}@W@aW29z5XT!-qV2^oXpiEFM38%#$Zi zc>44y&z?OaJ3E`4oE&mW0Sq7AX2>>}lo(%mw>2v_zBA_*6;WL|Erg3HAf06XOD)0vv3&aKf6H6le7N$~sA%x^@{^l+d3&&TriPpaW DY!W${ diff --git a/indra/newview/res-sdl/llnolocked.png b/indra/newview/res-sdl/llnolocked.png new file mode 100644 index 0000000000000000000000000000000000000000..6e7bd9633d9312463899d82e5bc0c673ded39969 GIT binary patch literal 247 zcmV|@}XkfY`{vYXGti2Y^LRUw~>f;!L)gr6*a$X6w7O2(-;Ro$z|# z5fROu(Wji4$3!)1^xn zx_0eKw{G2#laoVUULFMn1r!w(>E69NJ$m$@XV0GW>eUM+B_))Vl~GYqK~+_i-o1O% zr%xZ$)YRzPw=e4I>h$Z^kN*ApGhn~~G&D5O)YL>vOABpnZFF>W7&vesy1Kdy8Z?N( zg9oFhr-#12J_ZH`7#bR4WMqV~u`wnlCJY%egrP%+GHlo|h7TW(si`R=MvP$O$dQa1 zHHy)rM`LDY#+Wfh+#LCKwi4!McZEcN>jSZ6~ zO=9xo$=KT3GG)pX?Ck8AI&~`c_V!GhHVp>{2c}P-&Wsr|aCCHJ=FFMQnl+2rvu87B z&K#VaoN#t_#>K@2S65fu+}xNucP{Sk?#!Dv4-XFy=Fgvxr>7@gUS4>6d$VA{0(^XY z@b&d&;lhP1TC@m1KR*^PUW~uLKTDP@As`@trAwC*7#PU1Wy@H;d^tfuK?DZ}6A}`_ ziWMtZxpF0|R;^<7>eZ}Svxc>6*RpQiI@YgW&xQ>f*tl^cp`oFKg@v(c()g0;gPS*Ra_iPDZr{Gm zojZ59d-pE)?%g9hJDZ%G9PZ!0Pi}554<0<=;lqbKdi03Lj~|nlmq&hnK2M%J;px+- zJbU(x=g*(>;>8PIzI@56SFb22DB$($*SvZ2hPQ9uQdn5XyLay>Dk`G5xR{cX65hXm z&xa2m`1tW7rKP2O`t*sivNFoc%c-cS;PdCteEIT)uV26N?b|mhD=Vq0s^a_i?^IV; z^W(>ln)Cf{|E38DU*v`bA-uH)uT6jj4Fujm2LTe0+W6;|+ENSfU w)-?Z3p76ZCLX9|q)l2(D>XLd=n+fM3P*rPxt^BX>-zW6<`3T2ZzvU176Ubak<^TWy diff --git a/indra/newview/res-sdl/lltoolcamera.png b/indra/newview/res-sdl/lltoolcamera.png new file mode 100644 index 0000000000000000000000000000000000000000..13ae7f3c0aaac5d791ad6de9f33af15c52df8e35 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ37#&FAr-gYPP@%@K!L|u_~!rr zMc)*~ zZxWA62|i0q*P5!6cWZ}AI`@Pn-MaJl64$yAbuDj@CCqwNc=LAS6Vy zX3Y>57Dhxwgyzkg)1pNSL`6jr6B9#RT%49ITOuJLL914+Xx+Lsl9G~0Nl76sEsczf z3~k!9K~`24IXOAnwrxwhcI{~2zC9f}bf9C$j&$nOiO!unBQGycmo8mUP*6ZoQ4u92 zCAxO)in6jYDk>_ds;Z)ON+sS2Qy^I5QYvNing{k!-frG`0(NA=;$zF z#0YeCb z>CBihgPAjDGHcc>Y;0_>wYA00&W_o$XESHc9OllQi@m))4h{~?n>Ua7^XIc*!2%X8 zT*#tDi&(sPF-w*#!O_u?rAwFM(;Hq!@~nlPfxtOyjZ_}J>K5l`1ttX>+6f3pCA7I{%qK= zfq;MjHg4R=rcIj&3=AYFD2U+TU^Z{wOh`xwp`oFKg@q9w9!^9=1d)-EY}vAfty{OU zZQC}YqN0e7jwU81hS=Cxwr}4~TwEOS@$u}~v4ez!1QHVyNlHp$=gyt%+O>=1DMn(pinVB3p za)hHtkCK&@MRs;J$BrH2`0?YMIB|lLCr@(f)G1D%KFygkXE=NIEa%Rh({(_^Mn%A<>lpk`0#;` zA3yTx(+yzU-@Q&UqTsPDgM zP1Hr>g*S0B|3h3OcqEO~E#Qsdyn20u*CJrQy+K?DYk6G?!8ZQ3KNw8Tq8ko?;`t|u65Y`R-Q48WfSz}C~`Pcjx&<2?E diff --git a/indra/newview/res-sdl/lltoolcreate.png b/indra/newview/res-sdl/lltoolcreate.png new file mode 100644 index 0000000000000000000000000000000000000000..d90a41391305f390837d2522d45f1440a98b0b18 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJnVv3=Ar-gYPV?qFpupjB@b~@7 zT^l*owk|Vrx@{qCpLxi6OV5d31_!a#9-Hp58d!bmm}KHu^*Ny9!-I>LR=)`eJ%8ry zp6_@6PpM)Lia)4PyxGl5^Nd-9K?jQlUu8YN&)%l4wh1v_sKEX`z&gO2cf@)L zp+g5ccI=3#s3>A$Vsz@%32||8BqSt|l$4}%=gvq;Ng*vQjf{*8UAlBZR#uj-UArPD zCx^VeJl(o=qkH%6^ytxpo;`cgt5+`+6cp&)yElr8iuCEz2PGvX`u6QhzkdDb-@iY~ z%F3vysGzE<%76g_7&vesYHDhztE)3;&>%E4G|<%4L`zGH!Gi}gWXKS-wYAaF(Lq;N zm!U(4GHlo|h7TW(o}M21`uZ3c7%*bQ2n-DkF)}h@FJ4=mlrEmtYGEJm8@E|iq)%Evu4d2)~;R4x^?UD_V#A|`t|tu_^@Ha z1~zWo$fix3@b&e@&(9Bke}4i30@%EHGh4Q7Ve8hdY}>Yt?c2ArW5*75?%c_)UAqVj z3?wKhh~VI0cJJQJo;`aA2?-%IG?cx2_p)!_KKAe5&w&F6IC$_NhYlSgEG&%h@Ngm` zA~<~bFh`CYAu=+OqeqW&?AS4mA3x5C6DK%%@+47FQA9^a6B84|sZ*yoefl)9v9X*v zbB42L&k`3G$GLOoIDh^;7cN{NK0cm=gaj^LyvU_Xm$-cSGKqgb?bFM0Kaf6#TZ*uF_EpFew&7C`UxO?|585tR5W@d8l z-aYQ$zt4jQ4|w?SA&(wC;_>6hJbChjtgI}aK7GowXU};4{5daPyx`@_m%MuQitOxc za&mIW&CTWY>(}Jv<&mGCPeDNeZ{ED2u&|J#q9Tfmizz87;qBYEl$MtA?%g}yzkg3z zSsCT!kX=*Z2$m1C-@WnE(I) diff --git a/indra/newview/res-sdl/lltoolfocus.png b/indra/newview/res-sdl/lltoolfocus.png new file mode 100644 index 0000000000000000000000000000000000000000..84923a2e218f7dfdcec66d13354956e17f28cdcd GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ3{MxwkcwMxr#W&RP!M1ie))g@ z966TE>MZHIPA6k*X3B~-xwu!bCtm7#Xz-nhVcWzd>5)rne-tv$7i#4A<8V>{ z<)X8rm$x$oKfS#2{I$$p7Zs(#sXL74bgP6tyIynEi9>P9M&?AhX7>CaWQYb6gm6a_GyCo4qG7~~p!)PEQ+5=e?4O?Vu2-#UFWn^T8LX>RT z-W2_=Xj3C#6n+zlF*k2Em5T|UNVS52^BwNL|Iru zl954HRu(xqIppQ#sZym1RjXE|TD58@C@4_9dUX^P6;V=BqDGAx)T~*PTD5AStgMWR ziVC%B*QQRLI@GOOmwNT;QNMnDR8>`J(4YZoYHBoW*pNnz8qv6MW12K+Ler*AY1XV6 z&6_tzU0odw4GlCkHEGeJ1ua{)q*bd{v~Jy+Hf`FVrKLsNwry$Gt{v^$x2Hpg4s`6; zkxrdD(YbSHx^(G+wzf81yLLrKM+aS9UG((y(AU?eTeog>@7|prJ$lfyXHRP7F~ zz3J1Z4+aJX7#bR4WMqV~u`wnlCiLyw7gJMH`t|FFnVA{=`}b$SfB~4Bn=^3WKn4vO z#Nfe$v9PdU$dDln9Xga@!-ipLY02>6!?CimV#J6Mj2t4}$@7vA39`1ttX>+6f3pCA7I z{saUB5EvLpP*4!dmoI00oS+iyhYuB!2-MV#zgoF?p8cJAL z80*)sXTydKgolR{5fMRTWF%2hQEc3}kxiR6v3c`mwrttL)~#FFwrv~Rw{K_1jvYit zN3(P1PIm3uMNCW#yLazq&z?Q(-Mg24`}VPa|9%b}IKaV!2RU@;5V5hb#KpxCA0JOb zLIQ^mA0{y|kt0WraP;U=jvYHjQc@Dfk00m6i4&YWd6HA7PI3D5Y0jKE!`ZWENls4Y z+_`g{KYyMJ7cOw|;zcf9xJt5>{!{hBv# z-thMATi(5U$NTs1`S9TbA3uJisHlifpFZ*V^Jl(%`NG$)U-|a!8{fZw=f{s9{QUWo zU%!4)TwE;7_uq%`)2Yl=V4{l^|DB6rWd}-I1uBYvC`i#i4wTuJbe26*%5EuPTgHT3 zjwLrM>N1>CGElK#QCgKADaWEuObAh`=oM8GTs(>t{}W4#OLq(MQrZ&ge_@j5QhgOF z0{p BhjRb` diff --git a/indra/newview/res-sdl/lltoolgrab.png b/indra/newview/res-sdl/lltoolgrab.png new file mode 100644 index 0000000000000000000000000000000000000000..2f429bc2a97d7021d50e61bc8316f0e2e6ff4a88 GIT binary patch literal 244 zcmV-p3nT&@%FJTl2vL%m7AFLzYf-F!6KzIu(KoJDW0213p+w>}U z<|p3kBIEg!^#%6QAR4cs(vDRX=qj-a!5yZ{K#=|YcEIoaI9Pb-e+Hyk-u2E+mWq0000;_xri`bDwk1`RJQyh*M=6qM#y(6l#_THAEF#<3t2| z<*M97L}<{U0Sy~AL{wCiMvWTLxN&2|#KaI67pF;+CP+v~(6nh&nl)>Nq@*Oxn>VLL zix#wO*%B!!DO$B^g|xIZty{OIO`A5z$jBfoD@)t9ZE4r89qrqCvMHJ$v?~SFc|5 z?%f+zRaN@*>4Tb@8h!irMO|H;e*OBbihh6b9NnhYE`kU@h6p{1pTwzf8d z2Ms0|SN)8-}5wAx1_<3?Dw65hF%0a^y%xjT(iq zu`#1ZkH*Br1XEK}#*7)m*s)_7H*Or`$B$>igb7TXIFU({CShh~#^lM9nKESxQ>RX4 z+O%nyo0~Iz`gCT@n1O|b1v6*PWY(-%%$_|POG`_vtgNuMwr0+pIoR0PU~6m3+_`g^ zH*X&E=g()sf(0yGxR6DQ7O{BoVwNmff}Ncm_V)HHUAmNI%a-Bb;K1_b%W-sc#L3AC zXJ=eZ`Rvt|wM?(TSac;M;jiI)Ehj1HQh#`1$$a@9$4QKmZ#zZe-J@O>Ex0nJrtk5EvLpP*4zCw{B(I zwrvCl2NMz!LTG3x+qZ8gEGJ9e;h=T5@I!`ZcK7rS@wX3w5I?A^PUef##YfB$|C z95}$ig9nL-h~UtnLmWPQm?KAy5E&UsR8$m4j~*pDI+|n0j&c0>abjX(h>eXUE-sGv z_;^m7IKj!2CrL<1ATcqKq@*NHojS$o)2BIe<_u@gp5@%Rb0jAxlai9c`Sa(waNzg(u8^9VN?KYP>FMcYWMpvl>Q$~?yT-{--D2RwZEkVlUm@%Zs$o;-QN)2B~)_UswYpFiitix<3n z`I4-xEV8q+dG+cQuV23=CntwDZ{Cobn@e6^9&g{iB|kr(ckkZu{{4GCeE7h}j~^*0 zD4?*gkfNd@ii?XWDJkL8r%!zT{FyIbzVP+ySH6AwMrmm&Wo2c2|NfmHKYsA@=TFMZ z%c-cSsO;~r{e6KyzCiUKqQ?JDRbNnhs+CeXX4O_n)`q_qR8%PhPB@sgcLdWaz^kVA zkNofQ|5ILYS7>$03qfI2OQ#7jK_pBi6jVjk%>U+v-PPpzSC#+pb&J$(zTRgDlhlLj J9V#_-fnOJ?KV|>` diff --git a/indra/newview/res-sdl/lltoolland.png b/indra/newview/res-sdl/lltoolland.png new file mode 100644 index 0000000000000000000000000000000000000000..9ffa2fa3b278b4693f9c1199247629ed7c35eaa3 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJUQZXtkcwMxrydk)P~dQhUH<=n z>aL97X>AR`?X~KrTT&+qp6oX%K9l2ifIl`pf7z6$>lhDwT-&D{(iIvb$he((Z_fN{ zx=*%rClq-2alNhz8%QJEr@A(f&?r2&x!&9g)knlm(#1~jQO z8PZ7eKvC}ZeYe(P-O4}rpS#xGYwdUMb)K`&e)jXe@3FAemqujz;-D$WRDZY_KL8Q> z;~^%9LKg-xF&Z>zK*NR&5f>LnLP7#bNlB!nq>z@Drct9t$jHbbD=UkfoE(iCH%4Aw zo+eG2(6nh&6ciL_)~p$dii$LE-kcUKTA-w)M9Y>fY1OI~ty{OIO`A5fZQB-QWo1-U zRA|?(9qrqCvMHIyyS&>gv+7XHWF>^yt;A7rlG;Mqgi_K7IONU|@iup&>>_Mi?6# zV`5^0si`S_`}W1m%nWmLbNcn`hlPa&{rmUF($W$uD=P*J7{I`R1F^QYX3(HP*x1-G zc<^9`3>kv0tt~@`4rSP|Vc6N(VQ+8G@ZrN5F=7NGM~-CFs8Ng_JsJlG2gZyU!`QK7 z88>bm?U0rc=bHm-;ohehM;Njtc zr>7@Vr%uJo%Zq8#rZIi`bY{$$fw#9eK0ZG9`ugJM=f}*MGx7KLXV$D)%$_})IdkR^ z5D>uJxpSE}ZytexfdmBwF@OGi7A#mmaBwgoAt5YWxRB7$P!=s(#Nx$^S+ZmaVPRn` zUAmNI%a*Zx`EpjQSV4GrI1v#ML`Fuka^*^*qN0e7j%L-WRm8-^uzK}s)~s2>+O=z0 zw{9J=v9YXQzn%>nHn4HyMmBBQ#OBSL*|KE|Teogy+qP|N-@ct4J9e;h=T3I*+QshO zyNQd7W6z#F#K*_8ckf;j5)w#EOl04_eeB=Ap92RDaPZ(k4jno~Qc@Dh$;qUoq;UA~ zVU8R*!qKBgId<$A$B!T9#EBD}Jb98+r%sWYno3$)8tLijWMpJ;`t)heoH@hUvu8PX z?i}aOpXb7b3uIg(u5k70RdRB2$j!|qFE5X4*RFB> z`gLyHxWUbvH@S7|7Ww)4+`fIAJ9qAI_wHQ^3JSP)?;iK>-{--D2RwZEkVlUmQCL_= zQBe`a#l@7Al<@fRV@gX)dGh25PoF;J*|TRnfBu{oFJAESeD;h-!uPzvdw9{nLKgqMmxe zukz>q!VRJ`YVjAW)G`76x*ugNOq7b|t5g1yu`mh;ughG}ua^B&nEyUrSD{+c{GHYV F{{?v~N|FEo diff --git a/indra/newview/res-sdl/lltoolpan.png b/indra/newview/res-sdl/lltoolpan.png new file mode 100644 index 0000000000000000000000000000000000000000..01d3c0872ced8daf56cf15bc2ca90386d04eee2b GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJS)MMAAr-gYPW9$%P!MpAe*AZR zjJSrP3$H=VqM6e-Bq**8;1U$LrO=bZRw%KbmEldH>eaQbv+C{M9SFM9ApK)1<5sho zTYV(5T*A#al(FA%w$U^``=)5A@2suL?&%KvPHRrOtY%crZ-3V_RgS&)(b9gg>iGD% zdXFk*@+*s;U^TU3&QH9&CR)IClbl4+Gt-$7$ASuv7tVQK#PE4R$a4<=rWrt2GI+ZB KxvXC&4K@Y&rtr@r#yw=oMvB{5gzpvO z@)?J4#*FN73Sl0rJ^!|01zrW_ZXfLR6{P+M^OY#%qqeU^IlrX@sw7MbhcKT|i7YU= zM0dV~yCpK42RVXwnX%9?EF0CN|jC!gjpAwhv?+KR@VrKV$ z73Hcnr2|jV86dI}Rsl)R#_D5)%+u>&0}c<68B(~~vdRYBj!0!AjAjJ4TJCd1on%j+ zzbZ`UO*gkXqSK53+)H1VOqsJeo8FVV`!b)2_|^-trXv*pgiLyDE^3Y?OY_xLzSd_~A{$M>^X Wg7^x~w?N!XEn=l$JweiT?tcKn=N23Q diff --git a/indra/newview/res-sdl/lltoolpathfindingpathend.png b/indra/newview/res-sdl/lltoolpathfindingpathend.png new file mode 100644 index 0000000000000000000000000000000000000000..69dce589cfcbdae60a376f1fc15e5c069735866e GIT binary patch literal 295 zcmV+?0oeYDP)We%)#1KJ)yo20Nf7L6OQ?1-MY;f5O)Bc_ozg t1*0VN3yYTMD*89Y&AQ@79_-j5iVxpq<5J1^#eM()002ovPDHLkV1kZVdV~M~ literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/lltoolpathfindingpathendadd.BMP b/indra/newview/res-sdl/lltoolpathfindingpathendadd.BMP deleted file mode 100644 index fa19f3f1058dbe586920d7c42c9c1891b8d2ed46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmeH_F%rTs3D>z4qxRHfpJI+iBG$fp5c~4PtyAQ`O#(?`3 z*JZj6;S445JcSUiIbQ$R>jd5f(cC-O^Cyt|M_HRiAs^mt7Uldk7I4V~4-RE*gUXx& zQ!Tpl8Qwf1w|S5ayd&QwBk6Whm5fc(z-98tR6*S05&V6XO6~<0Am4kD!C@@4Jd697 zRmn}sF1)I}U&SsNNv=0b-dfa#pQ5B7&4Y}jM8*XL`a+@8N-Z$EG5?r;W{V+uTwJhB zBW(aR0%yTk*0H8I#GN~5%~;m87GRo?3^R=`v=A)!%-S%`(zK*Y9Ud}r1VXSZ46Se( e31cYSSS(H^ZzOyJR}19btvu80t|u7ao|hj4<|PdP diff --git a/indra/newview/res-sdl/lltoolpathfindingpathendadd.png b/indra/newview/res-sdl/lltoolpathfindingpathendadd.png new file mode 100644 index 0000000000000000000000000000000000000000..a96b693f7fbf4325c780d43f7a4c8652a5e1ccaf GIT binary patch literal 312 zcmV-80muG{P)_rr?K#?+gu`?dfV$(E~I`^4@k>tOFvju{QmEVFD5CD!O0pI~} zN48FVyf(|4Ng%}F$N75CeS#)SPMpSFA@zXymT_X$d2p(mOe$hbFMtDB1`ETI%Loe;hD zDgkbl#0)_1G{mH5fnemaSqWt5;;HFl83QZX!0Ze#D^ggLWrht{PDF3m@J7Q3&W<;{ z*IS;FHz0!b(0S6$<(*JF7xYBv7d9=`QS|=|K71Dp>fp1_RQ3a;VK@(}K*-4e0000< KMNUMnLSTY{WQ2|Y literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/lltoolpathfindingpathstart.BMP b/indra/newview/res-sdl/lltoolpathfindingpathstart.BMP deleted file mode 100644 index 912b7f931a744d3cf4e775aba5198ba0518e42a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmds#K@I{T3`KEoT)TAX3FZLqU3y~|-bz2yp=l`4Is+zSBf>!Y{-@z~pN?UU3IA7& z%Q6n(j1|T66ha&+UVjwt6eI2gc6cm5touqxIH{zo7_-NQhO?SxK|nb>j0r>Dx3Lmni&BR{iE&+G*3PNfZdW-^0nfUvZDYqt(`gxBqbNb|YgBPZ@{15oD4rIXa+Axc zOZe2m4aAYGb*@px1aq->iFN*|lc+5QHw~xGp8M0lB>o6EY!H7Cocrd#@7^;%=Xo32 diff --git a/indra/newview/res-sdl/lltoolpathfindingpathstart.png b/indra/newview/res-sdl/lltoolpathfindingpathstart.png new file mode 100644 index 0000000000000000000000000000000000000000..37f24f1c4080ad28d4da0207be45b62d602d472d GIT binary patch literal 286 zcmV+(0pb3MP)XMw`TwrSbVAH# z|0$`=Y~4O^B^@PVa>A8FLcI}LM)0oQEHw~)14Nq?8D)v6fy@_?M~yl%6}61#InM&C zH}DOr9Wb(N3yInT7ZH)o{>(ZF(=-K-;BD*_kI!hPp)52lRS%Un!GFfETZWyUH=)l7 kZzOguUoyz>fiEI)0HWF3`p6!HoB#j-07*qoM6N<$f=#S@82|tP literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/lltoolpathfindingpathstartadd.BMP b/indra/newview/res-sdl/lltoolpathfindingpathstartadd.BMP deleted file mode 100644 index 4e8999ae0bff6c34b7b442bcc457d4803f7fb64f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmds$F%H5o3`N6^m>C&4K@Y&r$c-7e75w7%D~*%bsZyk35ipMZ{B7v%J{-f>2E1Q! zF4H-LGd!{9DTMLN_WC1x&$h)(V28)_g5S3V;jshXG>;5GV&w~e{u`7&QERpkej*iJ z#<;_fR&OzKqRlUS2OlZ^7VHJbw75Bvo2IBI%Pp8}Ve(Nz!L4x5iabopj+M&@9{rvc zS#lRRATTbxqwEqHanH#09Id(6ulZxy(yl(N=e8ui;oR1G8iSZFbTocR)sz@-My|-AWUv`MvtZ`|$HMiZG0H*M_fJ2P% NH-d9-tyAwe{{y$5D$4)> diff --git a/indra/newview/res-sdl/lltoolpathfindingpathstartadd.png b/indra/newview/res-sdl/lltoolpathfindingpathstartadd.png new file mode 100644 index 0000000000000000000000000000000000000000..ca8eceec1d9cb4dc0de92f9a694f26530616eba9 GIT binary patch literal 303 zcmV+~0nq-5P)owvXhKo(r9!EwtIHxik_Ngs|fThm_t32$K9aIISdd6cGR>B@iJofc|Vk zzu_f7l8XD(Byu#kwj4PcT&neZh;%~S zz5P*Ak=dGkU`yIdMCF7}5^?p0XBfdcdZW~U_YdH0Qbd%+qXr^>L>4v5m8pnjZ09Tk zten7Ch-Sc*Wot;}A$V;ftoZq_FigYfnE5W+J^;~bzMy*zB*|rx?D91k)sh-h8D*O) z(^Qe*A5q!O`w?jC2aVI3o$y4W^6?>q2p@RE6Cbu&J0e9P;^zPW002ovPDHLkV1m_0 BghT)U literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/lltoolpipette.BMP b/indra/newview/res-sdl/lltoolpipette.BMP deleted file mode 100644 index 2d27118289e22acaf863e508f18aa66d40f210c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmeH^F%H5o3`N5X8w(>NC+Gp#xi_~8E{4cT9P4F>1X3cUa)17RZk_vMJEiy9@!NF__o&qv)Vr1V@1OyE1MiQ|$MIcIGIzG&E@WND#YhVvjWyM^-QIqxr43vkc7 zWew^t2Bp^oKQ*w~>n_Y9N)cq?k)^pcSpImKWMH9^Q})swiYw*PAuA#dBt#-($qi`+8Is6650#>5AX8*$KvaZerZPv7 zp-@VtiSOKdYkhyzz3cn)J8SK|&pOY3fA8;o_c_PZTvrM4rK(S|}(eP`h?*6crVzQ>P9}N=nqNTNh^8 zY}k-SjT)hRYo=;+Y7b7#7A=|b18UFp`X z8{NBir$>(-^z7M_UcGwJyLWH;^yx$2zJ2M}uOI#U_eWP(7d<^a1`HU0zP>&N1_l@! z8e(K*#K3_A88m1R#>U1B9y}Nm6BA5LO&Ky|2t$VsW!SJ`3?Dw65hF%0a^y%xjT*)1 z(W4nNW(;O#W|*6sGj{A)#*G`t`0?YJFku1{Cr)J2q)AMkJQ)iM3#Lq&f~BP;Q>RYF z%E}6BYip)Wo5u9%)3LF!VaALZ*xK4MbLLF!?Ch8|YZkL-&&J-~o;h>oFn8`;=FOYO z{Q2{7aByJ3f(0yGxR6DQ7O{BoVjLYES+ZmaPEJlZJ3F&<=~9+0TZW5^3(J=;$JN!9 z6)RTY=H|xAl`C1bY89(juV&4fHMqOGvv%!TJUl#Dw{9Jto}R2nHsIyu#m0>r z*|cdBn>TM}%a$!{-MW=++qSWN`*wEh*ul=7JK42s7rS@wX3w5I?A^PUef##YfB$|C z95{ftw>LgMKKT0ja`50m{QUgz_xI<}p+g)#e3*cM00IL8IdbF(M~@yQC@6^F;9x>R zLI@2F<=C-f96x@Xu&^*roH)VBlP5WK>J+C>pXSV&GlYkSbN1|6&Ye3)L_`GV&!6YQ zg$rD~c#%t&E)f|SNmNu6(b3Vw#Kds<@@1}Exx&?}SBZ^{<=VAtT)%#uxVSjtJ_hFzvj)GH@toOmh|*= z-o1Or`}gn3$jBfwGm{S=KJfA5N3ycA`1I)$pFe-*%a<>F{rZ*c>}+y!a`^V`8{fZw z=f{s9 ziVFVx`NQA8e?|5Ek1p}=NV*@ymZf?Yupl4|DGCA-h-9w5MG}fsE&y@AYK|8r6{VJv zUx*cUh{S8QSE-#O5~yyiDs>G+@~A4j`UbI@bSxwkVq|flXELy)AQ>-`C{_j*Ym2y) z!mGGciAsI($yBdiQkpCS|IJ@bXYz07Wqn1mdM8p4xO8zbmx(3kC$UoFEIT?W=^ti4 BW&;2K diff --git a/indra/newview/res-sdl/lltoolrotate.png b/indra/newview/res-sdl/lltoolrotate.png new file mode 100644 index 0000000000000000000000000000000000000000..db2a9e7046235015b3fa7e5d69597405f43d17a3 GIT binary patch literal 254 zcmV;#0r{5u>03BCZashKQL%Dv{fq?{odeIiGWn@BKU1F|#(1M`Q+apd;96R1X=dfrwU5GJ;h&go}&} zb?VeXR#p}{IXUXqtxLUn^{8LJKJxPNC@3hPsHljNk`fIXG@xO_hA1m5)2LA+8aHlC zlO|1Q+O#Rnnl(d3MTO?go71923tF~pNvl?^P*qi>b?er&Y14+bZQG)zrbfGV?NC=& zM?*scO-)U-w6tj7zC9f}bU<5Mn~ohj(y3D?baZs++_^Jdx^zKTSC_6`yV9*&H@bK4 zPLCcv=-IO;y?XVcckkZl>FJ@buTP&oeK0UEpl{#4^y}A;{{8ziV88$d4jhP~p&>>_ zMhqG>2xDVoOiWBLH8sV|%#6W<2V-t-&X6HPu&}Ve($bQlLx(bK*f6ZDtQbCgI3q@k zz}niHkt0VkYSbu3j~>mKF=H4zb}Zw@jbr@y@z~hdFk!+3CQh8lq)C&QJb5xxrcA-s z)|RPLr($Pk$FynFu(!8o`t<3{m@xwf2L~J-9ho_ECbMSE!pX@AXJ=lWuY}l}YjT<+zY11Y)Z{Ez7EnA3)h#)dD zlBlRCwr<_Zwr$&pj*ccKCWhG9ShjE9PF!3Z@$vEO*s+71J9n~c*DiMN-p!spd)T{o zFZ=fGWB>mB95`@*g9i_C=+Ge&5)wFk_%KI~9O3BEqZ~VSjN`|TbK=Aa5)%_SdGaKu zPMzZP>C>D!bB3g(B+i~a%eiysIDh^;7cN{NIXRh&7cY{Ml0s@~Dwi%@;_~IoT)A?E zt5>gb?bir|pHD$S0fmKy+_`gyyLaz$@7_J`-@ng;2M>7o@F7J-MHCko^XSnd9zTA}lP6Dj z`t&K!o;~CF^XHV5lu%k)%8M5-c=_@ruU@_4_3PKXdGm(1Z{Jc@R>r$`?|A?IJ>})) zeE9Hzj~_qs>C-1ZfBwvuFJJij^(z$>6;xJM^6lFj3KNR0_Ot>n4k4i|ssxwNBy;gAQn)CG6fUSwYJ5rg5lE`8t~P(M zv>N&U%`a??D0KDoSN}x#uV;VWO6H1$X5#fmkV|O zsiUma`X*0!ksd!BGb`3VwKg!1-(Ydg+RIA~wNyl5(OA1^5pJ=#HsVwDm-%MHYi?$%^ z!XP6ir>)GJ6-%C9@ab4OMWr&4@qj@?ud)xb3V&>SSAnh%3wycjrxn)9On!p@cZMb? zu2)cDe{FnX>COwe51)SX4X=LmP#~L0;pArT80`Y~52lj~UhZ8Gto&CmL(@v+K$&=p un`nM(K-hCq(r5R78P1D zQ%1x4oCjU+)$4is=e@7%cYf!b&-s4uan5xNjkV+vhn6g;iO!TOmkgCaOe+sEqFq?R zCL=?Q8a1d{vnH~#vdGEFQL9!hYS*rfyu3Vh>eQib-MZAPSC9Jj>(ih?0~$7LNTWuL zXxz9l3JMA|Y0`wIO`FoJSu>h9Z%&IAEoj-YC9PVuLQzqX)~#F9rcE2#wrxwhcI{A7 zQlfqP_9!bWqoSfhhYlT3RaK>9$BuOB)QQfWJJY307u3|$=-Ra_-MV$7d-v}2=+T3o zJ$s_Au1>FBz3AP$HyRom^y$-wzJ2?msi{f7e*MtW(n4EXoBsX#qobpPuC6Wv1`J@} zz=7!L>7lQ$kAZ;!g9Z&^@ZiB18X7WW$Pk7O9m=p_!x%n%I7UWBj2JP3kt0VkYSbu3 zj~>mKF=H?`HfHSDv5Xrxj`8EiV`5^$gb5RvIB_DACQV}UIRx%Cu?I zFf%j5+}xb$)2B0I#tbYhESNcSCYF|#SXo&yYt}4g&z{YkIdhmhcP{hh&13%j`B+<9 zvtYpjY;0_>wY6p8!i6kav@*4h{}1S+azsOP8{2*)o1`vTD^TR)~#dx`t@wsuz`&mH?nEd zCN^*0jJvx#TefUr>(;Go+qRAE+qbi0#}0Px+=+*W2cDjuczJoTYu7Hky}jAJdpABl zKKT0j;^*hbo;`cmyLT`9_U&W;{{0*{aDamc4|3?xAr2ot%#kBUIC}Ib$BrH2`0?YM zIB^1he}7J%Jjtn3r#OB3G-uA7;q2M7oI7`p^XJcV;lc$jUcAVqOP2@;2;lPN%Uro~ zg}}f-f`Wp$di5&7!NG)tgb*4UN?2GJ*REaT`t|GFxN(E<@Ngm`BDi_;Cbw?g;`Z&^ zL`Ft(=gu9XqN0e7jwU81hP!v~5*r)Ky?gh#fB!yladA9&@PPREcoGs4c=+%kj~+eZ z@#DuNCMNRa$rGMFeM(YN63NNQq@<*fnwrY9XU};4{5daPyx`@_m%MuQinO#e($mv< z{rWX;-n`-M+qYz7WRRJeNmf=C@7}%R{rmTP`0#;`A3yTx(W{zI~&(xR{cX5=u);DJv`E`}gns`0<0EKY#M; z*DuP;%Z2{_*Z7Me(lh?0B+3mr{F0&3{%dzWy!$@8rb8lE#IBipKJ%ZM}$i5aT&)vHDCOq#iYv0O46= AuK)l5 diff --git a/indra/newview/res-sdl/lltooltranslate.png b/indra/newview/res-sdl/lltooltranslate.png new file mode 100644 index 0000000000000000000000000000000000000000..bb9f17285c82dc58948706fbbc27c6a2584cffe6 GIT binary patch literal 268 zcmV+n0rUQeP)gpWL$39+@30RC9a3^IV7L#6=$r>dnQOh1N+1EE5kbw^Xc zxnj;e0F)PCSPPu)18s|VCRA_RK(h;nPM$yvcOWw*#=DT4va-x84`-$}u=4hm4j>3M zt|v=kygClt5ZslKy}sVD`;Fmo+#C#Ck$#;o??v(Q3I-J%_3A~ z1u8H?Le#5QkNWlNBP=Y8h=>Rc8Z@9`!-j~8iqfc2BgDkSXxz9lO`0@8TwI){O`FoJ zSu-RgB#@MpqB~9Z*qGK~+^1H8nNV)z#6^&_GjD6D=(*w6(R- z(b1t}$ByXg>e8uGCpvfTOqVWQ=-Ra_-MV!{Pfw5T-MiDHM-TM%^)WCopl8pX^y<}% z-o1O%r%xXY4Grnrw=ezr^~1=>i2nWiGhn~~jE#*kF)?A_z=4>Wnqp>V#-Kri7(93| zLxv2&+}s=s3k!x09g3x;C015e3>!8KYinz4Y;3T#wZ+cPj^V?HV{dPdgM$MjMvP$O z$dQa1H3~;ZN1U9T7(IG4&d$z^88ZeK7Z=8k9gC~0D{gLXj2kx&cXxNjj~~y32@{w& zaUzo@O=9xo$xN9tg{f1gGHu#4rca;Fj2ScV@bJLX(-SW*FJ{i1iMO{mK0ZFonl+2r zvu87B&K%~>oy)v=^YHccW&Zs6ELgCBg$ozr=jVsNzdwr>En@NF#RLQduw=;+mM&e& zvSrIyzI-`>fq?`C1rZz^%!(B&Sh;c~t5&UI_3G8ES+juxt!&%2jqTgFvt!2&cJAECu3ftb4-Y3IB7(@s zNOteuO;l7A(b3WD*|Ueed-oC(6GLolEOBvh#K*_8Z{I%l@88dX0|z*G@E{2Z2_z;a zl9ZIhp+ko_eE2X&jvV3W(W4wYc8uiYWKvR6IDY&%Cr+FoH8qvAv@}khJV|Zf-7ld3ogL=X37dInJLyPeDNe7cN}j z;>C+xx^#)lmoIbW$`uL=3%PprD%Y-ETNA>((u9-@Z*zQ4x3U+~Mxs zyWG2XkNfxU^Web)9zJ|Xad9z^9zEjmC>k?d-jay&!6++ z#S6;I%X#_oC9ht+;`Qs-ym|A6w{PF_?%g}yzkkn%4u%_e=PYX=OYi=cqyAvZSQrFLhP>_gLxQ`WKPvq?Yn1cai%Yvza#{ h?VqhyYY|ZD;qGb6Kdzs;^(D|H44$rjF6*2UngDOqOGW?y literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/lltoolzoomout.BMP b/indra/newview/res-sdl/lltoolzoomout.BMP deleted file mode 100644 index 5bdf96f80d16aa3f742d3fbdd6ef44eff54e10fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmdT>Ne+M@3>+HIrv89%@*Up&4lne;udro{U_9u}NrrSN3=_KTo{->WU4^#LV3I21 zm;oh=R0?7UAu6 diff --git a/indra/newview/res-sdl/lltoolzoomout.png b/indra/newview/res-sdl/lltoolzoomout.png new file mode 100644 index 0000000000000000000000000000000000000000..2c5afc954f345d348a06ee3c8ef9cf52c7b4a541 GIT binary patch literal 172 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 TzyKfo00000NkvXXu0mjf#&}nQ literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/toolmediaopen.BMP b/indra/newview/res-sdl/toolmediaopen.BMP deleted file mode 100644 index ac4b231994c1f3ccd69b04c35759fac271b1dbc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3128 zcmeH{y$-@K41^8o1``t_BTs;s*?Di?3Qj$+EH^SVI7mpfl+?}7ch2?aay@Tlj1&4J z+Tqz&vPUMe#{6!>HV&Y>EwMQ8pANiU;mS4TK;YhMk@eO5l24C#n)Lb!SBVt!0Rd18 zwi4uX9(jk$o=3@5qSVkjf~v9#&PC zBU@x6sxvKxZ$xbnYTWC}E%@Wx!A!v`(LS1U<(ZVKo-|adrCjpK&}AxK>8i5BrSR<2 z1e@&VQtKVgR!W}F`(Y(txFw`9aP_Sl%e()-eSW~X(QZdc`0RqT;AWc{95+1eVjKOk z5A9DXXx*^mx^nx)1=+t9?{wajxnb2IE-t?A2SbHReO;JIiX_lK44$rjF6*2UngA06 BWjz1@ literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/toolopen.BMP b/indra/newview/res-sdl/toolopen.BMP deleted file mode 100644 index 5b87979304979a70dd091f04df1977261bd3ef5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 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 UUkGY>vcKlGWEIHc;HWtF1ys3!wEzGB diff --git a/indra/newview/res-sdl/toolpause.png b/indra/newview/res-sdl/toolpause.png new file mode 100644 index 0000000000000000000000000000000000000000..10e1cb13c9b2f170283fb381d347c9d784934887 GIT binary patch literal 257 zcmV+c0sj7pP)z600000NkvXX Hu0mjf=df$s literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/toolpickobject3.BMP b/indra/newview/res-sdl/toolpickobject3.BMP deleted file mode 100644 index fc286980501efa6815696413f6c8e268b37ae1d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmeH{cT~@B6vtl?C8LtaNJU6x6lH}5Au1K2C>lmavV~HT3Q?%622oi>XrP6P$|@Nt zB73iF`F>T0-%3|IE-p@^Mvah=kf3qn#x!Ztgr-fK(yUoC zBqb%0l9EDNTAJp~n9CWy_YdYSjukIXPOlZcUpuZD`xJE$!O1Ltb8< z_U+rFprC-Fq9RI4N_6PZfsP$JqO7b;r%s*d+_^Jdx^zKBMTM?iyP~S9ikg}l>gwur z>(-6#-MiDHM-O`T?1_ek2AZ0h^y<}%-o1OHrKN?owl;nG^r3IxzVz$YkN*ApGhn~~ zbaZqWIB+0?1`T5H;KAtX>Y}HohrYf(1_lNU88U>SLx*B$XvnZ(!x%n%I3q@kz{tpm zkt0VkYSbuoXDg}ld!R|!PeH6$&)8DWy%!n?Ch|&x5vT30Y^tircRy8v}x0rK7Bef zX3W6J$%&aWXEJNnEN0K1&73)NaCUZP?%cV!xVSKH-aO{dpU;8?3s|^tA&V9*V)5d| zELpOIrAwFM>gvj}Wy@H;d^syttia994R?2UR<2x$hldBAo}R2)wF)mUFIKN!jkmWq zYu2p6$Hxa>Utj$E{8+noE$h~;WBvN|`1|{_VZ#PCZrn&fKmdV(fo$5eiOrigvt`Q` zf`Wnw4h|+HB!sP7x3X>9Hnwly&W;^B*tv5jp`oFKg@q9w9!^9=1iN;H4jm#kHkP=!I1V2^%#kBUh>wrw z=+UDbJ9doY$B&bckU(N$B1uU}Bqt|x;=~C~o;=B^Q>REtNg*{gm9(@p($mw)$jIRI z>C>D!bB42L&yty$Nmf=C+1c5gJ9m!r=g*UqlS6K9E_r!*T)1$7ix)3)>Cz=GU%t$h zD_6+R&!?cEfU8%pQdn5XwQJY7e*HQ(ZrtGJ&6^Yz6>;m&WF=e&6Ff|oB} z^6J$qUcY|Ln>TNG`}QsG-o4}f`}dTWm-FGn2R?rM$fr-A`26`ZU%q_d>({S*`}U3R z-@j8)Q6cQ_|Mg!@K=3cEE7jiy{x5jt#kJlq$o#j;e)3v^s^$EdrBYUvz9udRsFn+i zKQ0ius=46&BS6Tiy|r+mO1Ol1YSIh5m7p#zEUXS*-DWNME8D77U)6PGmH&JpHEDj2 X5b!GX@7`Z_4I}*p1yEP|yQ_%k=TwCi!M4{(Z?+bot#G RJV3WHc)I$ztaD0e0sz5%RJZ^D literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/toolplay.BMP b/indra/newview/res-sdl/toolplay.BMP deleted file mode 100644 index 9c40d7dbecab270979b9a06fe4a7a0fe5ac1a56c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3128 zcmds%F>As=6vxwoLuiK3DT6}=3H<<4x*4*GG?U;e_yK}zhKvpoH^Eh$0!ro#0SA{3 zet>+2Oo4m=`^Q%fNz<6vm!%KxIPSgs{V)H^o%!*uNSAm+|BCkV-5w+jBT0Hh{`ra8 zWdhyjzmCJ<(ChUUi$!x^2@fsHYPZ|7*$i^*Lg1gz=QxgS+g221JRS!@z^FoeNFdTQ z^*pcB=@^EwUawhHuKA>b-uL}}zpv}M<2c9T@h?J!d=fgHPSfdBRn^I45{BV@DkXeU zNs`2M-BznL7z{R>O(6etGfk8Ie6uWDE|=YI7ysvKwW@1H zVLkaz_e+*#+^_w9Us!qHB>1DzNYgaD4^b4|2Ps*F_ia9(mlV`ZiA!2{VU>EoVF&_) zD)l#Oa-1gkLV_KRuOlW&G{+~yFUGSuPe&v6OmGsyq==g*SY7~*Am;{1m9MRm{f*B8 j#|8@dT<}6ZBm5_y7oOv@!>{>Gzy-e{IPsfg9JI}z7{DZc<Mpug7Tg; zJ!XSX3Ed@0SVG_T*tX5gCqKpvKtl++EK5;_BNCh@06^Qe)o~o_5y;;#45tYYegSqT zP)&jmg3j|?$An$i>AJ2@!|3k?(KJnOH$SrX$fKb(AESTViVw}xnm~PRFUbG^002ov JPDHLkV1iq1fja;I literal 0 HcmV?d00001 diff --git a/indra/newview/res-sdl/toolsit.BMP b/indra/newview/res-sdl/toolsit.BMP deleted file mode 100644 index 8ce59ae97a9bbb6a2485265fcb02aa8a8ad653d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3126 zcmd6p%}!cT5XZqtAW~6?B8pZ)r5K{16;cBQgaG2#(ueT@T=^WD@DQfUu3UBHGq`d| zwDu>bOeXhSZb-CAC%K3JJ!kH3=FIuf##!l;Z(t?bEYI5C$L~v^FveqH^Oz2w@8^GP z!yMm!|3#X6dwV*B(H|8E+Qr4ikD>K?z1!Q{>+9Q^g1vE_W1bte!c^K zd3gz0+MAo3cZSfJ-{0T!>S)L0uPIwyU0q&Yo}Zten3$mKBy7s!AQS7?>+99km3N5s z_4Rx{zqPfMPNzQ)j8GdJ8w(2y5FQ>LfScCl6Pk4y#RmvEnM}^k&eFpCGBCu_(vrYQ z5`u}s&VeZ{odk8|Z*Fb^ft<-?_V@RT#p2hYK}J#;J~!#ngLXAnKFr0%Me3ljL;Tw> zz}?+lLg2ZwvSRpTPPNT)Aeh(j@i8r|<4 zLZ&i=aKPj7IGGDvGl2--goD4cvm<Mh+bv0!Qu~^J3 zsN|`cS__{&rt=q+tB6LULN-D(wH7`lq7*DEW%o{=h-@2O90QSvHlHDqHz9y?u3giX z&QvPJZWo~8gLT-;%kO@_Pp9!DgfVuV-|rWiLy!Q)*YHt%3FmOmX0w4nz=4%l__94dF ztOz~Ihb*6+v+iO4SF2T~Kr*%oR)qFBJUpD6o6|H~2ZKTGlSZRK2-^fJLVW7=I=eI+ z4%I-Da}iEfcH=1nIg0z!FhV+aSf5Ld1TYSa*g;$H>U z`uzO-IRMOG_ diff --git a/indra/newview/res-sdl/toolsit.png b/indra/newview/res-sdl/toolsit.png new file mode 100644 index 0000000000000000000000000000000000000000..8620527e521be7dac2a117dc7e5be39442a63824 GIT binary patch literal 1492 zcmV;_1uOcAP)Nkl7hC8OMJ!cKj8ONo?nXU=c@lDypccopM@54Xt`ebBI<|4@gz7`*m4u0SO^)dqFEz zDm`wg_Ohyi5PKs?s8W*BCRGawu%v2;*>$pj-6US{*q+Sy>|w_%$2i7pc%(<;nX&!< zzt8{qcwd3eY!v7NMgSj>1HK0S#{o@f^R6oriJb21>-$|Ikw``&5q~rqJtPQ%P^na& zYno=3N~Oxq&d#TmO64M;zcvDXzyG}>M~?hHlgXr_(P+@NZA{a|vMd06J|BTV0H4oC ztyVK0J$h6u7K?wLM5nQYw|cUR_=N zL{XG8uR_4r3_dnC_I@&%>`_(qrQiUzZDUy$(P%W>)6?@4MNtNHUBA&O0e@rIM@B~8 z>Fw>6YPDKR;Dv>SmVYuaF@dV8NRkxJWHP^9U0vPKb-g1w#Cjy+@%ZV%!NH`esyL2= z>$)%ae&)I^j^nVqyGvhRUpyX-Sl2Y| zdAlrsX*3$ZXJ%$_-3L5={5a{l?pHuB5ZZ6>i2#BiELJKN{Z(aXF2!Q8h$KmkkBEcTaTvAA;(0{b+oqn-}{hdjxJR>SCSC=~kp_V)H0?dPmP)0P>hpbDk!R1IeF3a_ z)o0FpJN}#d#MIOj=gysDZS6Avu3!HMV0&t6O7$WV1$<&d^H_|%de*A( zG!m*OUN)PhR;y7el`8djmC8}Z$H$qRoCL-gA0PjY)b;BhA zTeVv4r>d&H(cj%E}6| zEIYt2fiLzfGoQ~tGfng3P$)D%JUskqtya5{%jLd!`t<4l%jL3GtyZa4t0;=17Yc># zTrS7@`Z^O66S(dJmY0_SSYKb~>eZ`MDwRFg1~Y&F;P*E(%;)pZ(&_Z&a=HAoP$*PQ zCX=5VhS96*ddx5kzo)kyiA1y~Po5-BojUdA%*+g>`7o~npScgXY20WyK@&VT)1@k z@?}OxN85&9k~ZDN#l`2q1E2(G{&qje=krxy$@Avjv>)gOlDS;&((>{$vMe_@qCG{k zvSO6apFe*O_#?0j*uDddeb;lLP$>NO{{8!J9zTAZL?XfP@GzU3n@mqnQ!Eylo}PA# z#bQ|$#no%quKgRB_YN}JLH8a$ubxxD+p;XX^Yinrq9|_N6h(0qMR~rnv-2O|&%n=t zjMobyJ`Qg6NIWSN3SX+K`m0nb#m2@48yg$kyLYd;wzjr*>(;H$Z{EE52>7QLe)anv z=USbvy1c3P16h{qge*V-{sCM9J^+3U3<7a)LW%;f#{{pgW56%G!4m)~-kzZ9)qc^_ uUGwhk*F~V74}k{vH%Vl9p!Gpy1MWAxcpMHh=(h0y0000 Date: Sat, 10 Oct 2026 05:59:02 -0400 Subject: [PATCH 9/9] The Linux window carries the channel's own icon, with its alpha The window icon was res-sdl/ll_icon.BMP, the channel's 256 BMP with an opaque magenta (#FF00F6) border meant to be keyed out, which nothing did, so X11 title bars and taskbars and KDE's Wayland showed the icon in a magenta frame. The window now takes the hicolor PNGs the tree installs for its desktop entry, share/icons/hicolor//apps/.png, found from the read-only data dir and the app ID SDL was given: the 256 as the icon, as before, and the 512 as its 2x. SDL sends X11 only the icon itself and Wayland only alternates at whole multiples of it, so the smaller sizes are not loaded. A tree without them keeps the desktop's default icon. macOS still leaves the window icon alone, since SDL would set the Dock's over the bundle's. Nothing reads ll_icon.BMP any more, in res-sdl/ or, on Windows, in res/, whose resource script embeds only ll_icon.ico, so neither is copied from the branding package, and the Linux tree installs only the cursor PNGs from res-sdl/, leaving out a copy an older configure left there. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_018TgkpVXucG17x8kCrsXMjy --- indra/cmake/ViewerInstall.cmake | 10 ++++- indra/llwindow/llwindowsdl.cpp | 69 +++++++++++++++++++++------------ indra/newview/CMakeLists.txt | 20 +--------- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/indra/cmake/ViewerInstall.cmake b/indra/cmake/ViewerInstall.cmake index 45a6ba6002..e40b0a763e 100644 --- a/indra/cmake/ViewerInstall.cmake +++ b/indra/cmake/ViewerInstall.cmake @@ -693,7 +693,15 @@ if(LINUX) DESTINATION etc COMPONENT viewer ) - install(DIRECTORY "${al_newview_dir}/res-sdl" DESTINATION . COMPONENT viewer) + # The window's cursors, and not the ll_icon.BMP older configures copied in + # beside them: the window's icon is the desktop entry's now, below. + install( + DIRECTORY "${al_newview_dir}/res-sdl" + DESTINATION . + COMPONENT viewer + FILES_MATCHING + PATTERN "*.png" + ) # The desktop entry, its AppStream data and its icons, laid out under share/ # as they go under /usr/share. The entry runs the launcher by the package diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index f88248fe1d..24e450784f 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -196,23 +196,49 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, } #if LL_LINUX -// The window icon BMP (res-sdl/) is only shipped in the Linux bundle, so this -// helper would be unused on the other platforms — and the build is -Werror on -// unused static functions. -static SDL_Surface *Load_BMP_Resource(const char *basename) +// One size of the channel's icon, from the hicolor sizes the tree carries +// under share/icons for its desktop entry, named for the application ID +// llappviewersdl.cpp gives SDL. +static SDL_Surface *loadWindowIcon(S32 size) { - const int PATH_BUFFER_SIZE=1000; - char path_buffer[PATH_BUFFER_SIZE]; /* Flawfinder: ignore */ - - // Figure out where our BMP is living on the disk - snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s", - gDirUtilp->getAppRODataDir().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - basename); - path_buffer[PATH_BUFFER_SIZE-1] = '\0'; - - return SDL_LoadBMP(path_buffer); + const char *app_id = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING); + if (!app_id || !*app_id) + { + SDL_SetError("no application ID"); + return nullptr; + } + const std::string dims = std::to_string(size) + "x" + std::to_string(size); + const std::string path = gDirUtilp->add(gDirUtilp->getAppRODataDir(), "share", "icons", + "hicolor", dims, "apps", std::string(app_id) + ".png"); + return SDL_LoadPNG(path.c_str()); +} + +// The window's icon, which X11 desktops show from _NET_WM_ICON and KDE's +// Wayland from xdg_toplevel_icon_v1. SDL sends X11 the surface alone, and +// Wayland its alternates only at whole multiples of its size, so the 256 is +// the icon and the 512 its 2x; a smaller size would never be sent. A tree +// without them, a build that was never staged, keeps the desktop's default. +static void setWindowIcon(SDL_Window *window) +{ + SDL_Surface *icon = loadWindowIcon(256); + if (!icon) + { + LL_INFOS() << "No window icon: " << SDL_GetError() << LL_ENDL; + return; + } + if (SDL_Surface *icon_2x = loadWindowIcon(512)) + { + // The icon takes a reference of its own, released with it. + SDL_AddSurfaceAlternateImage(icon, icon_2x); + SDL_DestroySurface(icon_2x); + } + if (!SDL_SetWindowIcon(window, icon)) + { + // A compositor without xdg_toplevel_icon_v1 shows the desktop + // entry's icon, which it finds by the window's app ID. + LL_INFOS() << "Window icon not set: " << SDL_GetError() << LL_ENDL; + } + SDL_DestroySurface(icon); } #endif // LL_LINUX @@ -503,14 +529,9 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b #endif #if LL_LINUX - // Set the application icon. - SDL_Surface* bmpsurface = Load_BMP_Resource("ll_icon.BMP"); - if (bmpsurface) - { - SDL_SetWindowIcon(mWindow, bmpsurface); - SDL_DestroySurface(bmpsurface); - bmpsurface = nullptr; - } + // The channel's icon. Not on macOS, where SDL would put it on the Dock + // over the bundle's own, nor Windows, where the exe's icon serves. + setWindowIcon(mWindow); #endif // SDL3 ties both committed-text events (SDL_EVENT_TEXT_INPUT) and diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b56ef29f8..b6c5522602 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -108,28 +108,14 @@ if(AL_BUILD_VIEWER) find_package(unofficial-alchemy-branding CONFIG REQUIRED) set(BRANDING_SOURCE_DIR "${ALCHEMY_BRANDING_DIR}") + # Linux's window takes the hicolor PNGs installed for the desktop entry + # (ViewerInstall.cmake), and macOS's the bundle's alchemy.icns. if(WINDOWS) file( COPY_FILE "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy.ico" "${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.ico" ONLY_IF_DIFFERENT ) - file( - COPY_FILE "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP" - "${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.BMP" - ONLY_IF_DIFFERENT - ) - file( - COPY_FILE "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP" - "${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/ll_icon.BMP" - ONLY_IF_DIFFERENT - ) - elseif(LINUX) - file( - COPY_FILE "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP" - "${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/ll_icon.BMP" - ONLY_IF_DIFFERENT - ) endif() # Branded splash icon for the SDL splash screen (LLSplashScreenSDL loads this @@ -1999,8 +1985,6 @@ if(AL_BUILD_VIEWER) res/lltooltranslate.cur res/lltoolzoomin.cur res/lltoolzoomout.cur - res-sdl/ll_icon.BMP - res/ll_icon.BMP res/ll_icon.ico res/resource.h res/toolpickobject.cur