Anda Tidak Bisa Menyembunyikan Jendela dari Zoom di macOS 15
Pada macOS modern, Anda tidak dapat secara andal menyembunyikan jendela dari penangkapan layar — baik dari aplikasi lain maupun dari aplikasi Anda sendiri. Ini adalah cerita teknis tentang penghapusan CGSSetWindowCaptureExcluded, pengabaian SLSSetWindowSharingState secara diam-diam antar proses, serta alasan mengapa NSWindow.sharingType = .none merupakan saran lemah bagi Zoom dan QuickTime, bukan jaminan keras.
Sebuah refleksi singkat tentang pengembangan aplikasi 'window pribadi' yang tidak berjalan dengan sempurna.
Ide
Seperti banyak orang, saya bekerja dengan jendela desktop Claude terbuka selama pertemuan. Dan seperti banyak orang, saya kadang membagikan layar saya di Zoom, dan saya lebih suka jendela tersebut tidak terlihat oleh semua orang dalam pertemuan. Bukan karena ada sesuatu yang sensitif — hanya karena itu adalah keadaan kerja pribadi.
Saya tahu aplikasi seperti 1Password dan Hand Mirror dapat menyembunyikan jendela mereka dari penangkapan layar. Saya berpikir saya bisa membuat alat utilitas baris menu yang memungkinkan saya memilih apa pun aplikasi — Claude, Catatan, atau apa saja — dan mengubah keberadaan jendela tersebut tidak terlihat saat ditangkap, sambil tetap mempertahankan jendela tersebut penuh visibilitas dan interaktif di layar saya sendiri.
Proyek akhir pekan. Maksimal dua jam.
Ini memakan waktu lebih lama. Dan inti dari hal ini adalah: pada macOS modern, Anda tidak bisa melakukannya. Tidak untuk aplikasi lain, dan — ternyata — tidak dapat diandalkan bahkan untuk aplikasi Anda sendiri.
Ini adalah cerita teknis mengapa.
Upaya 1: menyembunyikan jendela aplikasi lain
Cara klasik untuk membuat jendela macOS tidak terlihat dalam penangkapan layar adalah NSWindow.sharingType = .none. Namun, ini adalah flag per-jendela yang hanya dapat diatur oleh proses pemilik pada jendela-jendela miliknya sendiri. AppKit tidak memungkinkan Anda mengakses daftar jendela aplikasi lain.
Solusi yang terkenal, yang digunakan selama bertahun-tahun oleh alat seperti Hand Mirror dan berbagai utilitas penutup layar, adalah fungsi SkyLight privat:
OSStatus CGSSetWindowCaptureExcluded(CGSConnectionID cid, CGWindowID wid, bool excluded);
Anda mengenumerasi jendela melalui CGWindowListCopyWindowInfo, menyaring ke PID aplikasi target, dan memanggil ini pada setiap ID jendela. Karena panggilan ini melalui WindowServer (bukan proses pemilik), maka jendela dapat dikecualikan dari penangkapan.
Saya menyambungkan ini melalui dlsym dalam /System/Library/PrivateFrameworks/SkyLight.framework/..., membangunnya, menjalankannya di macOS 15.3.1, dan mendapatkan:
[InvisibleApp] symbol not found: CGSSetWindowCaptureExcluded
[InvisibleApp] symbol not found: SLSSetWindowCaptureExcluded
Fungsi ini hilang. Apple menghapusnya. Saya mencari versi yang diubah (SLSSetWindowExcludedFromCapture, CGSSetWindowSharingState, semua variasi yang jelas). Sebagian besar tidak ada, tetapi saya menemukan dua yang ada:
SLSSetWindowSharingState(CGSConnectionID, CGWindowID, int sharingState)— panggilan bawah dasar yangNSWindow.sharingType = .nonemenggunakan secara internal. Berbagi status0adalahNSWindowSharingNone.SLSGetWindowOwner— memberi Anda ID koneksi dari proses pemilik jendela.
Jadi saya membangun kembali jembatan untuk memanggil SLSSetWindowSharingState pada jendela target, mencoba koneksi utama saya dan koneksi pemilik jendela.
Membangun, menjalankan, mengaktifkan, log menyatakan bahwa itu mengembalikan noErr, mengambil screenshot — Claude masih muncul di screenshot. Mencoba Zoom — Claude masih muncul dalam bagian berbagi.
SLSSetWindowSharingState berhasil saat dipanggil lintas proses tetapi WindowServer mengabaikannya secara diam-diam. Hanya proses pemilik yang dapat mengubah status jendela miliknya sendiri pada macOS 15.
Saya juga memverifikasi bahwa jalan keluar yang jelas telah ditutup: DYLD_INSERT_LIBRARIES injeksi ke dalam proses Claude dilarang karena Claude (seperti kebanyakan aplikasi modern) memiliki runtime yang diperkuat dan tanpa disable-library-validation entitlement.
Jadi itu telah ditentukan: tidak ada aplikasi pihak ketiga yang dapat membuat jendela aplikasi lain tidak terlihat dalam penangkapan pada macOS 15. Kesimpulan ini sesuai dengan apa yang dikatakan Apple: status penangkapan per-jendela adalah hak eksklusif aplikasi pemilik, tanpa pengecualian.
Upaya 2: menyembunyikan jendela kita sendiri
Rencana B: mengubah produk. Alih-alih alat yang menyembunyikan Claude, buat jendela obrolan kecil milik saya sendiri — tugas yang sama, bentuk yang berbeda. Jendela milik saya, saya sendiri. sharingType = .noneIni adalah mekanisme yang sudah terkenal digunakan oleh setiap alat yang menyembunyikan penangkapan layar, dan itu hanya satu baris kode:
window.sharingType = .none
Hubungkan aliran obrolan ke API Anthropic Messages (atau ke CLI lokal claude untuk autentikasi berlangganan), atur sharingType = .none pada jendela obrolan, distribusikan. Ini adalah API yang jelas, didukung, dan publik.
Saya membangunnya. Saya mencatat nilai tipe penangkapan secara real-time untuk memastikan macOS menerima itu:
[InvisibleApp] window 151526 sharingType=0
Mengambil screenshot — jendela obrolan benar-benar tidak muncul. ✅
Mengambil layar dengan QuickTime — jendela obrolan muncul dalam rekaman. ❌
Membagikan layar di Zoom — jendela obrolan terlihat bagi pihak lain. ❌
Ini tidak terduga. Seluruh titik dari NSWindowSharingNone adalah untuk mengeluarkannya dari alur-alur ini. Jadi saya membangun uji internal dalam aplikasi yang melakukan penangkapan layar menggunakan ScreenCaptureKit (API penangkapan modern, publik), yang sama dengan yang digunakan QuickTime di bawah kulit. Saya mencoba penangkapan tunggal (SCScreenshotManager.captureImage) dan penangkapan berkelanjutan (SCStream) — keduanya menghasilkan PNG dengan jendela obrolan yang benar-benar dikecualikan.
Jadi:
| Metode penangkapan | Menyembunyikan jendela kita? |
|---|---|
| Cmd-Shift-3/4/5 (screenshot sistem) | ✅ |
| Penangkapan tunggal oleh aplikasi kita menggunakan SCK | ✅ |
| Penangkapan berkelanjutan oleh aplikasi kita menggunakan SCK | ✅ |
| QuickTime “New Screen Recording” | ❌ |
| Zoom “Share Screen → Desktop” | ❌ |
Sama OS, sama mesin, sama jendela, sama sharingType = .none. Satu-satunya hal yang berbeda adalah siapa yang melakukan penangkapan.
Jalur penangkapan berhak istimewa
Ini adalah bagian yang tidak disadari oleh sebagian besar insinyur: pada macOS 15, penangkapan layar bukan satu API; itu setidaknya dua — satu publik, dan satu privat dengan entitas tambahan.
Saya mengunggah entitas QuickTime Player:
codesign -d --entitlements - /System/Applications/QuickTime\ Player.app
com.apple.private.screencapturekit.noprompt = true
com.apple.private.tcc.allow = [
kTCCServiceMicrophone,
kTCCServiceCamera,
kTCCServiceScreenCapture,
]
Kunci-kunci ini hanya dapat diberikan oleh Apple kepada biner pertama pihak mereka sendiri. Anda dan saya tidak bisa meminta mereka. Notifikasi akan ditolak. App Store tentu saja akan menolaknya. com.apple.private.* Dan apa yang mereka berikan, selain menghindari prompt izin penangkapan, adalah kemampuan untuk menangkap gambar layar
sebelum WindowServer menerapkan penyaringan tipe penangkapan . Jendela tersebut ada di framebuffer yang dihasilkan — alat-alat Apple hanya melihat semua itu.Zoom menggunakan jalur yang serupa. Mungkin itu adalah ekstensi kernel, ekstensi sistem, atau API privat yang diperoleh karena menjadi aplikasi konferensi yang telah diberi kepercayaan panjang — saya belum menyelidiki cukup untuk menyatakan mana. Namun perilakunya sama: mekanisme penyaringan umum tidak berlaku bagi itu.
Artinya
Jika Anda adalah pengembang pihak ketiga dan tujuan Anda adalah "jendela ini tidak boleh muncul dalam rekaman layar di setiap Mac",
Anda tidak dapat memastikan hal ini pada macOS 15. Jendela Anda tersembunyi dari semua jalur penangkapan yang Anda buat sendiri. Tersembunyi dari Google Meet (browser → → SCK), Microsoft Teams (SCK), OBS (SCK), semua alat pihak ketiga yang sesuai. Namun, alat-alat Apple sendiri dan mitra konferensi yang diberi kepercayaan oleh Apple tetap dapat melihatnya. getDisplayMedia Fitur "proteksi penangkapan layar" 1Password / Hand Mirror memiliki batasan yang sama. Orang-orang hanya tidak biasa merekam 1Password mereka dengan QuickTime, sehingga kebocoran tidak terlihat.
Ringkasan yang jujur yang saya berikan kepada Apple adalah:
publikkan entitas publik yang setara dengan , atau komit bahwa com.apple.private.screencapturekit.nopromptadalah jaminan keras terhadap NSWindow.sharingType = .none semua jalur penangkapan. Pada macOS 15.3.1, ini tidak ada — itu adalah jaminan keras terhadap kebanyakan jalur dan saran lemah bahwa alat berhak istimewa dapat melaluinya. Kondisi saat ini menciptakan posisi keamanan di mana pengguna percaya bahwa jendela tidak terlihat saat penangkapan, padahal itu tidak benar, yang lebih buruk daripada tidak ada perlindungan sama sekali. Solusi pengganti, diurutkan berdasarkan seberapa besar dampaknya
Untuk kasus saya — menjaga jendela obrolan tersembunyi saat berbagi layar di Zoom — semua ini bekerja dan tidak sempurna:
Bagi hanya satu jendela di Zoom, bukan desktop.
- Dialog Bagi Layar memiliki tab “Window”. Zoom hanya menangkap piksel dari jendela tersebut dan tidak ada yang lain, sehingga obrolan saya — dan semua hal lain di layar — secara otomatis tidak muncul. Ini adalah solusi paling andal dan tidak membutuhkan kode. Kelemahannya: penonton tidak melihat konteks layar secara keseluruhan. Gunakan Meet atau Teams daripada Zoom.
- Keduanya menghormati . Ini sangat baik jika Anda mengontrol alat pertemuan, sangat buruk jika Anda tidak.
sharingType = .noneLetakkan obrolan di ruang terpisah. - Mission Control memberi Anda beberapa desktop. Bagikan Ruang 1, letakkan obrolan di Ruang 2. Geser untuk berinteraksi. Lambat, mengganggu alur, tetapi berhasil. Gunakan perangkat kedua.
- Sebuah ponsel atau iPad di samping laptop Anda tidak dapat dihentikan oleh alat penangkapan apa pun, secara definisi. Saya memilih opsi 1 ditambah aplikasi obrolan yang sudah saya bangun. Obrolan ini tidak terlihat untuk sekitar 95% dari jalur penangkapan, dan untuk kasus berbagi layar di Zoom saya hanya tidak menggunakan berbagi layar desktop.
Apa yang saya inginkan selanjutnya
Entitas publik
- yang memungkinkan aplikasi yang telah dilakukan notarizasi menyatakan “jendela saya ini dikecualikan dari penangkapan, termasuk oleh pemanggil berhak istimewa.” Hari ini, itu tidak mungkin. jalur penangkapan. Kehadiran yang jujur dalam
- dokumentasi.
NSWindow.sharingTypeDokumentasi membuatnya terdengar seperti jaminan keras. Tidak — minimal dokumentasi harus menyebutkan bahwa alat berhak istimewa Apple dan aplikasi dengan entitas privat dapat menangkap meskipun demikian. Hari ini mereka tidak menyebutkan itu. Cara untuk memeriksa - aplikasi mana yang memiliki akses penangkapan berhak istimewa di sistem — serupa dengan “Files and Folders” di Privasi & Keamanan. Hari ini tidak ada permukaan bagi pengguna untuk melihat siapa yang dapat melintasi privasi mereka. Sampai salah satu dari itu muncul, saran praktis adalah: asumsikan bahwa setiap jendela di layar Anda dapat ditangkap oleh sistem dan oleh aplikasi konferensi utama, terlepas dari apa
yang Anda atur. API eksklusi ini nyata — mereka bekerja terhadap sebagian besar dunia — tetapi mereka bukan batas keamanan yang dapat dipercaya terhadap bagian dunia yang paling penting. sharingType Anda Tidak Bisa Menyembunyikan Jendela dari Zoom pada macOS 15 2
Instal Ekstensi Kami
Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat
恵 Papan Skor Telah Tiba!
Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!
Alat Wajib Coba
Lihat semua Pendatang baru
Lihat semuaMemperbarui: Kita alat terbaru ditambahkan pada 26 Apr 2026
