diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index b63cc52bec..13422612d6 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -54,14 +54,29 @@ std::string apr_strerror_helper(apr_status_t rv) *****************************************************************************/ #define ensure_equals_(left, right) \ - ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right)) +do { \ + auto _left_val = (left); \ + auto _right_val = (right); \ + if (_left_val != _right_val) { \ + std::string _msg = std::string(#left) + " != " + std::string(#right); \ + tut::ensure_equals(_msg, _left_val, _right_val); \ + } else { \ + tut::ensure_equals("", _left_val, _right_val); \ + } \ +} while(0) #define aprchk(expr) aprchk_(#expr, (expr)) static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS) { - tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper - (rv)), - rv, expected); + if (rv != expected) + { + std::string msg = std::string(call) + " => " + std::to_string(rv) + ": " + apr_strerror_helper(rv); + tut::ensure_equals(msg, rv, expected); + } + else + { + tut::ensure_equals("", rv, expected); + } } /** @@ -78,11 +93,14 @@ static std::string readfile(const std::string& pathname, const std::string& desc std::string use_desc(desc); if (use_desc.empty()) { - use_desc = STRINGIZE("in " << pathname); + use_desc = "in " + pathname; } std::ifstream inf(pathname.c_str()); std::string output; - tut::ensure(STRINGIZE("No output " << use_desc), bool(std::getline(inf, output))); + if (!std::getline(inf, output)) + { + tut::ensure("No output " + use_desc, false); + } std::string more; while (std::getline(inf, more)) { @@ -108,8 +126,8 @@ void waitfor(LLProcess& proc, int timeout=60) { yield(); } - tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"), - i < timeout); + std::string msg = "process took longer than " + std::to_string(timeout) + " seconds to terminate"; + tut::ensure(msg, i < timeout); } void waitfor(LLProcess::handle h, const std::string& desc, int timeout=60) @@ -119,8 +137,8 @@ void waitfor(LLProcess::handle h, const std::string& desc, int timeout=60) { yield(); } - tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"), - i < timeout); + std::string msg = "process took longer than " + std::to_string(timeout) + " seconds to terminate"; + tut::ensure(msg, i < timeout); } /** @@ -153,7 +171,8 @@ struct PythonProcessLauncher try { mPy = LLProcess::create(mParams); - tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy)); + std::string msg = "Couldn't launch " + mDesc + " script"; + tut::ensure(msg, bool(mPy)); } catch (const tut::failure&) { @@ -214,7 +233,8 @@ struct PythonProcessLauncher mParams.args.add(out.getName()); run(); // assuming the script wrote to that file, read it - return readfile(out.getName(), STRINGIZE("from " << mDesc << " script")); + std::string desc = "from " + mDesc + " script"; + return readfile(out.getName(), desc); } LLProcess::Params mParams; diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 82228f2db0..ee18abaa4d 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -95,6 +95,7 @@ public: #if LL_WINDOWS virtual bool getCursorDelta(LLCoordCommon* delta) = 0; #endif + virtual bool isWrapMouse() const = 0; virtual void showCursor() = 0; virtual void hideCursor() = 0; virtual bool isCursorHidden() = 0; diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 5696b69a59..dc7b833013 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -63,6 +63,7 @@ public: #if LL_WINDOWS /*virtual*/ bool getCursorDelta(LLCoordCommon* delta) override { return false; } #endif + /*virtual*/ bool isWrapMouse() const override { return true; } /*virtual*/ void showCursor() override {} /*virtual*/ void hideCursor() override {} /*virtual*/ void showCursorFromMouseMove() override {} diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 70e0a23c97..90f167fadd 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -63,6 +63,7 @@ public: bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override; bool setCursorPosition(LLCoordWindow position) override; bool getCursorPosition(LLCoordWindow *position) override; + bool isWrapMouse() const override { return !mCursorDecoupled; }; void showCursor() override; void hideCursor() override; void showCursorFromMouseMove() override; diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 3bf341eb11..b62b48bda1 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -72,6 +72,7 @@ public: /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL); /*virtual*/ bool setCursorPosition(LLCoordWindow position); /*virtual*/ bool getCursorPosition(LLCoordWindow *position); + /*virtual*/ bool isWrapMouse() const override { return true; } /*virtual*/ void showCursor(); /*virtual*/ void hideCursor(); /*virtual*/ void showCursorFromMouseMove(); diff --git a/indra/llwindow/llwindowsdl2.h b/indra/llwindow/llwindowsdl2.h index 390ff2eafc..ed6440f48c 100644 --- a/indra/llwindow/llwindowsdl2.h +++ b/indra/llwindow/llwindowsdl2.h @@ -74,6 +74,7 @@ public: // /*virtual*/ bool setCursorPosition(LLCoordWindow position); /*virtual*/ bool getCursorPosition(LLCoordWindow *position); + /*virtual*/ bool isWrapMouse() const override { return true; } /*virtual*/ void showCursor(); /*virtual*/ void hideCursor(); /*virtual*/ void showCursorFromMouseMove(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index bd22ff5a71..c34abfaa9d 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -451,6 +451,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, bool useLegacyCursors) // Legacy cursor setting from main program : LLWindow(callbacks, fullscreen, flags), + mAbsoluteCursorPosition(false), mMaxGLVersion(max_gl_version), mMaxCores(max_cores) { @@ -3262,6 +3263,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ prev_absolute_x = absolute_x; prev_absolute_y = absolute_y; + window_imp->mAbsoluteCursorPosition = true; } else { @@ -3278,6 +3280,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ window_imp->mRawMouseDelta.mX += (S32)round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED); window_imp->mRawMouseDelta.mY -= (S32)round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED); } + window_imp->mAbsoluteCursorPosition = false; } } } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index db09dd06ae..88bc6957fd 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -70,6 +70,7 @@ public: /*virtual*/ bool setCursorPosition(LLCoordWindow position); /*virtual*/ bool getCursorPosition(LLCoordWindow *position); /*virtual*/ bool getCursorDelta(LLCoordCommon* delta); + /*virtual*/ bool isWrapMouse() const override { return !mAbsoluteCursorPosition; }; /*virtual*/ void showCursor(); /*virtual*/ void hideCursor(); /*virtual*/ void showCursorFromMouseMove(); @@ -198,6 +199,7 @@ protected: HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread + bool mAbsoluteCursorPosition; // true if last position was received in absolute coordinates. LLMutex mRawMouseMutex; RAWINPUTDEVICE mRawMouse; LLCoordWindow mLastCursorPosition; // mouse cursor position from previous frame diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9e724c771a..fcb9e1c5ff 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4884,16 +4884,16 @@ Value 0 - DisableMouseWarp + MouseWarpMode Comment - Disable warping of the mouse to the center of the screen during alt-zoom and mouse look. Useful with certain input devices, mouse sharing programs like Synergy, or running under Parallels. + Controls warping of the mouse to the center of the screen during alt-zoom and mouse look. Useful with certain input devices, mouse sharing programs like Synergy, or running under Parallels. 0 - automatic, 1 - on, 2 - off Persist 1 Type - Boolean + S32 Value - 0 + 1 DisableExternalBrowser diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a4a6307c4f..7fd4c7ce8d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1215,6 +1215,17 @@ void LLFloaterPreference::onOpen(const LLSD& key) // Load (double-)click to walk/teleport settings. updateClickActionViews(); +#if LL_LINUX + // Lixux doesn't support automatic mode + LLComboBox* combo = getChild("double_click_action_combo"); + S32 mode = gSavedSettings.getS32("MouseWarpMode"); + if (mode == 0) + { + combo->setValue("1"); + } + combo->setEnabledByValue("0", false); +#endif + // Load UI Sounds tabs settings. updateUISoundsControls(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e06a4dade7..caf7bb3214 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4791,6 +4791,32 @@ void LLFolderBridge::pasteLinkFromClipboard() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + if (objects.size() == 0) + { + LLClipboard::instance().setCutMode(false); + return; + } + + LLUUID& first_id = objects[0]; + LLInventoryItem* item = model->getItem(first_id); + if (item && item->getAssetUUID().isNull()) + { + if (item->getActualType() == LLAssetType::AT_NOTECARD) + { + // otehrwise AIS will return 'Cannot link to items with a NULL asset_id.' + LLNotificationsUtil::add("CantLinkNotecard"); + LLClipboard::instance().setCutMode(false); + return; + } + else if (item->getActualType() == LLAssetType::AT_MATERIAL) + { + LLNotificationsUtil::add("CantLinkMaterial"); + LLClipboard::instance().setCutMode(false); + return; + } + } + + LLPointer cb = NULL; LLInventoryPanel* panel = mInventoryPanel.get(); if (panel->getRootFolder()->isSingleFolderMode()) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 5c990f5727..8aaba44292 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2126,6 +2126,30 @@ void LLInventoryGallery::pasteAsLink() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + if (objects.size() == 0) + { + LLClipboard::instance().setCutMode(false); + return; + } + + LLUUID& first_id = objects[0]; + LLInventoryItem* item = gInventory.getItem(first_id); + if (item && item->getAssetUUID().isNull()) + { + if (item->getActualType() == LLAssetType::AT_NOTECARD) + { + LLNotificationsUtil::add("CantLinkNotecard"); + LLClipboard::instance().setCutMode(false); + return; + } + else if (item->getActualType() == LLAssetType::AT_MATERIAL) + { + LLNotificationsUtil::add("CantLinkMaterial"); + LLClipboard::instance().setCutMode(false); + return; + } + } + bool paste_into_root = mSelectedItemIDs.empty(); for (LLUUID& dest : mSelectedItemIDs) { diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 7c64b7f61d..3251d3c93f 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -615,20 +615,23 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men bool has_children = false; bool is_full_perm_item = false; bool is_copyable = false; - LLViewerInventoryItem* selected_item = gInventory.getItem(selected_id); + + LLViewerInventoryCategory* selected_category = nullptr; + LLViewerInventoryItem* selected_item = nullptr; if(is_folder) { - LLInventoryCategory* category = gInventory.getCategory(selected_id); - if (category) + selected_category = dynamic_cast(obj); + if (selected_category) { - folder_type = category->getPreferredType(); + folder_type = selected_category->getPreferredType(); is_system_folder = LLFolderType::lookupIsProtectedType(folder_type); has_children = (gInventory.categoryHasChildren(selected_id) != LLInventoryModel::CHILDREN_NO); } } else { + selected_item = dynamic_cast(obj); if (selected_item) { is_full_perm_item = selected_item->getIsFullPerm(); @@ -747,8 +750,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits) { - LLViewerInventoryCategory* category = gInventory.getCategory(selected_id); - if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category)) + if (!selected_category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(selected_category)) { items.push_back(std::string("New Folder")); } @@ -776,6 +778,22 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if (inventory_linking) { items.push_back(std::string("Paste As Link")); + + if (selected_item) + { + if (!LLAssetType::lookupCanLink(selected_item->getActualType())) + { + disabled_items.push_back(std::string("Paste As Link")); + } + else if (gInventory.isObjectDescendentOf(selected_item->getUUID(), gInventory.getLibraryRootFolderID())) + { + disabled_items.push_back(std::string("Paste As Link")); + } + } + else if (selected_category && LLFolderType::lookupIsProtectedType(selected_category->getPreferredType())) + { + disabled_items.push_back(std::string("Paste As Link")); + } } } if (is_folder && is_agent_inventory) @@ -1032,9 +1050,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men { if (is_folder) { - LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); - if (cat - && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) + if (selected_category + && !LLFolderType::lookupIsProtectedType(selected_category->getPreferredType()) && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID())) { can_list = true; diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1de859aa80..6ba8ece706 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -445,10 +445,7 @@ bool LLTaskInvFVBridge::removeItem() return true; } - LLSD payload; - payload["task_id"] = mPanel->getTaskUUID(); - payload["inventory_ids"].append(mUUID); - LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + LLNotificationsUtil::add("CantModifyContentInNoModTask"); return false; } } @@ -471,13 +468,7 @@ void LLTaskInvFVBridge::removeBatch(std::vector& batch) if (!object->permModify()) { - LLSD payload; - payload["task_id"] = mPanel->getTaskUUID(); - for (LLFolderViewModelItem* item : batch) - { - payload["inventory_ids"].append(((LLTaskInvFVBridge*)item)->getUUID()); - } - LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + LLNotificationsUtil::add("CantModifyContentInNoModTask"); } else { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c072c9fb81..0ab60050ff 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3801,7 +3801,31 @@ void LLViewerWindow::clearPopups() void LLViewerWindow::moveCursorToCenter() { - if (! gSavedSettings.getBOOL("DisableMouseWarp")) + bool mouse_warp = false; + LLCachedControl mouse_warp_mode(gSavedSettings, "MouseWarpMode", 1); + + switch (mouse_warp_mode()) + { + case 0: + // For Windows: + // Mouse usually uses 'delta' position since it isn't aware of own location, keep it centered. + // Touch screen reports absolute or virtual absolute position and warping a physical + // touch is pointless, so don't move it. + // + // MacOS + // If 'decoupled', CGAssociateMouseAndMouseCursorPosition can make mouse stay in + // one place and not move, do not move it (needs testing). + mouse_warp = mWindow->isWrapMouse(); + break; + case 1: + mouse_warp = true; + break; + default: + mouse_warp = false; + break; + } + + if (mouse_warp) { S32 x = getWorldViewWidthScaled() / 2; S32 y = getWorldViewHeightScaled() / 2; diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index bf290baeed..a09f38ed15 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2703,6 +2703,12 @@ Möchten Sie es mit dem ausgewählten Objekt ersetzen? Sie können keinen Ordner tragen, der mehr als [AMOUNT] Elemente enthält. Sie können diesen Höchstwert unter „Erweitert“ > „Debug-Einstellungen anzeigen“ > „WearFolderLimit“ ändern. + + Sie müssen die Notizkarte speichern, bevor Sie eine Verknüpfung dorthin herstellen können. + + + Sie müssen das Material speichern, bevor Sie eine Verknüpfung dorthin herstellen können. + Sie haben den Nicht-stören-Modus aktiviert. Sie erhalten keine Artikel, die im Gegenzug für diese Zahlung angeboten werden. diff --git a/indra/newview/skins/default/xui/de/panel_preferences_move.xml b/indra/newview/skins/default/xui/de/panel_preferences_move.xml index 9b1df8c12a..98adc78d23 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_move.xml @@ -29,6 +29,14 @@ + + Maus-Warp: + + + + + + @@ -61,6 +69,7 @@ + Bewegungsvorhersage beim Regionswechsel: diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c041588b4e..17aa084262 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6882,6 +6882,22 @@ Do you want to replace it with the selected object? fail + + You must save the notecard before creating a link to it. + fail + + + + You must save the material before creating a link to it. + fail + + - + + Mouse Warp: + + + + + + +