PageSourceSearch

https://linguax.app/assets/js/d47f0019.a75a000f.js

js linguax.app collected 2026-10-04 08:33:18 UTC 43,489 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunklinguax_web=self.webpackChunklinguax_web||[]).push([[698],{2406:(e,t,i)=>{i.d(t,{A:()=>R});var s=i(6540),n=i(1312),r=i(4586),a=i(8774);const o={fallback:"fallback_pud7",fallbackHeader:"fallbackHeader_MsY5",fallbackTitle:"fallbackTitle_uXyr",fallbackDesc:"fallbackDesc_oxUa",fallbackActions:"fallbackActions_phFu",primaryBtn:"primaryBtn_P1sw",secondaryBtn:"secondaryBtn_KEbK",disclaimer:"disclaimer_AelQ",hint:"hint_PK5u",error:"error_iKR3",pairingBox:"pairingBox_ux0O",pairingTitle:"pairingTitle_oI2O",linkBtn:"linkBtn_YpZo",pickerList:"pickerList_nW7g",clickSequence:"clickSequence_K6is",clickDone:"clickDone_qAYD",clickPending:"clickPending_JrMx",pairedTable:"pairedTable_hbUE"};var l=i(4848);function d(){return(0,l.jsxs)("aside",{className:o.fallback,"aria-label":"Browser pairing not available",children:[(0,l.jsxs)("div",{className:o.fallbackHeader,children:[(0,l.jsx)("h3",{className:o.fallbackTitle,children:(0,l.jsx)(n.A,{id:"pairWidget.fallback.title",description:"Safari/non-Chromium fallback title",children:"Pair in-browser (requires Chrome or Edge)"})}),(0,l.jsx)("p",{className:o.fallbackDesc,children:(0,l.jsx)(n.A,{id:"pairWidget.fallback.desc",description:"Fallback subtitle promoting native app",children:"Or install LinguaX for macOS \u2014 first-time pairing handled natively, no browser required."})})]}),(0,l.jsxs)("div",{className:o.fallbackActions,children:[(0,l.jsx)(a.A,{to:"/download",className:o.primaryBtn,children:(0,l.jsx)(n.A,{id:"pairWidget.fallback.download",description:"Fallback download button",children:"Download LinguaX for macOS"})}),(0,l.jsx)(a.A,{to:"/tools/pair-logitech-receiver",className:o.secondaryBtn,children:(0,l.jsx)(n.A,{id:"pairWidget.fallback.learnMore",description:"Fallback learn-more link",children:"Learn more about pairing"})})]}),(0,l.jsx)("p",{className:o.disclaimer,children:(0,l.jsx)(n.A,{id:"pairWidget.disclaimer",description:"Logitech trademarks disclaimer (shared with widget)",children:"Not affiliated with or endorsed by Logitech. \u201cLogitech\u201d, \u201cMX Master\u201d, \u201cBolt\u201d, \u201cUnifying\u201d, \u201cLightspeed\u201d are trademarks of Logitech International SA, used descriptively for compatibility."})})]})}function c({children:e}){const{siteConfig:t}=(0,r.A)(),i=!1!==t.customFields?.pairingToolEnabled,[n,a]=(0,s.useState)(!1);return(0,s.useEffect)((()=>{i&&"undefined"!=typeof navigator&&"hid"in navigator&&a(!0)}),[i]),i&&n?(0,l.jsx)(l.Fragment,{children:e}):(0,l.jsx)(d,{})}const h=255,p=128,u=193,g=1,m=2,x=1,f=3,w=0,b=0,y={PASSKEY:1,PASSKEY_EMULATION_2_BUTTON:2},j={ENTRY_STARTED:0,DIGIT_ENTERED:1,DIGIT_ERASED:2,CLEARED:3,ENTRY_COMPLETED:4};function k(e,t,i,s=!1){const n=s?17:4;if(i.length>n)throw new Error(`params \u8d85\u957f: ${i.length} > ${n}`);const r=new Uint8Array(2+n);r[0]=255&e,r[1]=255&t;for(let a=0;a<i.length;a++)r[2+a]=255&i[a];return r}class v extends Error{constructor(e,t){super(e),this.errorCode=t,this.name="HidppError"}}class S extends Error{constructor(e="HID++ response timeout"){super(e),this.name="HidppTimeout"}}class A{listeners=new Set;onReport=e=>{if(16!==e.reportId&&17!==e.reportId)return;const t=new Uint8Array(e.data.buffer,e.data.byteOffset,e.data.byteLength),i=function(e,t){if(t.length<2)throw new Error(`payload \u8fc7\u77ed: ${t.length}`);return{reportId:e,deviceIdx:t[0],subId:t[1],params:t.subarray(2)}}(e.reportId,t);for(const s of this.listeners)s(i)};constructor(e){this.device=e}async open(){this.device.opened||await this.device.open(),this.device.addEventListener("inputreport",this.onReport)}async close(){this.device.removeEventListener("inputreport",this.onReport),this.device.opened&&await this.device.close()}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async registerRequest(e,t,i,s=[],n={}){const{long:r=!1,timeoutMs:a=3e3}=n,o=k(e,t,[i,...s],r),l=r?17:16;return new Promise(((s,n)=>{const r=setTimeout((()=>{d(),n(new S)}),a),d=this.subscribe((a=>{if(function(e,t,i,s){return e.deviceIdx===t&&(e.subId===i&&e.params[0]===s||143===e.subId&&e.params[0]===i&&e.params[1]===s)}(a,e,t,i))if(clearTimeout(r),d(),143===a.subId){const e=a.params[2];n(new v(`HID++ error 0x${e?.toString(16)} on sub 0x${t.toString(16)} reg 0x${i.toString(16)}`,e))}else s(a)}));this.device.sendReport(l,o).catch((e=>{clearTimeout(r),d(),n(e)}))}))}waitFor(e,t){return new Promise(((i,s)=>{const n=setTimeout((()=>{r(),s(new S)}),t),r=this.subscribe((t=>{e(t)&&(clearTimeout(n),r(),i(t))}))}))}}class M{kind="unifying";opened=!1;constructor(e){this.transport=new A(e)}
1async open(){this.opened||(await this.transport.open(),await this.transport.registerRequest(h,p,0,[0,1,0]),this.opened=!0)}async close(){this.opened=!1,await this.transport.close()}async startPairing(e,t){await this.open();const i=Math.min(255,Math.ceil(e/1e3));await this.transport.registerRequest(h,p,178,[1,0,i]);try{const t=await this.transport.waitFor((e=>65===e.subId),e),i=t.deviceIdx,n=((s=t.params)[1]<<8|s[2])>>>0;return{index:i,name:await this.readDeviceName(i).catch((()=>"")),wpid:n.toString(16).padStart(4,"0")}}finally{await this.transport.registerRequest(h,p,178,[2,0,0]).catch((()=>{}))}var s}async listPaired(){await this.open();const e=[];for(let i=1;i<=6;i++)try{const t=await this.transport.registerRequest(h,131,181,[i-1+32],{long:!1}),s=(t.params[3]<<8|t.params[4])>>>0;if(0===s)continue;const n=await this.readDeviceName(i).catch((()=>""));e.push({index:i,name:n,wpid:s.toString(16).padStart(4,"0")})}catch(t){if(t instanceof v)continue;throw t}return e}async unpair(e){await this.open(),await this.transport.registerRequest(h,p,178,[3,255&e,0])}async readDeviceName(e){const t=await this.transport.registerRequest(h,131,181,[e-1+64],{long:!1}),i=Math.min(t.params[1]??0,t.params.length-2);let s="";for(let n=0;n<i;n++)s+=String.fromCharCode(t.params[2+n]);return s.trim()}}class T extends M{kind="lightspeed"}class N{kind="bolt";opened=!1;constructor(e){this.transport=new A(e)}async open(){if(!this.opened){await this.transport.open();try{const e=await this.transport.registerRequest(h,129,0),t=16|(e.params[1]??0),i=1|(e.params[2]??0),s=e.params[3]??0;await this.transport.registerRequest(h,p,0,[t,i,s])}catch{await this.transport.registerRequest(h,p,0,[16,1,0])}await this.transport.registerRequest(h,p,2,[2,0,0]).catch((()=>{})),this.opened=!0}}async close(){this.opened=!1,await this.transport.close()}async startPairing(e,t){await this.open();const i=new Map,s=[],n=new Set;let r=0;const a=this.transport.subscribe((e=>{if(e.deviceIdx!==h)return;if(console.log("[Bolt] notif",{subId:`0x${e.subId.toString(16)}`,reportId:`0x${e.reportId.toString(16)}`,params:Array.from(e.params).map((e=>e.toString(16).padStart(2,"0"))).join(" ")}),79!==e.subId)return;const t=s.length;this.absorbDiscoveryChunk(e.params,i,s,n),0===r&&(s.length>0||i.size>0)&&(r=performance.now()),s.length>t&&console.log("[Bolt] discovered so far",s.length,s.map((e=>e.name)))}));console.log("[Bolt] start discovery"),await this.transport.registerRequest(h,p,192,[0,g,0]),console.log("[Bolt] discovery command acked");let o=null;try{o=await this.awaitDiscoveryDecision((()=>s),(()=>r),e,t)}finally{a(),await this.transport.registerRequest(h,p,192,[0,m,0]).catch((()=>{}))}if(!o)throw new S("No Bolt device discovered");return this.pairDiscovered(o,t)}absorbDiscoveryChunk(e,t,i,s){let n;if(0===(3&e[2])){const i=function(e){return{notifCounter:(e[0]<<8|e[1])>>>0,part:3&e[2],protocolType:e[3],deviceType:e[4],productId:(e[5]|e[6]<<8)>>>0,bluetoothAddress:[e[7],e[8],e[9],e[10],e[11],e[12]],extendedModelId:e[14],authMethod:e[15]}}(e);n=i.notifCounter;const s=t.get(n)??{nameChunks:[]};s.header=i,t.set(n,s)}else{const i=function(e){const t=(e[0]<<8|e[1])>>>0,i=3&e[2];return 1===i?{notifCounter:t,part:i,nameLength:e[3],chunk:e.subarray(4)}:{notifCounter:t,part:i,nameLength:null,chunk:e.subarray(3)}}(e);n=i.notifCounter;const s=t.get(n)??{nameChunks:[]};null!=i.nameLength&&(s.nameLength=i.nameLength),s.nameChunks.push(i.chunk),t.set(n,s)}const r=t.get(n);if(r.header&&null!=r.nameLength&&null==r.name){if(r.nameChunks.reduce(((e,t)=>e+t.length),0)>=r.nameLength){const e=new Uint8Array(r.nameLength);let a=0;for(const t of r.nameChunks){const i=Math.min(t.length,r.nameLength-a);if(e.set(t.subarray(0,i),a),a+=i,a>=r.nameLength)break}r.name=new TextDecoder("utf-8",{fatal:!1}).decode(e).replace(/\0+$/,"").trim(),t.delete(n);const o=r.header.bluetoothAddress.map((e=>e.toString(16).padStart(2,"0"))).join(":");if(s.has(o))return;s.add(o),i.push({bluetoothAddress:r.header.bluetoothAddress,productId:r.header.productId,name:r.name,authMethod:r.header.authMethod,deviceType:r.header.deviceType})}}}async awaitDiscoveryDecision(e,t,i,s){const n=performance.now()+i;for(;;){const i=performance.now(),r=e(),a=t();if(a>0&&i-a>=2e3&&r.length>0){if(1===r.length)return r[0];if(!s?.onDiscovered)return r[0];const e=await s.onDiscovered(r.slice());return"auto"===e?r[0]:e}if(i>=n)return null;await new Promise((e=>setTimeout(e,100)))}}async pairDiscovered(e,t){const i=[];i.push(this.transport.subscribe((i=>{if(i.deviceIdx===h)if(77===i.subId){const{digits:s}=function(e){const t=Math.min(e[0]??0,e.length-1);let i="";for(let s=0;s<t;s++)i+=String.fromCharCode(e[1+s]);return{digits:i}}(i.params),n=e.authMethod===y.PASSKEY_EMULATION_2_BUTTON?function(e){let t=BigInt(e||"0").toString(2);t.length<10&&(t=t.padStart(10,"0"));let i="";for(const s of t)i+="0"===s?"L":"R";return i}(s):void 0;console.log("[Bolt] passkey received",{authMethod:e.authMethod,digitsRaw:s,digitsAsNumber:Number(s),digitsAsBinary:Number(s).toString(2),clickSequence:n}),t?.onPasskey?.({digits:s,authMethod:e.authMethod,clickSequence:n})}else if(78===i.subId){const{keyCode:e}=function(e){return{keyCode:e[0],bluetoothAddress:[e[1],e[2],e[3],e[4],e[5],e[6]]}}(i.params),s=["ENTRY_STARTED","DIGIT_ENTERED","DIGIT_ERASED","CLEARED","ENTRY_COMPLETED"][e]??`unknown(${e})`;
1console.log("[Bolt] passkey progress",{keyCode:e,keyCodeName:s}),t?.onPasskeyProgress?.({keyCode:e})}})));const s=e.authMethod,n=s===y.PASSKEY_EMULATION_2_BUTTON?10:20,[r,a,o,l,d,c]=e.bluetoothAddress;new Uint8Array(20)[0]=u;const p=k(h,130,[u,x,0,r,a,o,l,d,c,s,n,0,0,0,0,0,0],!0),g=new Promise(((t,s)=>{const n=this.transport.subscribe((i=>{if(i.deviceIdx!==h)return;if(143===i.subId&&130===i.params[0]&&i.params[1]===u)return n(),void s(new v(`Bolt pair rejected: HID++ error 0x${i.params[2]?.toString(16)}`,i.params[2]));if(84!==i.subId)return;const r=function(e){return{status:e[0],errorCode:e[1],bluetoothAddress:[e[2],e[3],e[4],e[5],e[6],e[7]],slot:e[8]}}(i.params);r.status!==w&&(n(),r.errorCode===b?t({index:r.slot,name:e.name,wpid:e.productId.toString(16).padStart(4,"0")}):s(new v(`Bolt pair failed: status=${r.status} err=${r.errorCode}`,r.errorCode)))}));i.push(n)}));try{return console.log("[Bolt] pair request",{bdAddr:e.bluetoothAddress.map((e=>e.toString(16).padStart(2,"0"))).join(":"),authMethod:s,timeoutSec:n}),await this.transport.device.sendReport(17,p),console.log("[Bolt] pair report sent, waiting for 0x54 status"),await this.withTimeout(g,6e4,"Bolt pair status timeout")}finally{i.forEach((e=>e()))}}async listPaired(){await this.open();const e=[];for(let i=1;i<=6;i++)try{const t=await this.readBoltDeviceName(i);if(!t)continue;e.push({index:i,name:t,wpid:""})}catch(t){if(t instanceof v)continue;throw t}return e}async unpair(e){await this.open();const t=k(h,130,[u,f,255&e,0,0,0,0,0,0,0,0,0,0,0,0,0,0],!0);await this.transport.device.sendReport(17,t)}async readBoltDeviceName(e){const t=96+e;let i=0;const s=[];let n=1;for(;n<=4;){const e=await this.transport.registerRequest(h,131,181,[t,n]);if(1===n){if(i=e.params[3]??0,0===i)return"";s.push(e.params.subarray(4))}else s.push(e.params.subarray(3));if(s.reduce(((e,t)=>e+t.length),0)>=i)break;n++}const r=new Uint8Array(i);let a=0;for(const o of s){const e=Math.min(o.length,i-a);if(r.set(o.subarray(0,e),a),a+=e,a>=i)break}return new TextDecoder("utf-8",{fatal:!1}).decode(r).replace(/\0+$/,"").trim()}withTimeout(e,t,i){return new Promise(((s,n)=>{const r=setTimeout((()=>n(new S(i))),t);e.then((e=>{clearTimeout(r),s(e)}),(e=>{clearTimeout(r),n(e)}))}))}}const L=1133,B=new Set([50475,50482]),E=new Set([50504]),I=new Set([50489,50490,50495,50503]);function P(e){switch(function(e){return e.vendorId!==L?null:E.has(e.productId)?"bolt":B.has(e.productId)?"unifying":I.has(e.productId)?"lightspeed":null}(e)){case"bolt":return new N(e);case"unifying":return new M(e);case"lightspeed":return new T(e);default:return null}}function C({adapter:e}
1){const[t,i]=(0,s.useState)(null),[r,a]=(0,s.useState)(null),[d,c]=(0,s.useState)(!1),h=(0,s.useCallback)((async()=>{c(!0),a(null);try{await e.open(),i(await e.listPaired())}catch(t){console.error("[PairingWidget] listPaired failed",{kind:e.kind,error:t}),a((0,n.T)({id:"pairWidget.list.readError",message:"Could not read paired devices: {reason}",description:"Error message when listPaired fails"},{reason:t instanceof Error?t.message:String(t)}))}finally{c(!1)}}),[e]);(0,s.useEffect)((()=>{h()}),[h]);const p=(0,s.useCallback)((async t=>{const i=t.name||(0,n.T)({id:"pairWidget.list.slotLabel",message:"slot {n}"},{n:t.index}),s=(0,n.T)({id:"pairWidget.list.unpairConfirm",message:"Unpair {label}? It will stop working until you pair it again.",description:"Confirm dialog before unpairing a device"},{label:i});if(window.confirm(s)){c(!0);try{await e.unpair(t.index),await h()}catch(r){console.error("[PairingWidget] unpair failed",{kind:e.kind,slot:t.index,error:r}),a((0,n.T)({id:"pairWidget.list.unpairError",message:"Unpair failed: {reason}",description:"Error message when unpair fails"},{reason:r instanceof Error?r.message:String(r)})),c(!1)}}}),[e,h]);return r?(0,l.jsx)("p",{className:o.error,children:r}):null===t?(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.list.loading",description:"Loading state while reading paired devices",children:"Reading paired devices\u2026"})}):0===t.length?(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.list.empty",description:"Empty paired-devices state",children:"No devices paired to this receiver \u2014 all six slots are free."})}):(0,l.jsxs)("table",{className:o.pairedTable,children:[(0,l.jsx)("thead",{children:(0,l.jsxs)("tr",{children:[(0,l.jsx)("th",{children:(0,l.jsx)(n.A,{id:"pairWidget.list.header.slot",description:"Table header for slot column",children:"Slot"})}),(0,l.jsx)("th",{children:(0,l.jsx)(n.A,{id:"pairWidget.list.header.device",description:"Table header for device column",children:"Device"})}),(0,l.jsx)("th",{"aria-label":"actions"})]})}),(0,l.jsx)("tbody",{children:t.map((e=>(0,l.jsxs)("tr",{children:[(0,l.jsx)("td",{children:e.index}),(0,l.jsxs)("td",{children:[e.name||(0,l.jsx)("em",{children:(0,l.jsx)(n.A,{id:"pairWidget.list.unknownDevice",description:"Fallback name for unknown device",children:"unknown device"})}),e.wpid&&(0,l.jsxs)("span",{className:o.hint,children:[" (",e.wpid,")"]})]}),(0,l.jsx)("td",{children:(0,l.jsx)("button",{type:"button",className:o.linkBtn,disabled:d,onClick:()=>p(e),children:(0,l.jsx)(n.A,{id:"pairWidget.btn.unpair",description:"Unpair a paired device",children:"Unpair"})})})]},e.index)))})]})}const W=3e4,D="__pairing_widget_user_cancel__";function X({receiverHint:e}){const[t,i]=(0,s.useState)({s:"idle"}
1),[r,d]=(0,s.useState)(null),[c,h]=(0,s.useState)(!1),p=(0,s.useRef)(null);(0,s.useEffect)((()=>()=>{p.current&&clearInterval(p.current),r?.close().catch((()=>{}))}),[r]),(0,s.useEffect)((()=>{if(r)return;let e=!1;return navigator.hid.getDevices().then((t=>{if(!e)for(const e of t){const t=P(e);if(t)return void d(t)}})).catch((()=>{})),()=>{e=!0}}),[r]);const u=(0,s.useCallback)((async()=>{const e=await navigator.hid.requestDevice({filters:[{vendorId:L,usagePage:65280},{vendorId:L,usagePage:65347}]});if(0===e.length)return null;for(const t of e){const e=P(t);if(e)return e}return i({s:"unsupported"}),null}),[]),g=(0,s.useCallback)((()=>({onDiscovered:e=>new Promise(((t,s)=>{i({s:"picking",picker:{devices:e,resolve:t,cancel:()=>s(new Error(D))}})})),onPasskey:({digits:e,authMethod:t,clickSequence:s})=>{i({s:"passkey",digits:e,authMethod:t,clickSequence:s,entered:0})},onPasskeyProgress:({keyCode:e})=>{i((t=>"passkey"!==t.s?t:e===j.DIGIT_ENTERED?{...t,entered:t.entered+1}:e===j.DIGIT_ERASED?{...t,entered:Math.max(0,t.entered-1)}:e===j.CLEARED?{...t,entered:0}:e===j.ENTRY_COMPLETED?{...t,finalizing:!0}:t))}})),[]),m=(0,s.useCallback)((async()=>{let t=r;try{const e=t??await u();if(!e)return;t=e,d(e),await e.open();let s=W/1e3;i({s:"pairing",secondsLeft:s}),p.current=setInterval((()=>{s-=1,i((e=>"pairing"!==e.s?(p.current&&(clearInterval(p.current),p.current=null),e):s<=0?(p.current&&(clearInterval(p.current),p.current=null),{s:"pairing",secondsLeft:0}):{s:"pairing",secondsLeft:s}))}),1e3);const n=await e.startPairing(W,g());i({s:"success",device:n}),h(!0)}catch(s){if(s instanceof Error&&s.message===D)return void i({s:"idle"});const r=t?.kind??"unknown";console.error("[PairingWidget] pair failed",{kind:r,receiverHint:e,error:s}),i({s:"error",message:s instanceof S?(0,n.T)({id:"pairWidget.error.timeout",message:"No device showed up. Turn the mouse off and on (or press its connect button), then try again.",description:"Pair error: timeout waiting for device"}):(0,n.T)({id:"pairWidget.error.generic",message:"Pairing failed [{kind}]: {reason}",description:"Pair error: generic failure with adapter kind and reason"},{kind:r,reason:s instanceof Error?s.message:String(s)})})}finally{p.current&&(clearInterval(p.current),p.current=null)}}),[r,u,g,e]);return(0,l.jsxs)("div",{children:[e&&"idle"===t.s&&(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.hint.receiverHint",description:"Hint shown on model pages telling which receiver ships with this device",values:{hint:(0,l.jsx)("strong",{children:e})},children:"This model usually ships with a {hint} receiver \u2014 plug it in, then click below."})}),"idle"===t.s&&(0,l.jsxs)("div",{className:o.fallbackActions,children:[(0,l.jsx)("button",{type:"button",className:o.primaryBtn,onClick:m,children:(0,l.jsx)(n.A,{id:"pairWidget.btn.pairNew",description:"Primary button: start pairing a new device",children:"Pair a new device"})}),(0,l.jsx)("button",{type:"button",className:o.secondaryBtn,onClick:()=>h((e=>!e)),children:c?(0,l.jsx)(n.A,{id:"pairWidget.btn.hidePaired",description:"Secondary button when list is open",children:"Hide paired devices"}):(0,l.jsx)(n.A,{id:"pairWidget.btn.seePaired",description:"Secondary button when list is closed",children:"See paired devices"})})]}),"unsupported"===t.s&&(0,l.jsxs)("p",{className:o.error,children:[(0,l.jsx)(n.A,{id:"pairWidget.unsupported",description:"Shown when the picked HID device isn't a supported Logitech receiver",children:"That device isn\u2019t a supported receiver (Bolt / Unifying / Lightspeed). Pick the small USB receiver, not the mouse itself."})," ",(0,l.jsx)("button",{type:"button",className:o.linkBtn,onClick:()=>i({s:"idle"}),children:(0,l.jsx)(n.A,{id:"pairWidget.btn.tryAgain",description:"Button to reset and try again",children:"Try again"})})]}),"pairing"===t.s&&(0,l.jsxs)("div",{className:o.pairingBox,children:[(0,l.jsx)("p",{className:o.pairingTitle,children:"bolt"===r?.kind?(0,l.jsx)(n.A,{id:"pairWidget.pairing.title.bolt",description:"Instruction for Bolt receivers: put device in pairing mode",children:"Put your device in pairing mode (press & hold its pair / Easy-Switch button)\u2026"}):(0,l.jsx)(n.A,{id:"pairWidget.pairing.title.unifying",description:"Instruction for Unifying/Lightspeed: wake device",children:"Now turn on your device, or press its connect / Easy-Switch button\u2026"})}),(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.pairing.listening",description:"Countdown while waiting for device",values:{n:t.secondsLeft},children:"Listening for {n}s"})})]}),"picking"===t.s&&(0,l.jsxs)("div",{className:o.pairingBox,children:[(0,l.jsx)("p",{className:o.pairingTitle,children:(0,l.jsx)(n.A,{id:"pairWidget.picker.title",description:"Title when multiple Bolt devices are discovered and user must pick one",children:"Multiple devices found \u2014 pick one:"})}),(0,l.jsx)("ul",{className:o.pickerList,children:t.picker.devices.map((e=>{const i=e.bluetoothAddress.map((e=>e.toString(16).padStart(2,"0"))).join(":"),s=e.authMethod===y.PASSKEY?(0,n.T)({id:"pairWidget.picker.kind.keyboard",message:"keyboard"}):(0,n.T)({id:"pairWidget.picker.kind.mouse",message:"mouse"}),r=(0,n.T)({id:"pairWidget.picker.unknown",message:"Unknown device ({addr})"},{addr:i});return(0,l.jsx)("li",{children:(0,l.jsxs)("button",{type:"button",className:o.linkBtn,onClick:()=>t.picker.resolve(e),children:[e.name||r,(0,l.jsxs)("span",{className:o.hint,children:[" (",s,")"]})]})},i)}))}),(0,l.jsx)("button",{type:"button",className:o.linkBtn,onClick:()=>t.picker.cancel(),children:(0,l.jsx)(n.A,{id:"pairWidget.btn.cancel",description:"Cancel button in the picker",children:"Cancel"})})]}),"passkey"===t.s&&t.authMethod===y.PASSKEY&&(0,l.jsxs)("div",{className:o.pairingBox,children:[(0,l.jsx)("p",{className:o.pairingTitle,children:t.finalizing?(0,l.jsx)(n.A,{id:"pairWidget.passkey.confirming",description:"Shown briefly before pair success",children:"Confirming pairing\u2026"}):(0,l.jsx)(n.A,{id:"pairWidget.passkey.keyboard.title",description:"Ask user to type passkey on keyboard",values:{digits:(0,l.jsx)("strong",{children:t.digits})},children:"On the keyboard, type {digits} and press Enter"})}),!t.finalizing&&(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.passkey.keyboard.progress",description:"Progress counter for keyboard passkey",values:{entered:t.entered,total:t.digits.length},children:"{entered} / {total} digits entered"})})]}),"passkey"===t.s&&t.authMethod===y.PASSKEY_EMULATION_2_BUTTON&&t.clickSequence&&(0,l.jsxs)("div",{className:o.pairingBox,children:[(0,l.jsx)("p",{className:o.pairingTitle,children:t.finalizing?(0,l.jsx)(n.A,{id:"pairWidget.passkey.confirming2",description:"Shown briefly before pair success (mouse)",children:"Confirming pairing\u2026"}):t.entered<t.clickSequence.length?(0,l.jsx)(n.A,{id:"pairWidget.passkey.mouse.title",description:"Ask user to click mouse in L/R sequence",children:"Click your mouse in this sequence:"}):(0,l.jsx)(n.A,{id:"pairWidget.passkey.mouse.finalTitle",description:"Ask user to press both buttons for final confirmation",children:"Now press LEFT + RIGHT buttons at the same time"})}),!t.finalizing&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("p",{className:o.clickSequence,children:t.entered<t.clickSequence.length?t.clickSequence.split("").map(((e,i)=>(0,l.jsx)("span",{className:i<t.entered?o.clickDone:o.clickPending,children:e},i))):(0,l.jsx)("span",{className:o.clickPending,children:"L + R"})}),(0,l.jsx)("p",{className:o.hint,children:t.entered<t.clickSequence.length?(0,l.jsx)(n.A,{id:"pairWidget.passkey.mouse.progress",description:"Progress counter for mouse click sequence with L/R legend",values:{entered:t.entered,total:t.clickSequence.length,L:(0,l.jsx)("strong",{children:"L"}),R:(0,l.jsx)("strong",{children:"R"})},children:"{entered} / {total} clicks \u2014 {L} = left, {R} = right"}):(0,l.jsx)(n.A,{id:"pairWidget.passkey.mouse.finalHint",description:"Hint for pressing both mouse buttons",values:{both:(0,l.jsx)("strong",{children:(0,l.jsx)(n.A,{id:"pairWidget.passkey.mouse.finalHint.both",description:"Emphasized word: both",children:"both"})})},children:"Final step: press {both} buttons together to confirm"})})]})]}),"success"===t.s&&(0,l.jsxs)("div",{className:o.pairingBox,children:[(0,l.jsx)("p",{className:o.pairingTitle,children:(0,l.jsx)(n.A,{id:"pairWidget.success.title",description:"Success message showing paired device name or slot number",values:{name:(0,l.jsx)("strong",{children:t.device.name||(0,n.T)({id:"pairWidget.success.slotFallback",message:"device in slot {n}"},{n:t.device.index})})},children:"\u2713 Paired: {name}"})}),(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.success.installHint",description:"Post-pair CTA text with LinguaX download link",values:{dl:(0,l.jsx)(a.A,{to:"/download",children:(0,l.jsx)(n.A,{id:"pairWidget.success.installLink",description:"LinguaX download link text",children:"Download LinguaX for macOS"})})},children:"Now install LinguaX to remap its side buttons \u2014 {dl}"})}),(0,l.jsx)("button",{type:"button",className:o.linkBtn,onClick:()=>i({s:"idle"}),children:(0,l.jsx)(n.A,{id:"pairWidget.btn.pairAnother",description:"Button to start another pairing",children:"Pair another device"})})]}),"error"===t.s&&(0,l.jsxs)("p",{className:o.error,children:[t.message," ",(0,l.jsx)("button",{type:"button",className:o.linkBtn,onClick:()=>i({s:"idle"}),children:(0,l.jsx)(n.A,{id:"pairWidget.btn.tryAgain2",description:"Try again after error",children:"Try again"})})]}),c&&r&&(0,l.jsx)(C,{adapter:r}),c&&!r&&"idle"===t.s&&(0,l.jsx)("p",{className:o.hint,children:(0,l.jsx)(n.A,{id:"pairWidget.list.needConnect",description:"Shown when user asks to see paired devices but adapter isn't ready",children:"Connect a receiver first (click \u201cPair a new device\u201d and pick it) to see its paired devices."})})]})}function R({receiverHint:e,hideHeader:t}){return(0,l.jsx)(c,{children:(0,l.jsxs)("aside",{className:o.fallback,"aria-label":"Logitech receiver pairing",children:[!t&&(0,l.jsxs)("div",{className:o.fallbackHeader,children:[(0,l.jsx)("h3",{className:o.fallbackTitle,children:(0,l.jsx)(n.A,{id:"pairWidget.header.title",description:"PairingWidget default header title",children:"Pair your Logitech receiver \u2014 right here in the browser"})}),(0,l.jsx)("p",{className:o.fallbackDesc,children:(0,l.jsx)(n.A,{id:"pairWidget.header.desc",description:"PairingWidget default header description",children:"Works with Bolt, Unifying, and Lightspeed receivers. No Logitech software needed."})})]}),(0,l.jsx)(X,{receiverHint:e}),(0,l.jsx)("p",{className:o.disclaimer,children:(0,l.jsx)(n.A,{id:"pairWidget.disclaimer",description:"Logitech trademarks disclaimer",children:"Not affiliated with or endorsed by Logitech. \u201cLogitech\u201d, \u201cMX Master\u201d, \u201cBolt\u201d, \u201cUnifying\u201d, \u201cLightspeed\u201d are trademarks of Logitech International SA, used de
1scriptively for compatibility."})})]})})}},4360:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>p,contentTitle:()=>h,default:()=>m,frontMatter:()=>c,metadata:()=>s,toc:()=>u});const s=JSON.parse('{"id":"mouse-plus/models/mx-anywhere-3s","title":"MX Anywhere 3S on Mac: Button Mapping","description":"The MX Anywhere 3S has four mappable inputs \u2014 LinguaX unlocks side-button push-to-talk, Space switching, and per-app overrides on macOS without Options+.","source":"@site/docs/mouse-plus/models/mx-anywhere-3s.md","sourceDirName":"mouse-plus/models","slug":"/mouse-plus/models/mx-anywhere-3s","permalink":"/docs/mouse-plus/models/mx-anywhere-3s","draft":false,"unlisted":false,"editUrl":"https://github.com/xiaopozhu/linguax-web/tree/master/docs/mouse-plus/models/mx-anywhere-3s.md","tags":[],"version":"current","frontMatter":{"id":"mx-anywhere-3s","title":"MX Anywhere 3S on Mac: Button Mapping","description":"The MX Anywhere 3S has four mappable inputs \u2014 LinguaX unlocks side-button push-to-talk, Space switching, and per-app overrides on macOS without Options+.","sidebar_label":"MX Anywhere 3S","keywords":["mx anywhere 3s mac","mx anywhere 3s mac setup","mx anywhere 3s button mapping mac","mx anywhere 3s side buttons mac","mx anywhere 3s travel mac","portable mouse mac"]},"sidebar":"tutorialSidebar","previous":{"title":"MX Master 3","permalink":"/docs/mouse-plus/models/mx-master-3"},"next":{"title":"MX Anywhere 3","permalink":"/docs/mouse-plus/models/mx-anywhere-3"}}');var n=i(4848),r=i(8453),a=i(2406),o=i(5260),l=i(1122),d=i(6025);const c={id:"mx-anywhere-3s",title:"MX Anywhere 3S on Mac: Button Mapping",description:"The MX Anywhere 3S has four mappable inputs \u2014 LinguaX unlocks side-button push-to-talk, Space switching, and per-app overrides on macOS without Options+.",sidebar_label:"MX Anywhere 3S",keywords:["mx anywhere 3s mac","mx anywhere 3s mac setup","mx anywhere 3s button mapping mac","mx anywhere 3s side buttons mac","mx anywhere 3s travel mac","portable mouse mac"]},h="MX Anywhere 3S on Mac \u2014 Portable Mouse, Full Mapping",p={},u=[{value:"What you can actually map on the MX Anywhere 3S",id:"what-you-can-actually-map-on-the-mx-anywhere-3s",level:2},{value:"What Options+ can&#39;t do on the Anywhere 3S",id:"what-options-cant-do-on-the-anywhere-3s",level:2},{value:"Three ready-to-copy setups for a portable mouse",id:"three-ready-to-copy-setups-for-a-portable-mouse",level:2},{value:"1. Push-to-talk on S2",id:"1-push-to-talk-on-s2",level:3},{value:"2. Space switching with S1 swipe",id:"2-space-switching-with-s1-swipe",level:3},{value:"3. App-scoped side-button behaviour",id:"3-app-scoped-side-button-behaviour",level:3},{value:"Setup in three minutes",id:"setup-in-three-minutes",level:2},{value:"MX Anywhere 3S vs the MX Master line",id:"mx-anywhere-3s-vs-the-mx-master-line",level:2},{value:"Compatibility notes",id:"compatibility-notes",level:2},{value:"FAQ",id:"faq",level:2},{value:"Get started",id:"get-started",level:2},{value:"Related pages",id:"related-pages",level:2}];function g(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(o.A,{children:(0,n.jsx)("script",{type:"application/ld+json",children:JSON.stringify({"@context":"https://schema.org","@type":"FAQPage",mainEntity:[{"@type":"Question",name:"Does the MX Anywhere 3S have a Thumb button?",acceptedAnswer:{"@type":"Answer",text:"No. The MX Anywhere line is designed for portability and drops the Thumb button that MX Master models have. On the Anywhere 3S you have the two side buttons (S1 / S2), the wheel click (M), and the Scroll Mode toggle (SM). LinguaX lets each of those carry multiple gestures."}},{"@type":"Question",name:"Can I still do push-to-talk on the MX Anywhere 3S?",acceptedAnswer:{"@type":"Answer",text:"Yes \u2014 bind long-press to one of the side buttons (S2 works well since it defaults to Forward, less-used than Back). The 200 ms long-press threshold turns any side button into a physical PTT switch."}},{"@type":"Question",name:"Bluetooth or Bolt receiver for a portable mouse?",acceptedA
1nswer:{"@type":"Answer",text:"Bluetooth is usually the right call for travel \u2014 no dongle to lose. If you dock at a permanent desk with a receiver, keep the Bolt there and Bluetooth for the road; the Easy-Switch button toggles between paired hosts."}}]})})}),"\n",(0,n.jsx)(t.header,{children:(0,n.jsx)(t.h1,{id:"mx-anywhere-3s-on-mac--portable-mouse-full-mapping",children:"MX Anywhere 3S on Mac \u2014 Portable Mouse, Full Mapping"})}),"\n",(0,n.jsx)(t.p,{children:"The MX Anywhere 3S is the travel-sized cousin of the MX Master 3S \u2014 no Thumb button, no Wheel Tilt sensors, but the four inputs it does have get every LinguaX gesture type. Push-to-talk on a side button, Space switching by swipe, per-app input-source switching \u2014 all fit on a mouse you can slip in a laptop bag."}),"\n",(0,n.jsx)(a.A,{receiverHint:"bolt"}),"\n",(0,n.jsx)(l.A,{alt:"MX Anywhere 3S \u2014 LinguaX button slot layout showing 4 configurable slots (S1, S2, M, SM); no thumb button, no thumb wheel",sources:{light:(0,d.Ay)("/img/models/mx-anywhere-slots.svg"),dark:(0,d.Ay)("/img/models/mx-anywhere-slots-dark.svg")},width:"640"}),"\n",(0,n.jsx)(t.h2,{id:"what-you-can-actually-map-on-the-mx-anywhere-3s",children:"What you can actually map on the MX Anywhere 3S"}),"\n",(0,n.jsx)(t.p,{children:"LinguaX exposes four configurable inputs on the Anywhere 3S, plus Left / Right which macOS handles directly:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsxs)(t.strong,{children:[(0,n.jsx)(t.code,{children:"S1"})," / ",(0,n.jsx)(t.code,{children:"S2"})," (side buttons)"]})," \u2014 the two thumb-side buttons (default Back / Forward). Full four-gesture layer: click / double-click / long-press / directional swipe."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsxs)(t.strong,{children:[(0,n.jsx)(t.code,{children:"M"})," (wheel click)"]})," \u2014 the middle button."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsxs)(t.strong,{children:[(0,n.jsx)(t.code,{children:"SM"})," (Scroll Mode)"]})," \u2014 the small button behind the wheel that toggles MagSpeed between ratchet and free-spin. LinguaX lets SM carry a second action while still toggling wheel mode."]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["The Anywhere 3S has ",(0,n.jsx)(t.strong,{children:"no dedicated Thumb button"})," (that is exclusive to the MX Master line), and ",(0,n.jsx)(t.strong,{children:"no Wheel Tilt"})," \u2014 the wheel presses down for a middle-click but does not tilt sideways."]}),"\n",(0,n.jsxs)(t.p,{children:["Named-slot vocabulary reference: ",(0,n.jsx)(t.a,{href:"/docs/mouse-plus/fundamentals/button-mapping",children:"Button & Side-Button Mapping"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"what-options-cant-do-on-the-anywhere-3s",children:"What Options+ can't do on the Anywhere 3S"}),"\n",(0,n.jsx)(t.p,{children:"Even with fewer buttons than a MX Master, LinguaX still gives you what Options+ leaves on the table:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Push-to-talk"})," on a side button \u2014 long-press with a 200 ms threshold as a physical PTT switch."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Four-direction swipe"})," on the side buttons \u2014 Options+ fires on press; LinguaX distinguishes swipe-left / -right / -up / -down as four independent actions."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Per-app overrides"})," by bundle ID \u2014 same side button, different action per app. See ",(0,n.jsx)(t.a,{href:"/docs/mouse-plus/fundamentals/app-scoped-overrides",children:"App-Scoped Overrides"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Modifier-hold"}),' \u2014 treat a side button as "held Cmd" while pressed.']}),"\n",(0,n.jsx)(t.li,{children:(0,n.jsx)(t.strong,{children:"No account, no cloud sync, ~10 MB native."})}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Broader writeup: ",(0,n.jsx)(t.a,{href:"/docs/comparisons/logi-options-plus-alternative-macos",children:"Logi Options+ Alternative for macOS"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"three-ready-to-copy-setups-for-a-portable-mouse",children:"Three ready-to-copy setups for a portable mouse"}),"\n",(0,n.jsx)(t.h3,{id:"1-push-to-talk-on-s2",children:"1. Push-to-talk on S2"}),"\n",(0,n.jsxs)(t.p,{children:["Since the Anywhere line has no Thumb button, use ",(0,n.jsx)(t.code,{children:"S2"})," (Forward) for PTT \u2014 Forward is less muscle-critical than Back for most browsing habits:"]}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"S2 long-press"})," (200 ms) \u2192 ",(0,n.jsx)(t.strong,{children:"Hold"})," the shortcut your voice tool uses (Superwhisper ",(0,n.jsx)(t.code,{children:"Fn"}),", Wispr Flow ",(0,n.jsx)(t.code,{children:"\u2325"}),", Zoom ",(0,n.jsx)(t.code,{children:"Space"}),")"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"S2 click"})," \u2192 keep Forward for browsing (short click still fires the default)"]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Details: ",(0,n.jsx)(t.a,{href:"/docs/push-to-talk/push-to-talk-voice-typing-mac",children:"Push-to-Talk Voice Typing on macOS with a Mouse Button"}),"."]}),"\n",(0,n.jsx)(t.h3,{id:"2-space-switching-with-s1-swipe",children:"2. Space switching with S1 swipe"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"S1 swipe-left"}
1)," \u2192 ",(0,n.jsx)(t.code,{children:"\u2303 \u2190"})," (Space left)"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"S1 swipe-right"})," \u2192 ",(0,n.jsx)(t.code,{children:"\u2303 \u2192"})," (Space right)"]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.code,{children:"S1 click"})," \u2192 keeps default Back action"]}),"\n"]}),"\n",(0,n.jsx)(t.p,{children:"Two or more Spaces reachable with a thumb flick, no reach to the trackpad or keyboard."}),"\n",(0,n.jsx)(t.h3,{id:"3-app-scoped-side-button-behaviour",children:"3. App-scoped side-button behaviour"}),"\n",(0,n.jsx)(t.p,{children:"Same button, different action depending on the frontmost app:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:["Global: ",(0,n.jsx)(t.code,{children:"S2 click"})," \u2192 Forward"]}),"\n",(0,n.jsxs)(t.li,{children:["In Zoom: ",(0,n.jsx)(t.code,{children:"S2 click"})," \u2192 Mute toggle"]}),"\n",(0,n.jsxs)(t.li,{children:["In your browser: ",(0,n.jsx)(t.code,{children:"S2 double-click"})," \u2192 Reopen closed tab (",(0,n.jsx)(t.code,{children:"\u2318 \u21e7 T"}),")"]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["Configuration reference: ",(0,n.jsx)(t.a,{href:"/docs/mouse-plus/fundamentals/app-scoped-overrides",children:"App-Scoped Overrides"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"setup-in-three-minutes",children:"Setup in three minutes"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Install LinguaX"})," from ",(0,n.jsx)(t.a,{href:"/docs/getting-started/installation",children:"Installation"}),"."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Pair the mouse."})," For travel, Bluetooth is usually better \u2014 no dongle to lose. Pair via macOS System Settings; the Anywhere 3S supports three Easy-Switch slots so you can also pair a Bolt receiver at a permanent desk."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Open Mouse+."})," LinguaX recognises the Anywhere 3S via VID",":PID"," and shows the S1 / S2 / M / SM slots."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Apply a recipe."})," Start with push-to-talk on S2 \u2014 it is the biggest productivity win a portable mouse can offer."]}),"\n"]}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.a,{href:"/docs/getting-started/first-run",children:"First Run"})," guide covers accessibility-permission prompts on macOS."]}),"\n",(0,n.jsx)(t.h2,{id:"mx-anywhere-3s-vs-the-mx-master-line",children:"MX Anywhere 3S vs the MX Master line"}),"\n",(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{}),(0,n.jsx)(t.th,{children:"MX Anywhere 3S"}),(0,n.jsx)(t.th,{children:"MX Master 3S"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Weight"}),(0,n.jsx)(t.td,{children:"Lighter, pocketable"}),(0,n.jsx)(t.td,{children:"Full-size desktop"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Configurable slots"}),(0,n.jsx)(t.td,{children:"4 (S1, S2, M, SM)"}),(0,n.jsx)(t.td,{children:"7 (S1, S2, M, T, SM, WL, WR)"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Thumb button"}),(0,n.jsx)(t.td,{children:"No"}),(0,n.jsxs)(t.td,{children:["Yes (",(0,n.jsx)(t.code,{children:"T"}),")"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Wheel Tilt"}),(0,n.jsx)(t.td,{children:"No"}),(0,n.jsxs)(t.td,{children:["Yes (",(0,n.jsx)(t.code,{children:"WL"})," / ",(0,n.jsx)(t.code,{children:"WR"}),")"]})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Portability"}),(0,n.jsx)(t.td,{children:"High"}),(0,n.jsx)(t.td,{children:"Desk-only"})]})]})]}),"\n",(0,n.jsx)(t.p,{children:"If your workflow is mostly stationary, the MX Master 3S gives you three extra mappable inputs. If you carry a laptop bag, the Anywhere 3S trades those slots for portability \u2014 the four it has still cover push-to-talk, Spaces, and per-app overrides."}),"\n",(0,n.jsx)(t.h2,{id:"compatibility-notes",children:"Compatibility notes"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"HID++ 2.0"})," \u2014 recognised natively with full profile support."]}
1),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Battery"})," \u2014 shown in the tray for both Bluetooth and Bolt connections."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Sleep / wake"})," \u2014 auto-recovers."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Three Easy-Switch hosts"})," \u2014 LinguaX keeps a separate profile per host."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"faq",children:"FAQ"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Does the MX Anywhere 3S have a Thumb button?"}),"\nNo \u2014 the Anywhere line drops the Thumb button that MX Master models have. Four configurable inputs: S1, S2, M, SM."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Can I still do push-to-talk on the Anywhere 3S?"}),"\nYes \u2014 bind long-press to S2 (Forward, less-used than Back). Same 200 ms threshold as the Master line."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Bluetooth or Bolt receiver for a portable mouse?"}),"\nBluetooth for travel (no dongle to lose), Bolt for a permanent desk. The Easy-Switch button toggles paired hosts."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:"Does LinguaX show battery for the Anywhere 3S?"}),"\nYes, via HID++ over Bluetooth or via the Bolt receiver."]}),"\n",(0,n.jsx)(t.h2,{id:"get-started",children:"Get started"}),"\n",(0,n.jsxs)(t.p,{children:["LinguaX is a free download with a ",(0,n.jsx)(t.strong,{children:"30-day trial"})," \u2014 no account, no telemetry. If it fits, it is a ",(0,n.jsx)(t.strong,{children:"$9.9 one-time purchase covering 3 devices"})," (no subscription)."]}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.strong,{children:(0,n.jsx)(t.a,{href:"/download",children:"Download LinguaX"})})," and set up your MX Anywhere 3S free for 30 days."]}),"\n",(0,n.jsx)(t.h2,{id:"related-pages",children:"Related pages"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.a,{href:"./mx-anywhere-3",children:"MX Anywhere 3"})," \u2014 the previous-generation model; same slot layout."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.a,{href:"./mx-master-3s",children:"MX Master 3S"})," \u2014 the larger desktop-first sibling with T, SM, WL, WR."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.a,{href:"./mx-master-3",children:"MX Master 3"})," \u2014 desktop, older generation, same seven-slot mapping surface."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.a,{href:"/docs/mouse-plus/recipes/map-mouse-side-buttons-macos",children:"How to Map Mouse Side Buttons on macOS"})," \u2014 brand-agnostic side-button walkthrough; every gesture pattern shown there applies to Anywhere 3S's S1 and S2."]}),"\n",(0,n.jsxs)(t.li,{children:["All models: ",(0,n.jsx)(t.a,{href:"/docs/mouse-plus/device-compatibility",children:"Compatible Mouse Models overview"}),"."]}),"\n"]})]})}function m(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(g,{...e})}):g(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>o});var s=i(6540);const n={},r=s.createContext(n);function a(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:a(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.