diff --git a/include/wx/msw/missing.h b/include/wx/msw/missing.h index 7f381bb898..6e75c541c8 100644 --- a/include/wx/msw/missing.h +++ b/include/wx/msw/missing.h @@ -398,6 +398,18 @@ #ifndef MUI_LANGUAGE_NAME #define MUI_LANGUAGE_NAME 0x8 +#endif + +#ifndef WDA_NONE +#define WDA_NONE 0x0 +#endif + +#ifndef WDA_MONITOR +#define WDA_MONITOR 0x1 +#endif + +#ifndef WDA_EXCLUDEFROMCAPTURE +#define WDA_EXCLUDEFROMCAPTURE 0x11 #endif /* diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 3b52341376..18b36f46b3 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -68,6 +68,9 @@ public: virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) wxOVERRIDE; virtual bool IsFullScreen() const wxOVERRIDE { return m_fsIsShowing; } + virtual wxContentProtection GetContentProtection() const wxOVERRIDE; + virtual bool SetContentProtection(wxContentProtection contentProtection) wxOVERRIDE; + // wxMSW only: EnableCloseButton(false) may be used to remove the "Close" // button from the title bar virtual bool EnableCloseButton(bool enable = true) wxOVERRIDE; diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index cbe2b4aa21..83de3b8d64 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -297,6 +297,9 @@ public : virtual void SetTitle( const wxString& title, wxFontEncoding encoding ) wxOVERRIDE; + virtual wxContentProtection GetContentProtection() const wxOVERRIDE; + virtual bool SetContentProtection(wxContentProtection contentProtection) wxOVERRIDE; + virtual bool EnableCloseButton(bool enable) wxOVERRIDE; virtual bool EnableMaximizeButton(bool enable) wxOVERRIDE; virtual bool EnableMinimizeButton(bool enable) wxOVERRIDE; diff --git a/include/wx/osx/core/private.h b/include/wx/osx/core/private.h index bf56446f69..53e5bdb687 100644 --- a/include/wx/osx/core/private.h +++ b/include/wx/osx/core/private.h @@ -76,6 +76,7 @@ WXDLLIMPEXP_BASE CFURLRef wxOSXCreateURLFromFileSystemPath( const wxString& path #include "wx/bmpbndl.h" #include "wx/window.h" +#include "wx/toplevel.h" class wxTextProofOptions; @@ -965,6 +966,9 @@ public : virtual bool ShowFullScreen(bool show, long style)= 0; + virtual wxContentProtection GetContentProtection() const = 0; + virtual bool SetContentProtection(wxContentProtection contentProtection) = 0; + virtual void RequestUserAttention(int flags) = 0; virtual void ScreenToWindow( int *x, int *y ) = 0; diff --git a/include/wx/osx/iphone/private.h b/include/wx/osx/iphone/private.h index 011434fbcc..58e9b6e3ae 100644 --- a/include/wx/osx/iphone/private.h +++ b/include/wx/osx/iphone/private.h @@ -184,6 +184,11 @@ public : virtual bool ShowFullScreen(bool show, long style); + virtual wxContentProtection GetContentProtection() const wxOVERRIDE + { return wxCONTENT_PROTECTION_NONE; } + virtual bool SetContentProtection(wxContentProtection contentProtection) wxOVERRIDE + { return false; } + virtual void RequestUserAttention(int flags); virtual void ScreenToWindow( int *x, int *y ); diff --git a/include/wx/osx/toplevel.h b/include/wx/osx/toplevel.h index bde2671a14..4882037a23 100644 --- a/include/wx/osx/toplevel.h +++ b/include/wx/osx/toplevel.h @@ -68,6 +68,9 @@ public: virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) wxOVERRIDE; virtual bool IsFullScreen() const wxOVERRIDE; + virtual wxContentProtection GetContentProtection() const wxOVERRIDE; + virtual bool SetContentProtection(wxContentProtection contentProtection) wxOVERRIDE; + // implementation from now on // -------------------------- diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h index 5632aff027..3adeb8c998 100644 --- a/include/wx/toplevel.h +++ b/include/wx/toplevel.h @@ -119,6 +119,13 @@ enum wxUSER_ATTENTION_ERROR = 2 }; +// Values for Get/SetContentProtection +enum wxContentProtection +{ + wxCONTENT_PROTECTION_NONE, + wxCONTENT_PROTECTION_ENABLED +}; + // ---------------------------------------------------------------------------- // wxTopLevelWindow: a top level (as opposed to child) window // ---------------------------------------------------------------------------- @@ -181,6 +188,11 @@ public: // return true if the frame is in fullscreen mode virtual bool IsFullScreen() const = 0; + virtual wxContentProtection GetContentProtection() const + { return wxCONTENT_PROTECTION_NONE; } + virtual bool SetContentProtection(wxContentProtection WXUNUSED(contentProtection)) + { return false; } + // the title of the top level window: the text which the // window shows usually at the top of the frame/dialog in dedicated bar virtual void SetTitle(const wxString& title) = 0; diff --git a/interface/wx/toplevel.h b/interface/wx/toplevel.h index ab852628f3..76dad23d53 100644 --- a/interface/wx/toplevel.h +++ b/interface/wx/toplevel.h @@ -14,6 +14,13 @@ enum wxUSER_ATTENTION_ERROR = 2 ///< Results in a more drastic action. }; +// Values for wxTopLevelWindow::GetContentProtection() and wxTopLevelWindow::SetContentProtection() +enum wxContentProtection +{ + wxCONTENT_PROTECTION_NONE, ///< Window contents are visible in screen captures + wxCONTENT_PROTECTION_ENABLED ///< Window contents are not visible in screen captures +}; + /** Styles used with wxTopLevelWindow::ShowFullScreen(). */ @@ -682,6 +689,39 @@ public: */ virtual bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL); + /** + Get the current content protection of the window. + + @see SetContentProtection() + + @since 3.1.6 + */ + virtual wxContentProtection GetContentProtection() const; + + /** + Set content protection for the window. + + When content protection is enabled contents of this window will not + be included in screen captures. + + Obviously this can't provide absolute security as there might be + workarounds and tools that bypass this protection. Additionally a + screen could always be photographed. + + @return @true if the content protection was changed, @false if running + under an unsupported OS. + + @note Windows 7 or newer is required but any macOS version is supported. + + @onlyfor{wxmsw,wxosx} + + @see GetContentProtection() + + @since 3.1.6 + */ + virtual bool SetContentProtection(wxContentProtection contentProtection); + + /** This method is specific to wxUniversal port. diff --git a/samples/display/display.cpp b/samples/display/display.cpp index ac572af0cc..914b78473f 100644 --- a/samples/display/display.cpp +++ b/samples/display/display.cpp @@ -67,6 +67,7 @@ public: void OnQuit(wxCommandEvent& event); void OnFromPoint(wxCommandEvent& event); void OnFullScreen(wxCommandEvent& event); + void OnContentProtection(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); #if wxUSE_DISPLAY @@ -115,6 +116,8 @@ enum // menu items Display_FromPoint = wxID_HIGHEST + 1, Display_FullScreen, + Display_ContentProtection_None, + Display_ContentProtection_Enable, // controls Display_ChangeMode, @@ -140,6 +143,8 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Display_Quit, MyFrame::OnQuit) EVT_MENU(Display_FromPoint, MyFrame::OnFromPoint) EVT_MENU(Display_FullScreen, MyFrame::OnFullScreen) + EVT_MENU(Display_ContentProtection_None, MyFrame::OnContentProtection) + EVT_MENU(Display_ContentProtection_Enable, MyFrame::OnContentProtection) EVT_MENU(Display_About, MyFrame::OnAbout) #if wxUSE_DISPLAY @@ -210,6 +215,13 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, itemFullScreen->SetBitmap( wxArtProvider::GetBitmap(wxART_FULL_SCREEN, wxART_MENU) ); + + wxMenu* contentProtectionMenu = new wxMenu(); + contentProtectionMenu->Append(Display_ContentProtection_None, _("&None"), "", wxITEM_RADIO); + contentProtectionMenu->Check(Display_ContentProtection_None, true); + contentProtectionMenu->Append(Display_ContentProtection_Enable, _("&Enabled"), "", wxITEM_RADIO); + menuDisplay->Append(wxID_ANY, _("Content &Protection"), contentProtectionMenu); + menuDisplay->Append(itemFullScreen); menuDisplay->AppendSeparator(); menuDisplay->Append(Display_Quit, _("E&xit\tAlt-X"), _("Quit this program")); @@ -406,6 +418,34 @@ void MyFrame::OnFullScreen(wxCommandEvent& WXUNUSED(event)) ShowFullScreen(!IsFullScreen()); } +void MyFrame::OnContentProtection(wxCommandEvent& event) +{ + wxContentProtection contentProtection; + switch (event.GetId()) + { + case Display_ContentProtection_Enable: + contentProtection = wxCONTENT_PROTECTION_ENABLED; + break; + default: + contentProtection = wxCONTENT_PROTECTION_NONE; + } + + if (SetContentProtection(contentProtection)) + { + switch (GetContentProtection()) + { + case wxCONTENT_PROTECTION_ENABLED: + wxLogInfo("The contents of this window should now NOT be visible in screen captures."); + break; + case wxCONTENT_PROTECTION_NONE: + wxLogInfo("The contents of this window should now be visible in screen captures."); + break; + } + } + else + wxLogError("Content protection could not be changed"); +} + #if wxUSE_DISPLAY void MyFrame::OnChangeMode(wxCommandEvent& event) diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 972585258b..1439cd589e 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -34,6 +34,7 @@ #include "wx/module.h" #endif //WX_PRECOMP +#include "wx/dynlib.h" #include "wx/scopeguard.h" #include "wx/tooltip.h" @@ -1048,6 +1049,47 @@ void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons) DoSelectAndSetIcon(icons, SM_CXICON, SM_CYICON, ICON_BIG); } +wxContentProtection wxTopLevelWindowMSW::GetContentProtection() const +{ +#if wxUSE_DYNLIB_CLASS + typedef BOOL(WINAPI *GetWindowDisplayAffinity_t)(HWND, DWORD *); + + wxDynamicLibrary dllUser32("user32.dll"); + GetWindowDisplayAffinity_t pfnGetWindowDisplayAffinity = + (GetWindowDisplayAffinity_t)dllUser32.RawGetSymbol("GetWindowDisplayAffinity"); + if (pfnGetWindowDisplayAffinity) + { + DWORD affinity = 0; + if (!pfnGetWindowDisplayAffinity(GetHWND(), &affinity)) + wxLogLastError("GetWindowDisplayAffinity"); + else if (affinity & WDA_MONITOR) + return wxCONTENT_PROTECTION_ENABLED; + } +#endif + return wxCONTENT_PROTECTION_NONE; +} + +bool wxTopLevelWindowMSW::SetContentProtection(wxContentProtection contentProtection) +{ +#if wxUSE_DYNLIB_CLASS + typedef BOOL(WINAPI *SetWindowDisplayAffinity_t)(HWND, DWORD); + + wxDynamicLibrary dllUser32("user32.dll"); + SetWindowDisplayAffinity_t pfnSetWindowDisplayAffinity = + (SetWindowDisplayAffinity_t)dllUser32.RawGetSymbol("SetWindowDisplayAffinity"); + if (pfnSetWindowDisplayAffinity) + { + if (pfnSetWindowDisplayAffinity(GetHWND(), + (contentProtection == wxCONTENT_PROTECTION_ENABLED) ? + WDA_MONITOR : WDA_NONE)) + return true; + else + wxLogLastError("SetWindowDisplayAffinity"); + } +#endif + return false; +} + // static bool wxTopLevelWindowMSW::MSWEnableCloseButton(WXHWND hwnd, bool enable) { diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index dd98b3db85..75f4a315f9 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -1093,6 +1093,20 @@ void wxNonOwnedWindowCocoaImpl::SetTitle( const wxString& title, wxFontEncoding [m_macWindow setTitle:wxCFStringRef( title , encoding ).AsNSString()]; } +wxContentProtection wxNonOwnedWindowCocoaImpl::GetContentProtection() const +{ + return (m_macWindow.sharingType == NSWindowSharingNone) ? + wxCONTENT_PROTECTION_ENABLED : wxCONTENT_PROTECTION_NONE; +} + +bool wxNonOwnedWindowCocoaImpl::SetContentProtection(wxContentProtection contentProtection) +{ + m_macWindow.sharingType = (contentProtection == wxCONTENT_PROTECTION_ENABLED) ? + NSWindowSharingNone : NSWindowSharingReadOnly; + + return true; +} + bool wxNonOwnedWindowCocoaImpl::EnableCloseButton(bool enable) { [[m_macWindow standardWindowButton:NSWindowCloseButton] setEnabled:enable]; diff --git a/src/osx/toplevel_osx.cpp b/src/osx/toplevel_osx.cpp index b7ca67b3b8..71df160a03 100644 --- a/src/osx/toplevel_osx.cpp +++ b/src/osx/toplevel_osx.cpp @@ -196,6 +196,16 @@ bool wxTopLevelWindowMac::IsFullScreen() const return m_nowpeer->IsFullScreen(); } +wxContentProtection wxTopLevelWindowMac::GetContentProtection() const +{ + return m_nowpeer->GetContentProtection(); +} + +bool wxTopLevelWindowMac::SetContentProtection(wxContentProtection contentProtection) +{ + return m_nowpeer->SetContentProtection(contentProtection); +} + bool wxTopLevelWindowMac::EnableCloseButton(bool enable) { // Unlike in wxMSW, wxSYSTEM_MENU is not sufficient to show