From ecfda19eb5f69a95bf9e70f5a47a0341498af8fe Mon Sep 17 00:00:00 2001 From: Damian Minkov Date: Mon, 9 Feb 2015 18:19:09 +0200 Subject: [PATCH] Adds always on top indicator to notify user when sharing its full screen. --- resources/languages/resources.properties | 1 + .../impl/gui/main/call/CallManager.java | 33 ++- .../main/call/FullScreenShareIndicator.java | 208 ++++++++++++++++++ 3 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/gui/main/call/FullScreenShareIndicator.java diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 75ef88065..f6fc83df6 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -190,6 +190,7 @@ service.gui.DATE=Date service.gui.DELETE=Delete service.gui.DENY=&Deny service.gui.DESKTOP_SHARING_WARNING=Are you sure you want to start screen sharing?
Clicking OK will let people on this call see your screen. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=You are sharing your screen service.gui.DIALPAD=Dial Pad service.gui.DISPLAY_NAME=Display name service.gui.DISCONNECTED_STATUS=Disconnected diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java index 79a5c5f7d..80b8e4f28 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java @@ -544,7 +544,8 @@ private static void createDesktopSharing( protocolProvider, contact, uiContact, - desktopDevices.get(0)); + desktopDevices.get(0), + true); } else if (deviceNumber > 1) { @@ -557,7 +558,8 @@ else if (deviceNumber > 1) protocolProvider, contact, uiContact, - selectDialog.getSelectedDevice()); + selectDialog.getSelectedDevice(), + true); } } @@ -624,7 +626,8 @@ public static void createRegionDesktopSharing( width, height, x, - y)); + y), + false); } } @@ -636,17 +639,20 @@ public static void createRegionDesktopSharing( * @param contact the contact to call to * @param uiContact the UIContactImpl we're calling * @param mediaDevice the media device corresponding to the screen to share + * @param fullscreen whether we are sharing the fullscreen */ private static void createDesktopSharing( ProtocolProviderService protocolProvider, String contact, UIContactImpl uiContact, - MediaDevice mediaDevice) + MediaDevice mediaDevice, + boolean fullscreen) { new CreateDesktopSharingThread( protocolProvider, contact, uiContact, - mediaDevice).start(); + mediaDevice, + fullscreen).start(); } /** @@ -667,6 +673,8 @@ else if (showDesktopSharingWarning()) = mediaService.getDevices(MediaType.VIDEO, MediaUseCase.DESKTOP); int deviceNumber = desktopDevices.size(); + new FullScreenShareIndicator(call); + if (deviceNumber == 1) enableDesktopSharing(call, null, enable); else if (deviceNumber > 1) @@ -2781,6 +2789,11 @@ private static class CreateDesktopSharingThread */ private final UIContactImpl uiContact; + /** + * Whether user has selected sharing full screen or region. + */ + private boolean fullscreen = false; + /** * Creates a desktop sharing session thread. * @@ -2796,12 +2809,14 @@ public CreateDesktopSharingThread( ProtocolProviderService protocolProvider, String contact, UIContactImpl uiContact, - MediaDevice mediaDevice) + MediaDevice mediaDevice, + boolean fullscreen) { this.protocolProvider = protocolProvider; this.stringContact = contact; this.uiContact = uiContact; this.mediaDevice = mediaDevice; + this.fullscreen = fullscreen; } @Override @@ -2858,6 +2873,12 @@ public void run() if (uiContact != null && createdCall != null) addUIContactCall(uiContact, createdCall); + + + if(createdCall != null && fullscreen) + { + new FullScreenShareIndicator(createdCall); + } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenShareIndicator.java b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenShareIndicator.java new file mode 100644 index 000000000..cd7e5433d --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenShareIndicator.java @@ -0,0 +1,208 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.gui.main.call; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.media.*; +import org.jitsi.service.neomedia.*; + +import javax.swing.*; +import javax.swing.plaf.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.*; + +/** + * FullScreenShareIndicator take care of always on top dialog + * shown when we are sharing our fullscreen. This way when users go to other + * application can still see an indication that their screen is shared, so + * don't show sensitive information. + * We use the java setAlwaysOnTop which is reported to be not working when + * using fullscreen, for example if you enter fullscreen of the call (but + * as you are sharing your screen it doesn't make sense). It also stops working + * if other app goes in always on top, like when using windows you open task + * manager and it is set as always on top, our indicator dialog will stop to + * be always on top. + * + * @author Damian Minkov + */ +public class FullScreenShareIndicator + extends CallChangeAdapter + implements PropertyChangeListener +{ + /** + * The call to take care of. + */ + private final Call call; + + /** + * The dialog that is shown, otherwise null. + */ + private JDialog dialog = null; + + /** + * Constructs the indicator and adds the appropriate listeners. + * @param call + */ + FullScreenShareIndicator(Call call) + { + this.call = call; + + if(call instanceof MediaAwareCall) + { + ((MediaAwareCall)call).addVideoPropertyChangeListener(this); + } + call.addCallChangeListener(this); + } + + /** + * Listens for vide change events of local video straming in mesia case + * desktop, whether we need to start and show the dialog, or if already + * shown to close it. + * @param evt the video event + */ + @Override + public void propertyChange(PropertyChangeEvent evt) + { + if(!evt.getPropertyName() + .equals(OperationSetVideoTelephony.LOCAL_VIDEO_STREAMING) + || (call instanceof MediaAwareCall + && ((MediaAwareCall)call).getMediaUseCase() + != MediaUseCase.DESKTOP)) + return; + + Object newValue = evt.getNewValue(); + Object oldValue = evt.getOldValue(); + + // and if there is no frame shown for region desktop sharing + if((oldValue == null || oldValue == MediaDirection.RECVONLY) + && newValue == MediaDirection.SENDRECV + && DesktopSharingFrame.getFrameForCall(call) == null) + { + showDialog(); + } + else if(oldValue == MediaDirection.SENDRECV + && (newValue == null || newValue == MediaDirection.RECVONLY)) + { + closeDialog(); + } + } + + /** + * Listens whether we need to show or hide the dialog. + * @param ev + */ + @Override + public void callStateChanged(CallChangeEvent ev) + { + if(!CallChangeEvent.CALL_STATE_CHANGE + .equals(ev.getPropertyName())) + return; + + Object newValue = ev.getNewValue(); + + if(CallState.CALL_INITIALIZATION.equals(newValue) + || CallState.CALL_IN_PROGRESS.equals(newValue)) + { + showDialog(); + + } + else if(CallState.CALL_ENDED.equals(newValue)) + { + ev.getSourceCall().removeCallChangeListener(this); + + if(call instanceof MediaAwareCall) + { + ((MediaAwareCall)call) + .removeVideoPropertyChangeListener(this); + } + + closeDialog(); + } + } + + /** + * Creates and shows the dialog if not already created. + */ + private void showDialog() + { + if(dialog != null) + return; + + dialog = new JDialog((Window) null) + { + @Override + public void setVisible(boolean b) + { + setLocationByPlatform(false); + + Dimension screenSize = + Toolkit.getDefaultToolkit().getScreenSize(); + setLocation(screenSize.width/2 - getWidth()/2, + getLocation().y); + + super.setVisible(b); + } + }; + dialog.setUndecorated(true); + dialog.getRootPane().setWindowDecorationStyle(JRootPane.NONE); + dialog.setAlwaysOnTop(true); + + JLabel label = new JLabel( + GuiActivator.getResources() + .getI18NString("service.gui.DESKTOP_SHARING_DIALOG_INDICATE")); + label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 8)); + + Color backgroundColor = + new ColorUIResource(GuiActivator.getResources(). + getColor("service.gui.DESKTOP_BACKGROUND")); + + JPanel panel = new JPanel(new FlowLayout()); + panel.setBackground(backgroundColor); + + JPanel linePanel = new TransparentPanel(new BorderLayout()); + linePanel.add(label, BorderLayout.CENTER); + linePanel.setBorder( + BorderFactory.createMatteBorder(0, 0, 0, 1, Color.lightGray)); + panel.add(linePanel); + + SIPCommTextButton stopButton = new SIPCommTextButton("Stop"); + stopButton.setBackground(backgroundColor); + panel.add(stopButton); + stopButton.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + if (CallManager.isDesktopSharingEnabled(call)) + { + CallManager.enableDesktopSharing(call, false); + } + } + }); + + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + dialog.getContentPane().add(panel); + dialog.pack(); + dialog.setVisible(true); + } + + /** + * Closes and clears the dialog instance. + */ + private void closeDialog() + { + if(dialog != null) + { + dialog.setVisible(false); + dialog = null; + } + } +}