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 3387532c7..2c85e309d 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 @@ -619,7 +619,7 @@ public static void enableRegionDesktopSharing( if (deviceNumber > 0) { - enableDesktopSharing( + boolean succeed = enableDesktopSharing( call, mediaService.getMediaDeviceForPartialDesktopStreaming( width, @@ -627,6 +627,15 @@ public static void enableRegionDesktopSharing( x, y), true); + // If the region sharing succeed, then display the frame of the + // current region shared. + if(succeed) + { + TransparentFrame frame + = DesktopSharingFrame.createTransparentFrame(call, false); + + frame.setVisible(true); + } } // in case we switch to video, disable remote control if it was @@ -641,8 +650,11 @@ public static void enableRegionDesktopSharing( * @param mediaDevice the media device corresponding to the screen to share * @param enable indicates if the desktop sharing should be enabled or * disabled + * + * @return True if the desktop sharing succeed (we are currently sharing the + * whole or a part of the desktop). False, otherwise. */ - private static void enableDesktopSharing(Call call, + private static boolean enableDesktopSharing(Call call, MediaDevice mediaDevice, boolean enable) { @@ -681,8 +693,7 @@ private static void enableDesktopSharing(Call call, } } - if (enable && !enableSucceeded) - getActiveCallContainer(call).setDesktopSharingButtonSelected(false); + return (enable && enableSucceeded); } /** @@ -2418,9 +2429,6 @@ public void run() // First make sure the desktop sharing is disabled. if (enable && isDesktopSharingEnabled(call)) { - getActiveCallContainer(call) - .setDesktopSharingButtonSelected(false); - JFrame frame = DesktopSharingFrame.getFrameForCall(call); if(frame != null) diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java index f0a40ccbe..527c581bf 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java @@ -26,10 +26,12 @@ import net.java.sip.communicator.service.gui.call.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.media.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; import net.java.sip.communicator.util.skin.*; +import org.jitsi.service.neomedia.*; import org.jitsi.util.*; import org.jitsi.util.event.*; import org.osgi.framework.*; @@ -745,6 +747,8 @@ private void doUpdateSettingsPanelInEventDispatchThread( boolean videoTelephony = false; boolean videoTelephonyIsLocalVideoAllowed = false; boolean videoTelephonyIsLocalVideoStreaming = false; + boolean desktopSharing = false; + boolean desktopSharingIsStreamed = false; for (Call call : calls) { @@ -796,6 +800,25 @@ private void doUpdateSettingsPanelInEventDispatchThread( videoTelephonyIsLocalVideoStreaming = true; } } + + if(!desktopSharing) + { + OperationSetDesktopStreaming osds + = pps.getOperationSet( + OperationSetDesktopStreaming.class); + if(osds != null) + { + desktopSharing = true; + + if(videoTelephonyIsLocalVideoStreaming + && call instanceof MediaAwareCall + && ((MediaAwareCall) call).getMediaUseCase() + == MediaUseCase.DESKTOP) + { + desktopSharingIsStreamed = true; + } + } + } } conferenceButton.setEnabled(telephonyConferencing); @@ -820,6 +843,19 @@ private void doUpdateSettingsPanelInEventDispatchThread( showHideVideoButton.isEnabled() && uiVideoHandler.isLocalVideoVisible()); showHideVideoButton.setVisible(showHideVideoButton.isEnabled()); + + // The desktop sharing button depends on the operation set desktop + // sharing server. + desktopSharingButton.setEnabled(desktopSharing); + desktopSharingButton.setSelected(desktopSharingIsStreamed); + if (callPanel instanceof OneToOneCallPanel) + { + OneToOneCallPanel oneToOneCallPanel = (OneToOneCallPanel) callPanel; + if(desktopSharingIsStreamed) + oneToOneCallPanel.addDesktopSharingComponents(); + else + oneToOneCallPanel.removeDesktopSharingComponents(); + } } /** @@ -1750,37 +1786,6 @@ private void setCallTitle(long startTime) fireTitleChangeEvent(); } - /** - * Selects or unselects the desktop sharing button in this call dialog. - * - * @param isSelected indicates if the video button should be selected or not - */ - public void setDesktopSharingButtonSelected(boolean isSelected) - { - if (logger.isTraceEnabled()) - logger.trace("Desktop sharing enabled: " + isSelected); - - if (isSelected && !desktopSharingButton.isSelected()) - desktopSharingButton.setSelected(true); - else if (!isSelected && desktopSharingButton.isSelected()) - desktopSharingButton.setSelected(false); - - if (callPanel instanceof OneToOneCallPanel) - { - OneToOneCallPanel oneToOneCallPanel = (OneToOneCallPanel) callPanel; - - if (isSelected - && (oneToOneCallPanel.getCall().getProtocolProvider() - .getOperationSet(OperationSetDesktopSharingServer.class) - != null)) - { - oneToOneCallPanel.addDesktopSharingComponents(); - } - else - oneToOneCallPanel.removeDesktopSharingComponents(); - } - } - /** * Sets the display of this view to full-screen or windowed mode. * diff --git a/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingMouseAndKeyboardListener.java b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingMouseAndKeyboardListener.java new file mode 100644 index 000000000..6b5e6922e --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingMouseAndKeyboardListener.java @@ -0,0 +1,259 @@ +/* + * 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.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +import java.awt.*; +import java.awt.event.*; + +/** + * This class listens to mouse and keyboard event for dekstop sharing at the + * client side, in order to send moves, clicks and key strokes to the server. + * + * @author Vincent Lucas + */ +public class DesktopSharingMouseAndKeyboardListener + implements RemoteControlListener, + KeyListener, + MouseListener, + MouseMotionListener +{ + /** + * The remote controlled call peer to which the events must be sent. + */ + private CallPeer remoteCallPeer; + + /** + * The video component displqying the remote desktop. + */ + private Component videoComponent = null; + + /** + * An object get mutual exclusion access to the videoComponent. + */ + private Object videoComponentMutex = new Object(); + + /** + * The oeration set which received the granted/revoked desktop sharing + * rights and to which, we are sending the mouse and key events. + */ + private OperationSetDesktopSharingClient opSetDesktopSharingClient = null; + + /** + * Creates a new listener of mouse and key event for a the + * video diplaying the streamed remote desktop. The video component is null + * until calling the setVideoComponent function. + * + * @param remoteCallPeer The remote controlled call peer to which the events + * must be sent. + */ + public DesktopSharingMouseAndKeyboardListener(CallPeer remoteCallPeer) + { + this.remoteCallPeer = remoteCallPeer; + + this.opSetDesktopSharingClient + = remoteCallPeer.getProtocolProvider().getOperationSet( + OperationSetDesktopSharingClient.class); + } + + /** + * Sets the video diplaying component for the streamed remote desktop. + * + * @param videoComponenet The video component displqying the remote desktop. + */ + public void setVideoComponent(Component videoComponent) + { + synchronized(this.videoComponentMutex) + { + // If there was an old video component, and no new one, then + // unregisters to the operation set. + if(this.videoComponent != null + && videoComponent == null) + { + // The remove remote control listener will also be called + // directly by the operationst when the peer state change. + opSetDesktopSharingClient.removeRemoteControlListener(this); + } + // If there was no video component, and a new one is set, then + // registers to the operation set. + else if(this.videoComponent == null + && videoComponent != null) + { + opSetDesktopSharingClient.addRemoteControlListener(this); + } + + this.videoComponent = videoComponent; + } + } + + /** + * Returns the remote-controlled CallPeer. + * + * @return The remote-controlled CallPeer. + */ + public CallPeer getCallPeer() + { + return this.remoteCallPeer; + } + + /** + * This method is called when remote control has been granted. + * + * @param event The event which grants us the control of the remote call + * peer. + */ + public void remoteControlGranted(RemoteControlGrantedEvent event) + { + synchronized(this.videoComponentMutex) + { + if(this.videoComponent != null) + { + this.videoComponent.addKeyListener(this); + this.videoComponent.addMouseListener(this); + this.videoComponent.addMouseMotionListener(this); + } + } + } + + /** + * This method is called when remote control has been revoked. + * + * @param event The event which revokes us the control of the remote call + * peer. + */ + public void remoteControlRevoked(RemoteControlRevokedEvent event) + { + synchronized(this.videoComponentMutex) + { + if(this.videoComponent != null) + { + this.videoComponent.removeKeyListener(this); + this.videoComponent.removeMouseListener(this); + this.videoComponent.removeMouseMotionListener(this); + } + } + } + + /** + * Invoked when a mouse button is pressed on a + * component and then dragged. + * + * @param e The mouse dragged event. + */ + public void mouseDragged(MouseEvent e) + { + opSetDesktopSharingClient.sendMouseEvent( + remoteCallPeer, + e, + videoComponent.getBounds().getSize()); + } + + /** + * Invoked when the mouse cursor has been moved + * onto a component but no buttons have been pushed. + * + * @param e The mouse moved event. + */ + public void mouseMoved(MouseEvent e) + { + opSetDesktopSharingClient.sendMouseEvent( + remoteCallPeer, + e, + videoComponent.getBounds().getSize()); + } + + + /** + * Invoked when the mouse button has been clicked (pressed and released) on + * a component. + * + * @param e The mouse event. + */ + public void mouseClicked(MouseEvent e) + { + opSetDesktopSharingClient.sendMouseEvent( + remoteCallPeer, + e, + videoComponent.getBounds().getSize()); + } + + /** + * Invoked when the mouse enters a component. + * + * @param e The mouse event. + */ + public void mouseEntered(MouseEvent e) + { + } + + /** + * Invoked when the mouse exits a component. + * + * @param e The mouse event. + */ + public void mouseExited(MouseEvent e) + { + } + + /** + * Invoked when a mouse button has been pressed on a component. + * + * @param e The mouse event. + */ + public void mousePressed(MouseEvent e) + { + opSetDesktopSharingClient.sendMouseEvent( + remoteCallPeer, + e, + videoComponent.getBounds().getSize()); + } + + /** + * Invoked when a mouse button has been released on a component. + * + * @param e The mouse event. + */ + public void mouseReleased(MouseEvent e) + { + opSetDesktopSharingClient.sendMouseEvent( + remoteCallPeer, + e, + videoComponent.getBounds().getSize()); + } + + /** + * Invoked when a key has been pressed. + * + * @param e The keyborad event. + */ + public void keyPressed(KeyEvent e) + { + } + + /** + * Invoked when a key has been released. + * + * @param e The keyborad event. + */ + public void keyReleased(KeyEvent e) + { + } + + /** + * Invoked when a key has been typed. + * + * @param e The keyborad event. + */ + public void keyTyped(KeyEvent e) + { + opSetDesktopSharingClient.sendKeyboardEvent( + remoteCallPeer, + e); + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java index 985c73293..32fbad385 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java @@ -209,6 +209,13 @@ public class OneToOneCallPeerPanel */ private final UIVideoHandler2 uiVideoHandler; + /** + * A listener to desktop sharing granted/revoked events and to mouse and + * keyboard interaction with the remote video displaying the remote desktop. + */ + private DesktopSharingMouseAndKeyboardListener + desktopSharingMouseAndKeyboardListener; + /** * The Observer which listens to changes in the video-related * information detected and reported by {@link #uiVideoHandler}. @@ -320,6 +327,9 @@ public OneToOneCallPeerPanel( } updateViewFromModel(); + + this.desktopSharingMouseAndKeyboardListener + = new DesktopSharingMouseAndKeyboardListener(callPeer); } /** @@ -1370,6 +1380,11 @@ private void updateViewFromModelInEventDispatchThread() // the LO/SD/HD button. if(remoteVideoChanged) { + // Updates video component which may listen the mouse and key + // events. + this.desktopSharingMouseAndKeyboardListener + .setVideoComponent(remoteVideo); + CallPanel callPanel = callRenderer.getCallContainer(); // The remote video has been added, then tries to display the // LO/SD/HD button. diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetDesktopSharingClient.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetDesktopSharingClient.java index 743676dcb..6ea438fa0 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetDesktopSharingClient.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetDesktopSharingClient.java @@ -152,7 +152,7 @@ public void fireRemoteControlGranted(CallPeer peer) { listener.remoteControlGranted(new RemoteControlGrantedEvent(peer)); } - // The UI has not created the listenre yet, then we need to store the + // The UI has not created the listener yet, then we need to store the // information taht this peer has alreayd been granted. else {