aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYana Stamcheva <yana@jitsi.org>2011-02-17 16:35:42 +0000
committerYana Stamcheva <yana@jitsi.org>2011-02-17 16:35:42 +0000
commit7ab0b8ca79221230bda2e8d7ebe4e7fe68dc4055 (patch)
tree397fb4ac87387475b364fa3b7f44158c76841d6f
parent9ed22ae8263529ef19f5c393a5710eee0b2171c9 (diff)
downloadjitsi-7ab0b8ca79221230bda2e8d7ebe4e7fe68dc4055.zip
jitsi-7ab0b8ca79221230bda2e8d7ebe4e7fe68dc4055.tar.gz
jitsi-7ab0b8ca79221230bda2e8d7ebe4e7fe68dc4055.tar.bz2
Ongoing work on partial desktop sharing user interface.
-rw-r--r--lib/felix.client.run.properties1
-rw-r--r--resources/images/images.properties2
-rw-r--r--resources/images/impl/gui/buttons/transparentWindowButton.pngbin0 -> 1423 bytes
-rw-r--r--resources/images/impl/gui/common/src/windowResizeIcon.svg80
-rw-r--r--resources/images/impl/gui/common/windowResizeIcon.pngbin0 -> 283 bytes
-rw-r--r--resources/languages/resources.properties4
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallManager.java269
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingButton.java75
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingFrame.java567
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java99
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java71
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java19
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactRightButtonMenu.java148
-rw-r--r--src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf1
-rw-r--r--src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java6
-rw-r--r--src/net/java/sip/communicator/util/swing/transparent/AWTUtilitiesWrapper.java170
-rw-r--r--src/net/java/sip/communicator/util/swing/transparent/TransparentFrame.java82
-rw-r--r--src/net/java/sip/communicator/util/util.manifest.mf4
18 files changed, 1364 insertions, 234 deletions
diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties
index cd2954e..a1caf60 100644
--- a/lib/felix.client.run.properties
+++ b/lib/felix.client.run.properties
@@ -7,6 +7,7 @@ org.osgi.framework.system.packages.extra= \
com.apple.cocoa.foundation; \
com.apple.eawt; \
com.apple.eio; \
+ com.sun.awt; \
net.java.sip.communicator.util.launchutils; \
org.apache.xml.serialize; \
org.jdesktop.jdic.desktop; \
diff --git a/resources/images/images.properties b/resources/images/images.properties
index 2b05421..3b398ab 100644
--- a/resources/images/images.properties
+++ b/resources/images/images.properties
@@ -101,6 +101,7 @@ service.gui.icons.VOICEMAIL=resources/images/impl/gui/common/voicemail.png
service.gui.icons.SEND_SMS=resources/images/impl/gui/common/sms.png
service.gui.icons.SEND_SMS_SELECTED=resources/images/impl/gui/common/smsSelected.png
service.gui.icons.TYPING=resources/images/impl/gui/common/typing.gif
+service.gui.icons.WINDOW_RESIZE_ICON=resources/images/impl/gui/common/windowResizeIcon.png
# Status icons
service.gui.statusicons.USER_ONLINE_ICON=resources/images/impl/gui/common/statusicons/online.png
@@ -202,6 +203,7 @@ service.gui.buttons.ZOOM_IN=resources/images/impl/gui/buttons/magnifier_zoom_in.
service.gui.buttons.RESET=resources/images/impl/gui/buttons/reset.png
service.gui.buttons.VOLUME_CONTROL=resources/images/impl/gui/buttons/volumeControl.png
service.gui.buttons.CLOSE_VIDEO=resources/images/impl/gui/buttons/closeVideo.png
+service.gui.buttons.TRANSPARENT_WINDOW_BUTTON=resources/images/impl/gui/buttons/transparentWindowButton.png
# Sound level icons
service.gui.soundlevel.SOUND_LEVEL_ACTIVE=resources/images/impl/gui/common/soundlevel/soundActive.png
diff --git a/resources/images/impl/gui/buttons/transparentWindowButton.png b/resources/images/impl/gui/buttons/transparentWindowButton.png
new file mode 100644
index 0000000..4ba895f
--- /dev/null
+++ b/resources/images/impl/gui/buttons/transparentWindowButton.png
Binary files differ
diff --git a/resources/images/impl/gui/common/src/windowResizeIcon.svg b/resources/images/impl/gui/common/src/windowResizeIcon.svg
new file mode 100644
index 0000000..48e7ee2
--- /dev/null
+++ b/resources/images/impl/gui/common/src/windowResizeIcon.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="New document 1">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2830"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7"
+ inkscape:cx="480.02255"
+ inkscape:cy="899.69334"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:snap-grids="true"
+ inkscape:snap-to-guides="true"
+ inkscape:window-width="1227"
+ inkscape:window-height="703"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:#030000;fill-opacity:1;stroke:none"
+ d="M 741.60714,4.2812503 387.29464,360.59375 c 1.77274,2.77846 4.88361,4.625 8.4375,4.625 l 49.875,0 300.125,-301.59375 0,-51.25 c 0,-3.3367797 -1.62759,-6.2790897 -4.125,-8.0937497 z M 745.73214,252 l 0,0 z m 0,0 -112.59375,113.21875 84.411,-0.50507 c 14.63138,-0.50508 28.18275,-13.0463 28.18275,-27.1726 l 0,-85.54108 z m -172.28125,113.21875 0,0 z m 0,0 172.28125,-175.27031 0,-63.79219 -237.90625,239.0625 65.625,0 z"
+ id="rect2818"
+ sodipodi:nodetypes="ccccccccccccccccccccc"
+ inkscape:export-filename="/Users/yanastamcheva/workspace/trunk/resources/images/impl/gui/common/windowResizeIcon.png"
+ inkscape:export-xdpi="3.0130775"
+ inkscape:export-ydpi="3.0130775" />
+ </g>
+</svg>
diff --git a/resources/images/impl/gui/common/windowResizeIcon.png b/resources/images/impl/gui/common/windowResizeIcon.png
new file mode 100644
index 0000000..c463535
--- /dev/null
+++ b/resources/images/impl/gui/common/windowResizeIcon.png
Binary files differ
diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties
index 60eaf2a..baf9b19 100644
--- a/resources/languages/resources.properties
+++ b/resources/languages/resources.properties
@@ -390,6 +390,8 @@ service.gui.SET_STATUS_MESSAGE=Set status message
service.gui.SETTINGS=&Options
service.gui.SHARE_DESKTOP=&Share desktop
service.gui.SHARE_DESKTOP_WITH_CONTACT=Share desktop with contact
+service.gui.SHARE_FULL_SCREEN=Share full screen
+service.gui.SHARE_REGION=Share region
service.gui.SHOW=Show
service.gui.SHOW_CONTACT_LIST_TOOL_TIP=Click here to switch off the history view and show your contact list.
service.gui.SHOW_OFFLINE_CONTACTS=Show offline contacts
@@ -399,11 +401,13 @@ service.gui.SMS_SEND_CONNECTION_PROBLEM=You need to be connected before being ab
service.gui.SPECIFY_REASON=In the field below you could specify the reason of this operation.
service.gui.SOUND_OFF=Turn sound off
service.gui.SOUND_ON=Turn sound on
+service.gui.START_SHARING=Start sharing
service.gui.STATUS=Status:
service.gui.STATUS_CHANGED_CHAT_MESSAGE=has become {0}
service.gui.STATUS_CHANGE_GENERAL_ERROR=Failed to change status for account: User name: {0}, Server name: {1}, due to a general error.
service.gui.STATUS_CHANGE_NETWORK_FAILURE=Failed to change status for account: User name: {0}, Server name: {1}, due to a network problem.
service.gui.STATUS_MESSAGE_INFO=In the field below you can specify the new message you would like to use.
+service.gui.STOP_SHARING=Stop sharing
service.gui.SUBJECT=Subject
service.gui.SUMMARY=Summary
service.gui.TODAY=Today
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 47500e5..2c13dc5 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
@@ -8,7 +8,6 @@ package net.java.sip.communicator.impl.gui.main.call;
import java.text.*;
import java.util.*;
-import java.util.List;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
@@ -16,10 +15,12 @@ import net.java.sip.communicator.impl.gui.main.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
+import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.util.swing.transparent.*;
/**
* The <tt>CallManager</tt> is the one that handles calls. It contains also
@@ -315,8 +316,56 @@ public class CallManager
ProtocolProviderService protocolProvider,
String contact)
{
- // Use the default media device corresponding to the screen to share
- createDesktopSharing(protocolProvider, contact, null);
+ // If the user presses cancel on the desktop sharing warning then we
+ // have nothing more to do here.
+ if (!showDesktopSharingWarning())
+ return;
+
+ MediaService mediaService = GuiActivator.getMediaService();
+
+ List<MediaDevice> desktopDevices = mediaService.getDevices(
+ MediaType.VIDEO, MediaUseCase.DESKTOP);
+
+ int deviceNumber = desktopDevices.size();
+
+ if (deviceNumber == 1)
+ {
+ createDesktopSharing(
+ protocolProvider, contact, desktopDevices.get(0));
+ }
+ else if (deviceNumber > 1)
+ {
+ SelectScreenDialog selectDialog
+ = new SelectScreenDialog(desktopDevices);
+
+ selectDialog.setVisible(true);
+
+ createDesktopSharing( protocolProvider,
+ contact,
+ selectDialog.getSelectedDevice());
+ }
+ }
+
+ /**
+ * Creates a region desktop sharing through the given
+ * <tt>protocolProvider</tt> with the given <tt>contact</tt>.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, through
+ * which the sharing session will be established
+ * @param contact the address of the contact recipient
+ */
+ public static void createRegionDesktopSharing(
+ ProtocolProviderService protocolProvider,
+ String contact)
+ {
+ if (showDesktopSharingWarning())
+ {
+ TransparentFrame frame = DesktopSharingFrame.createTransparentFrame(
+ protocolProvider, contact, true);
+
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ }
}
/**
@@ -325,22 +374,64 @@ public class CallManager
*
* @param protocolProvider the protocol provider to which this call belongs.
* @param contact the contact to call to
- * @param mediaDevice the media device corresponding to the screen to share
+ * @param x the x coordinate of the shared region
+ * @param y the y coordinated of the shared region
+ * @param width the width of the shared region
+ * @param height the height of the shared region
*/
- public static void createDesktopSharing(
+ public static void createRegionDesktopSharing(
ProtocolProviderService protocolProvider,
String contact,
- MediaDevice mediaDevice)
+ int x,
+ int y,
+ int width,
+ int height)
{
- if (showDesktopSharingWarning())
+ MediaService mediaService = GuiActivator.getMediaService();
+
+ List<MediaDevice> desktopDevices = mediaService.getDevices(
+ MediaType.VIDEO, MediaUseCase.DESKTOP);
+
+ int deviceNumber = desktopDevices.size();
+
+ if (deviceNumber == 1)
+ {
+ createDesktopSharing(protocolProvider, contact,
+ mediaService.getMediaDeviceForPartialDesktopStreaming(
+ desktopDevices.get(0), width, height, x, y));
+ }
+ else if (deviceNumber > 1)
{
- new CreateDesktopSharingThread( protocolProvider,
- contact,
- mediaDevice).start();
+ SelectScreenDialog selectDialog
+ = new SelectScreenDialog(desktopDevices);
+
+ selectDialog.setVisible(true);
+
+ createDesktopSharing(protocolProvider, contact,
+ mediaService.getMediaDeviceForPartialDesktopStreaming(
+ selectDialog.getSelectedDevice(), width, height, x, y));
}
}
/**
+ * Creates a desktop sharing call to the contact represented by the given
+ * string.
+ *
+ * @param protocolProvider the protocol provider to which this call belongs.
+ * @param contact the contact to call to
+ * @param mediaDevice the media device corresponding to the screen to share
+ */
+ private static void createDesktopSharing(
+ ProtocolProviderService protocolProvider,
+ String contact,
+ MediaDevice mediaDevice)
+ {
+ new CreateDesktopSharingThread( protocolProvider,
+ contact,
+ mediaDevice).start();
+ }
+
+ /**
* Enables the desktop sharing in an existing <tt>call</tt>.
*
* @param call the call for which desktop sharing should be enabled
@@ -349,7 +440,102 @@ public class CallManager
*/
public static void enableDesktopSharing(Call call, boolean enable)
{
- enableDesktopSharing(call, null, enable);
+ if (!enable)
+ enableDesktopSharing(call, null, enable);
+ else if (showDesktopSharingWarning())
+ {
+ MediaService mediaService = GuiActivator.getMediaService();
+
+ List<MediaDevice> desktopDevices = mediaService.getDevices(
+ MediaType.VIDEO, MediaUseCase.DESKTOP);
+
+ int deviceNumber = desktopDevices.size();
+
+ if (deviceNumber == 1)
+ {
+ enableDesktopSharing(call, null, enable);
+ }
+ else if (deviceNumber > 1)
+ {
+ SelectScreenDialog selectDialog
+ = new SelectScreenDialog(desktopDevices);
+
+ selectDialog.setVisible(true);
+
+ enableDesktopSharing(
+ call, selectDialog.getSelectedDevice(), enable);
+ }
+ }
+
+ // in case we switch to video, disable remote control if it was
+ // enabled
+ enableDesktopRemoteControl(call.getCallPeers().next(), false);
+ }
+
+ /**
+ * Enables the region desktop sharing for the given call.
+ *
+ * @param call the call, for which the region desktop sharing should be
+ * enabled
+ * @param enable indicates if the desktop sharing should be enabled or
+ * disabled
+ */
+ public static void enableRegionDesktopSharing(Call call, boolean enable)
+ {
+ if (!enable)
+ enableDesktopSharing(call, null, enable);
+ else if (showDesktopSharingWarning())
+ {
+ TransparentFrame frame
+ = DesktopSharingFrame.createTransparentFrame(call, true);
+
+ frame.setVisible(true);
+ }
+ }
+
+ /**
+ * Creates a desktop sharing call to the contact represented by the given
+ * string.
+ *
+ * @param call the call for which desktop sharing should be enabled
+ * @param x the x coordinate of the shared region
+ * @param y the y coordinated of the shared region
+ * @param width the width of the shared region
+ * @param height the height of the shared region
+ */
+ public static void enableRegionDesktopSharing(
+ Call call,
+ int x,
+ int y,
+ int width,
+ int height)
+ {
+ // Use the default media device corresponding to the screen to share
+ MediaService mediaService = GuiActivator.getMediaService();
+
+ List<MediaDevice> desktopDevices = mediaService.getDevices(
+ MediaType.VIDEO, MediaUseCase.DESKTOP);
+
+ int deviceNumber = desktopDevices.size();
+
+ if (deviceNumber == 1)
+ {
+ enableDesktopSharing(call,
+ mediaService.getMediaDeviceForPartialDesktopStreaming(
+ desktopDevices.get(0), width, height, x, y), true);
+ }
+ else if (deviceNumber > 1)
+ {
+ SelectScreenDialog selectDialog
+ = new SelectScreenDialog(desktopDevices);
+
+ selectDialog.setVisible(true);
+
+ enableDesktopSharing(call,
+ mediaService.getMediaDeviceForPartialDesktopStreaming(
+ selectDialog.getSelectedDevice(), width, height, x, y),
+ true);
+ }
// in case we switch to video, disable remote control if it was
// enabled
@@ -364,7 +550,7 @@ public class CallManager
* @param enable indicates if the desktop sharing should be enabled or
* disabled
*/
- public static void enableDesktopSharing(Call call,
+ private static void enableDesktopSharing(Call call,
MediaDevice mediaDevice,
boolean enable)
{
@@ -383,27 +569,24 @@ public class CallManager
if (enable && isLocalVideoEnabled(call))
enableLocalVideo(call, false);
- if (!enable || showDesktopSharingWarning())
+ try
{
- try
- {
- if (mediaDevice != null)
- desktopOpSet.setLocalVideoAllowed(
- call,
- mediaDevice,
- enable);
- else
- desktopOpSet.setLocalVideoAllowed(
- call,
- enable);
-
- enableSucceeded = true;
- }
- catch (OperationFailedException ex)
- {
- logger.error(
- "Failed to toggle the streaming of local video.", ex);
- }
+ if (mediaDevice != null)
+ desktopOpSet.setLocalVideoAllowed(
+ call,
+ mediaDevice,
+ enable);
+ else
+ desktopOpSet.setLocalVideoAllowed(
+ call,
+ enable);
+
+ enableSucceeded = true;
+ }
+ catch (OperationFailedException ex)
+ {
+ logger.error(
+ "Failed to toggle the streaming of local video.", ex);
}
}
@@ -434,6 +617,28 @@ public class CallManager
}
/**
+ * Indicates if the desktop sharing is currently enabled for the given
+ * <tt>call</tt>.
+ *
+ * @param call the <tt>Call</tt>, for which we would to check if the desktop
+ * sharing is currently enabled
+ * @return <tt>true</tt> if the desktop sharing is currently enabled for the
+ * given <tt>call</tt>, <tt>false</tt> otherwise
+ */
+ public static boolean isRegionDesktopSharingEnabled(Call call)
+ {
+ OperationSetDesktopSharingServer desktopOpSet
+ = call.getProtocolProvider().getOperationSet(
+ OperationSetDesktopSharingServer.class);
+
+ if (desktopOpSet != null
+ && desktopOpSet.isPartialStreaming(call))
+ return true;
+
+ return false;
+ }
+
+ /**
* Enables/disables remote control when in a desktop sharing session with
* the given <tt>callPeer</tt>.
*
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingButton.java b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingButton.java
index 00dc29d..8814f96 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingButton.java
@@ -6,12 +6,13 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
-import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
-import net.java.sip.communicator.service.neomedia.*;
-import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.protocol.*;
/**
@@ -70,23 +71,67 @@ public class DesktopSharingButton
// Otherwise we enable the desktop sharing.
else
{
- MediaService mediaService = GuiActivator.getMediaService();
+ //We'll select the button once the desktop sharing has been
+ // established.
+ setSelected(false);
- List<MediaDevice> desktopDevices = mediaService.getDevices(
- MediaType.VIDEO, MediaUseCase.DESKTOP);
+ JPopupMenu sharingMenu = createDesktopSharingMenu();
- int deviceNumber = desktopDevices.size();
+ Point location = new Point(getX(), getY() + getHeight());
- if (deviceNumber == 1)
- CallManager.enableDesktopSharing(call, true);
- else if (deviceNumber > 1)
- {
- SelectScreenDialog selectDialog
- = new SelectScreenDialog(call, desktopDevices);
+ SwingUtilities.convertPointToScreen(location, getParent());
- selectDialog.setVisible(true);
- }
+ sharingMenu.setLocation(location);
+ sharingMenu.setVisible(true);
}
}
}
+
+ /**
+ * Creates the menu responsible for desktop sharing when a single desktop
+ * sharing contact is available.
+ *
+ * @return the created popup menu
+ */
+ private JPopupMenu createDesktopSharingMenu()
+ {
+ final JPopupMenu popupMenu = new JPopupMenu(
+ GuiActivator.getResources().getI18NString(
+ "service.gui.SHARE_DESKTOP"));
+
+ popupMenu.setInvoker(this);
+ popupMenu.setFocusable(true);
+
+ JMenuItem shareFullScreen = new JMenuItem(GuiActivator.getResources()
+ .getI18NString("service.gui.SHARE_FULL_SCREEN"));
+
+ JMenuItem shareRegion = new JMenuItem(GuiActivator.getResources()
+ .getI18NString("service.gui.SHARE_REGION"));
+
+ shareRegion.setEnabled(false);
+
+ popupMenu.add(shareFullScreen);
+ popupMenu.add(shareRegion);
+
+ shareFullScreen.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ popupMenu.setVisible(false);
+ CallManager.enableDesktopSharing(call, true);
+ }
+ });
+
+ shareRegion.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ popupMenu.setVisible(false);
+
+ CallManager.enableRegionDesktopSharing(call, true);
+ }
+ });
+
+ return popupMenu;
+ }
} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingFrame.java b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingFrame.java
new file mode 100644
index 0000000..19b3788
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/DesktopSharingFrame.java
@@ -0,0 +1,567 @@
+/*
+ * SIP Communicator, 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 java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import java.beans.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.service.neomedia.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.util.swing.*;
+import net.java.sip.communicator.util.swing.transparent.*;
+
+/**
+ *
+ * @author Yana Stamcheva
+ */
+public class DesktopSharingFrame
+{
+ /**
+ * Used for logging.
+ */
+ private static final Logger logger
+ = Logger.getLogger(DesktopSharingFrame.class);
+
+ /**
+ * The icon shown to indicate the resize drag area.
+ */
+ private static final ImageIcon resizeIcon
+ = GuiActivator.getResources().getImage(
+ "service.gui.icons.WINDOW_RESIZE_ICON");
+
+ /**
+ * The indent of the sharing region from the frame.
+ */
+ private static int SHARING_REGION_INDENT = 2;
+
+ /**
+ * The x coordinate of the frame, which started the regional sharing.
+ */
+ private static int initialFrameX = -1;
+
+ /**
+ * The y coordinate of the frame, which started the regional sharing.
+ */
+ private static int initialFrameY = -1;
+
+ /**
+ * The width of the sharing region, which started the sharing.
+ */
+ private static int sharingRegionWidth = -1;
+
+ /**
+ * The height of the sharing region, which started the sharing.
+ */
+ private static int sharingRegionHeight = -1;
+
+ /**
+ * A mapping of a desktop sharing frame created by this class and a call.
+ */
+ private static final Map<Call, JFrame> callDesktopFrames
+ = new Hashtable<Call, JFrame>();
+
+ /**
+ * Creates the transparent desktop sharing frame.
+ *
+ * @param protocolProvider the protocol provider, through which the desktop
+ * sharing will pass
+ * @param contactAddress the address of the contact to call
+ * @param initialFrame indicates if this is the frame which initiates the
+ * desktop sharing
+ * @return the created desktop sharing frame
+ */
+ public static TransparentFrame createTransparentFrame(
+ ProtocolProviderService protocolProvider,
+ String contactAddress,
+ boolean initialFrame)
+ {
+ TransparentFrame frame = TransparentFrame.createTransparentFrame();
+
+ initContentPane(frame, initialFrame);
+
+ JComponent sharingRegion = new TransparentPanel();
+ // The preferred width on MacOSX should be a multiple of 16, that's why
+ // we put 592 as a default width.
+ sharingRegion.setPreferredSize(new Dimension(592, 400));
+
+ frame.getContentPane().add(sharingRegion, BorderLayout.NORTH);
+
+ JPanel buttonPanel = initButtons(
+ frame, sharingRegion, initialFrame, null,
+ protocolProvider, contactAddress);
+
+ frame.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
+ frame.pack();
+
+ return frame;
+ }
+
+ /**
+ * Creates the transparent desktop sharing frame.
+ *
+ * @param call the current call
+ * @param initialFrame indicates if this is the frame which initiates the
+ * desktop sharing
+ * @return the created desktop sharing frame
+ */
+ public static TransparentFrame createTransparentFrame(
+ Call call,
+ boolean initialFrame)
+ {
+ TransparentFrame frame = TransparentFrame.createTransparentFrame();
+
+ initContentPane(frame, initialFrame);
+
+ JComponent sharingRegion = new TransparentPanel();
+ // The preferred width on MacOSX should be a multiple of 16,
+ // that's why we put 592 as a default width.
+ sharingRegion.setPreferredSize(new Dimension(592, 400));
+ frame.getContentPane().add(sharingRegion, BorderLayout.NORTH);
+
+ JPanel buttonPanel = initButtons(
+ frame, sharingRegion, initialFrame, call, null, null);
+
+ frame.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
+
+ // If the desktop sharing has started we store the frame to call mapping.
+ if (!initialFrame)
+ {
+ callDesktopFrames.put(call, frame);
+ addCallListener(call, frame);
+ addFrameListener(call, frame, sharingRegion);
+ addDesktopSharingListener(call, frame);
+
+ logger.info("The sharing region width: " + sharingRegionWidth);
+
+ if (sharingRegionWidth > -1 && sharingRegionHeight > -1)
+ sharingRegion.setPreferredSize(
+ new Dimension(sharingRegionWidth, sharingRegionHeight));
+
+ frame.pack();
+
+ if (initialFrameX > -1 && initialFrameY > -1)
+ frame.setLocation(initialFrameX, initialFrameY);
+ else
+ // By default we position the frame in the center of the screen.
+ // It's important to call this method after the pack(), because
+ // it requires the frame size to calculate the location.
+ frame.setLocationRelativeTo(null);
+ }
+ else
+ {
+ frame.pack();
+
+ // By default we position the frame in the center of the screen.
+ // It's important to call this method after the pack(), because
+ // it requires the frame size to calculate the location.
+ frame.setLocationRelativeTo(null);
+ }
+
+ return frame;
+ }
+
+ /**
+ * Adds a call listener, which listens for call ended events and would
+ * close any related desktop sharing frames when a call is ended.
+ *
+ * @param call the call, for which we're registering a listener
+ * @param frame the frame to be closed on call ended
+ */
+ private static void addCallListener(Call call, JFrame frame)
+ {
+ OperationSetBasicTelephony telOpSet = call.getProtocolProvider()
+ .getOperationSet(OperationSetBasicTelephony.class);
+
+ if (telOpSet != null) // This should be always true.
+ {
+ telOpSet.addCallListener(new CallListener()
+ {
+ /**
+ * Implements CallListener.callEnded. Disposes the frame
+ * related to the ended call.
+ *
+ * @param event the <tt>CallEvent</tt> that notified us
+ */
+ public void callEnded(CallEvent event)
+ {
+ Call call = event.getSourceCall();
+ JFrame desktopFrame = callDesktopFrames.get(call);
+
+ if (desktopFrame != null)
+ {
+ desktopFrame.dispose();
+ callDesktopFrames.remove(call);
+ }
+ }
+
+ public void incomingCallReceived(CallEvent event) {}
+
+ public void outgoingCallCreated(CallEvent event) {}
+ });
+ }
+ }
+
+ /**
+ * Adds the desktop sharing listener.
+ *
+ * @param call the call, for which we're registering a listener
+ * @param frame the frame to be closed on call ended
+ */
+ private static void addDesktopSharingListener(final Call call, JFrame frame)
+ {
+ OperationSetVideoTelephony videoOpSet =
+ call.getProtocolProvider()
+ .getOperationSet(OperationSetVideoTelephony.class);
+
+ videoOpSet.addPropertyChangeListener(call, new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ if (OperationSetVideoTelephony.LOCAL_VIDEO_STREAMING
+ .equals(evt.getPropertyName())
+ && evt.getNewValue().equals(MediaDirection.RECVONLY))
+ {
+ JFrame desktopFrame = callDesktopFrames.get(call);
+
+ if (desktopFrame != null)
+ {
+ desktopFrame.dispose();
+ callDesktopFrames.remove(call);
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Initializes the content pane of the given window.
+ *
+ * @param frame the parent frame
+ * @param initialFrame indicates if this is the frame which initiates the
+ * desktop sharing
+ */
+ private static void initContentPane(JFrame frame, boolean initialFrame)
+ {
+ JPanel contentPane = new JPanel()
+ {
+ protected void paintComponent(Graphics g)
+ {
+ if (TransparentFrame.isTranslucencySupported)
+ {
+ AntialiasingManager.activateAntialiasing(g);
+ final int R = 240;
+ final int G = 240;
+ final int B = 240;
+
+ Paint p =
+ new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0),
+ getWidth(), getHeight(), new Color(R, G, B, 0), true);
+ Graphics2D g2d = (Graphics2D)g;
+ g2d.setPaint(p);
+ g2d.fillRect(0, 0, getWidth(), getHeight());
+ g2d.setColor(new Color( Color.DARK_GRAY.getRed(),
+ Color.DARK_GRAY.getGreen(),
+ Color.DARK_GRAY.getBlue(), 180));
+ g2d.setStroke(
+ new BasicStroke((float) 4));
+ g2d.drawRoundRect(
+ 0, 0, getWidth() - 1, getHeight() - 1, 20, 20);
+ }
+ else
+ {
+ super.paintComponent(g);
+ }
+ }
+ };
+
+ contentPane.setOpaque(false);
+ contentPane.setDoubleBuffered(false);
+ contentPane.setLayout(new BorderLayout());
+ contentPane.setBorder(BorderFactory.createEmptyBorder(
+ SHARING_REGION_INDENT, SHARING_REGION_INDENT,
+ SHARING_REGION_INDENT, SHARING_REGION_INDENT));
+
+ frame.setContentPane(contentPane);
+
+ if (TransparentFrame.isTranslucencySupported)
+ frame.setAlwaysOnTop(true);
+ }
+
+ /**
+ * Creates and initializes the button panel.
+ *
+ * @param frame the parent frame
+ * @param sharingRegion the sharing region component
+ * @param initialFrame indicates if this is the frame which initiates the
+ * desktop sharing
+ * @param call the current call, if we're in a call
+ * @param protocolProvider the protocol provider
+ * @param contact the contact, which is the receiver of the call
+ *
+ * @return the created button panel
+ */
+ private static JPanel initButtons(
+ final JFrame frame,
+ final JComponent sharingRegion,
+ boolean initialFrame,
+ final Call call,
+ final ProtocolProviderService protocolProvider,
+ final String contact)
+ {
+ JPanel buttonPanel = new TransparentPanel(new GridBagLayout())
+ {
+ public void paintComponent(Graphics g)
+ {
+ if (!TransparentFrame.isTranslucencySupported)
+ {
+ super.paintComponent(g);
+ return;
+ }
+
+ Graphics2D g2d = (Graphics2D) g.create();
+
+ AntialiasingManager.activateAntialiasing(g2d);
+
+ g2d.setColor(new Color( Color.DARK_GRAY.getRed(),
+ Color.DARK_GRAY.getGreen(),
+ Color.DARK_GRAY.getBlue(), 180));
+
+ GeneralPath shape = new GeneralPath();
+ int x = -SHARING_REGION_INDENT + 2;
+ int y = 0;
+ int width = getWidth() + SHARING_REGION_INDENT*2 - 4;
+ int height = getHeight() + SHARING_REGION_INDENT*2 - 2;
+
+ shape.moveTo(x, y);
+ shape.lineTo(width, y);
+ shape.lineTo(width, height - 12);
+ shape.curveTo(width, height - 12,
+ width, height,
+ width - 12, height);
+ shape.lineTo(12, height);
+ shape.curveTo(12, height,
+ x, height,
+ x, height - 12);
+ shape.lineTo(x, y);
+ shape.closePath();
+
+ g2d.fill(shape);
+ g2d.setColor(getBackground());
+ }
+ };
+
+ GridBagConstraints constraints = new GridBagConstraints();
+
+ buttonPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ buttonPanel.setPreferredSize(
+ new Dimension(sharingRegion.getWidth(), 30));
+
+ if (initialFrame)
+ {
+ JButton startButton = createButton(
+ GuiActivator.getResources()
+ .getI18NString("service.gui.START_SHARING"));
+
+ JButton cancelButton = createButton(
+ GuiActivator.getResources()
+ .getI18NString("service.gui.CANCEL"));
+
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.weightx = 1.0;
+ constraints.insets = new Insets(0, 0, 0, 5);
+ constraints.anchor = GridBagConstraints.EAST;
+ buttonPanel.add(cancelButton, constraints);
+
+ constraints.gridx = 1;
+ constraints.gridy = 0;
+ constraints.weightx = 1.0;
+ constraints.anchor = GridBagConstraints.WEST;
+ buttonPanel.add(startButton, constraints);
+
+ constraints.gridx = 3;
+ constraints.gridy = 0;
+ constraints.weightx = 0;
+ constraints.insets = new Insets(0, 0, 2, 2);
+ constraints.anchor = GridBagConstraints.SOUTHWEST;
+ buttonPanel.add(
+ createResizeLabel(frame, sharingRegion, buttonPanel),
+ constraints);
+
+ startButton.setCursor(Cursor.getDefaultCursor());
+ cancelButton.setCursor(Cursor.getDefaultCursor());
+
+ cancelButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent arg0)
+ {
+ frame.dispose();
+ }
+ });
+
+ startButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ Point location = sharingRegion.getLocationOnScreen();
+
+ initialFrameX = frame.getX();
+ initialFrameY = frame.getY();
+ sharingRegionWidth = sharingRegion.getWidth();
+ sharingRegionHeight = sharingRegion.getHeight();
+
+ frame.dispose();
+
+ if (call != null)
+ CallManager.enableRegionDesktopSharing(
+ call, location.x, location.y,
+ sharingRegionWidth, sharingRegionHeight);
+ else
+ CallManager.createRegionDesktopSharing(
+ protocolProvider, contact,
+ location.x, location.y,
+ sharingRegionWidth, sharingRegionHeight);
+ }
+ });
+ }
+ else
+ {
+ JButton stopButton = createButton(
+ GuiActivator.getResources()
+ .getI18NString("service.gui.STOP_SHARING"));
+
+ buttonPanel.add(stopButton);
+
+ stopButton.setCursor(Cursor.getDefaultCursor());
+
+ stopButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ if (call != null)
+ CallManager.enableDesktopSharing(call, false);
+
+ frame.dispose();
+ }
+ });
+ }
+
+ return buttonPanel;
+ }
+
+ /**
+ * Creates a button with the given text.
+ *
+ * @param text the text of the button
+ * @return the created button
+ */
+ private static JButton createButton(String text)
+ {
+ JButton button = new JButton(text);
+
+ button.setOpaque(false);
+
+ return button;
+ }
+
+ /**
+ * Creates the label allowing to resize the given frame.
+ *
+ * @param frame the frame to resize
+ * @param sharingRegion the sharing region
+ * @param buttonPanel the button panel, where the created label would be
+ * added
+ * @return the created resize label
+ */
+ private static JLabel createResizeLabel(final JFrame frame,
+ final JComponent sharingRegion,
+ final JComponent buttonPanel)
+ {
+ final JLabel resizeLabel = new JLabel(resizeIcon);
+ resizeLabel.addMouseMotionListener(new MouseMotionAdapter()
+ {
+ public void mouseDragged(MouseEvent e)
+ {
+ Point p = e.getLocationOnScreen();
+ Point regionLocation = sharingRegion.getLocationOnScreen();
+
+ int sharingWidth = (int) ( p.getX()
+ - regionLocation.getX()
+ - 2*SHARING_REGION_INDENT);
+
+ int newSharingHeight = (int) (p.getY()
+ - frame.getY()
+ - buttonPanel.getHeight()
+ - 2*SHARING_REGION_INDENT);
+
+ // We should make sure that the width on MacOSX is a multiple
+ // of 16.
+ if (OSUtils.IS_MAC && sharingWidth%16 > 0)
+ sharingWidth = sharingWidth - sharingWidth%16;
+
+ sharingRegion.setPreferredSize(
+ new Dimension(sharingWidth, newSharingHeight));
+
+ frame.validate();
+
+ int height = (int) (p.getY() - frame.getY());
+
+ frame.setSize(sharingWidth + 2*SHARING_REGION_INDENT, height);
+ }
+ });
+
+ return resizeLabel;
+ }
+
+ /**
+ * Adds a listener for the given frame and call
+ *
+ * @param call the underlying call
+ * @param frame the frame to which the listener would be added
+ * @param sharingRegion the sharing region
+ */
+ private static void addFrameListener( final Call call,
+ final JFrame frame,
+ final Component sharingRegion)
+ {
+ frame.addComponentListener(new ComponentListener()
+ {
+ public void componentResized(ComponentEvent e) {}
+
+ public void componentMoved(ComponentEvent e)
+ {
+ OperationSetDesktopSharingServer desktopOpSet
+ = call.getProtocolProvider().getOperationSet(
+ OperationSetDesktopSharingServer.class);
+
+ if (desktopOpSet == null)
+ return;
+
+ Point location = new Point( sharingRegion.getX(),
+ sharingRegion.getY());
+
+ SwingUtilities.convertPointToScreen(location,
+ frame.getContentPane());
+
+ desktopOpSet.movePartialDesktopStreaming(
+ call, location.x, location.y);
+ }
+
+ public void componentShown(ComponentEvent e) {}
+
+ public void componentHidden(ComponentEvent arg0) {}
+ });
+ }
+}
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 a3e9b79..a5d58bc 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
@@ -26,6 +26,7 @@ import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.skin.*;
import net.java.sip.communicator.util.swing.*;
+import net.java.sip.communicator.util.swing.transparent.*;
/**
* The <tt>OneToOneCallPeerPanel</tt> is the panel containing data for a call
@@ -488,6 +489,15 @@ public class OneToOneCallPeerPanel
if (CallManager.isDesktopSharingEnabled(call))
{
callContainer.setDesktopSharingButtonSelected(true);
+
+ if (CallManager.isRegionDesktopSharingEnabled(call))
+ {
+ TransparentFrame frame
+ = DesktopSharingFrame.createTransparentFrame(
+ call, false);
+
+ frame.setVisible(true);
+ }
}
else if (CallManager.isLocalVideoEnabled(call))
{
@@ -1595,24 +1605,12 @@ public class OneToOneCallPeerPanel
}
}
- /**
- * {@inheritDoc}
- */
public void mouseMoved(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mouseClicked(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mouseEntered(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mouseExited(MouseEvent event) {}
/**
@@ -1643,34 +1641,20 @@ public class OneToOneCallPeerPanel
if (!closeButton.isVisible())
{
Component c = (Component) event.getSource();
- closeButton.setLocation(
- c.getX() + c.getWidth() - closeButton.getWidth() - 3,
+ closeButton.setLocation(
+ c.getX() + c.getWidth() - closeButton.getWidth() - 3,
c.getY() + 3);
closeButton.setVisible(true);
}
}
}
- /**
- * The local video close button.
- */
private class CloseButton
extends Label
implements MouseListener
{
- /**
- * Serial version UID.
- */
- private static final long serialVersionUID = 0L;
-
- /**
- * Background image.
- */
Image image = ImageLoader.getImage(ImageLoader.CLOSE_VIDEO);
- /**
- * Constructor.
- */
public CloseButton()
{
int buttonWidth = image.getWidth(this) + 5;
@@ -1682,9 +1666,6 @@ public class OneToOneCallPeerPanel
this.addMouseListener(this);
}
- /**
- * {@inheritDoc}
- */
public void paint(Graphics g)
{
g.setColor(Color.GRAY);
@@ -1694,9 +1675,6 @@ public class OneToOneCallPeerPanel
getHeight()/2 - image.getHeight(this)/2, this);
}
- /**
- * {@inheritDoc}
- */
public void mouseClicked(MouseEvent event)
{
setLocalVideoVisible(false);
@@ -1705,24 +1683,12 @@ public class OneToOneCallPeerPanel
.setShowHideVideoButtonSelected(false);
}
- /**
- * {@inheritDoc}
- */
public void mouseEntered(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mouseExited(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mousePressed(MouseEvent event) {}
- /**
- * {@inheritDoc}
- */
public void mouseReleased(MouseEvent event) {}
}
@@ -1781,19 +1747,6 @@ public class OneToOneCallPeerPanel
.setShowHideVideoButtonSelected(isVisible);
}
- if(localVideo == null && isVisible)
- {
- /* create local visual component if not already created */
- try
- {
- videoTelephony.createLocalVisualComponent(callPeer,
- null);
- }
- catch(OperationFailedException e)
- {
- }
- }
-
int videoContainerCount;
if ((videoTelephony != null)
@@ -1804,12 +1757,28 @@ public class OneToOneCallPeerPanel
if (localVideo != null)
{
- videoContainer.remove(localVideo);
- videoContainer.remove(closeButton);
- /* release resources */
- videoTelephony.disposeLocalVisualComponent(callPeer,
- localVideo);
- localVideo = null;
+ if (isVisible)
+ {
+ Container parent = localVideo.getParent();
+
+ if (parent != null)
+ {
+ parent.remove(parent);
+ parent.remove(closeButton);
+ }
+
+ videoContainer.add(
+ closeButton, VideoLayout.CLOSE_LOCAL_BUTTON, 0);
+ videoContainer.add(localVideo, VideoLayout.LOCAL, 1);
+ }
+ else
+ {
+ if (localVideo != null)
+ {
+ videoContainer.remove(localVideo);
+ videoContainer.remove(closeButton);
+ }
+ }
}
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
index 3951e15..2f05509 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/SelectScreenDialog.java
@@ -17,7 +17,6 @@ import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
import net.java.sip.communicator.service.neomedia.format.*;
-import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
@@ -65,54 +64,9 @@ public class SelectScreenDialog
private static MediaDevice videoDeviceInPreview;
/**
- * The parent call for which the screen is selected, if any.
+ * The selected media device.
*/
- private Call call;
-
- /**
- * The protocol provider through which we make the sharing.
- */
- private ProtocolProviderService protocolProvider;
-
- /**
- * The contact with which we'd like to share our desktop.
- */
- private String contact;
-
- /**
- * Creates an instance of <tt>SelectScreenDialog</tt> by specifying the list
- * of possible desktop devices to choose from.
- *
- * @param call the call, for which screen for desktop sharing is selected
- * @param desktopDevices the list of possible desktop devices to choose
- * from
- */
- public SelectScreenDialog(Call call, List<MediaDevice> desktopDevices)
- {
- this(desktopDevices);
-
- this.call = call;
- }
-
- /**
- * Creates an instance of <tt>SelectScreenDialog</tt> by specifying the list
- * of possible desktop devices to choose from.
- *
- * @param protocolProvider the protocol provider through which we make the
- * sharing
- * @param contact the contact to share the desktop with
- * @param desktopDevices the list of possible desktop devices to choose
- * from
- */
- public SelectScreenDialog( ProtocolProviderService protocolProvider,
- String contact,
- List<MediaDevice> desktopDevices)
- {
- this(desktopDevices);
-
- this.protocolProvider = protocolProvider;
- this.contact = contact;
- }
+ private MediaDevice selectedDevice;
/**
* Creates an instance of <tt>SelectScreenDialog</tt> by specifying the list
@@ -123,6 +77,8 @@ public class SelectScreenDialog
*/
public SelectScreenDialog(List<MediaDevice> desktopDevices)
{
+ setModal(true);
+
setPreferredSize(new Dimension(400, 300));
Container contentPane = getContentPane();
@@ -139,6 +95,16 @@ public class SelectScreenDialog
}
/**
+ * Returns the selected device.
+ *
+ * @return the selected device
+ */
+ public MediaDevice getSelectedDevice()
+ {
+ return selectedDevice;
+ }
+
+ /**
* Creates the buttons panel.
*
* @return the buttons panel
@@ -155,17 +121,10 @@ public class SelectScreenDialog
{
public void actionPerformed(ActionEvent e)
{
- MediaDevice selectedDevice
+ selectedDevice
= (MediaDevice) deviceComboBox.getSelectedItem();
dispose();
-
- if (call != null)
- CallManager.enableDesktopSharing(call, selectedDevice, true);
- else
- CallManager.createDesktopSharing( protocolProvider,
- contact,
- selectedDevice);
}
});
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
index 7b3a311..05a8aec 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
@@ -1161,24 +1161,7 @@ public class ContactListTreeCellRenderer
private void shareDesktop( ProtocolProviderService protocolProvider,
String contactName)
{
- MediaService mediaService = GuiActivator.getMediaService();
-
- List<MediaDevice> desktopDevices = mediaService.getDevices(
- MediaType.VIDEO, MediaUseCase.DESKTOP);
-
- int deviceNumber = desktopDevices.size();
-
- if (deviceNumber == 1)
- CallManager.createDesktopSharing(protocolProvider, contactName);
- else if (deviceNumber > 1)
- {
- SelectScreenDialog selectDialog
- = new SelectScreenDialog( protocolProvider,
- contactName,
- desktopDevices);
-
- selectDialog.setVisible(true);
- }
+ CallManager.createDesktopSharing(protocolProvider, contactName);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactRightButtonMenu.java
index b0cf7c4..e8edc65 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactRightButtonMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactRightButtonMenu.java
@@ -122,18 +122,28 @@ public class MetaContactRightButtonMenu
"service.gui.VIDEO_CALL"));
/**
- * The desktop sharing menu item.
+ * The menu responsible for desktop sharing when a single desktop sharing
+ * contact is available.
*/
- private final JMenuItem desktopSharingItem = new JMenuItem(
+ private final SIPCommMenu contactDesktopSharingMenu = new SIPCommMenu(
GuiActivator.getResources().getI18NString(
"service.gui.SHARE_DESKTOP"));
/**
- * The menu responsible for calling a contact with video.
+ * The menu responsible for full screen sharing when more than one contact
+ * is available for sharing.
*/
- private final SIPCommMenu desktopSharingMenu = new SIPCommMenu(
+ private final SIPCommMenu multiContactFullShareMenu = new SIPCommMenu(
GuiActivator.getResources().getI18NString(
- "service.gui.SHARE_DESKTOP"));
+ "service.gui.SHARE_FULL_SCREEN"));
+
+ /**
+ * The menu responsible for region screen sharing when more than one contact
+ * is available for sharing.
+ */
+ private final SIPCommMenu multiContactRegionShareMenu = new SIPCommMenu(
+ GuiActivator.getResources().getI18NString(
+ "service.gui.SHARE_REGION"));
/**
* The send message menu item.
@@ -201,9 +211,14 @@ public class MetaContactRightButtonMenu
private static final String videoCallPrefix = "videoCall:";
/**
- * The prefix for video call contact menu.
+ * The prefix for full screen desktop sharing menu.
*/
- private static final String desktopSharingPrefix = "desktopSharing:";
+ private static final String fullDesktopSharingPrefix = "shareFullScreen:";
+
+ /**
+ * The prefix for region screen desktop sharing menu.
+ */
+ private static final String regionDesktopSharingPrefix = "shareRegionScreen:";
/**
* The contact to move when the move menu has been chosen.
@@ -367,9 +382,16 @@ public class MetaContactRightButtonMenu
hasContactCapabilities(contact,
OperationSetDesktopSharingServer.class))
{
- desktopSharingMenu.add(
+ multiContactFullShareMenu.add(
createMenuItem( contactDisplayName,
- desktopSharingPrefix
+ fullDesktopSharingPrefix
+ + contact.getAddress()
+ + protocolProvider.getProtocolName(),
+ protocolIcon));
+
+ multiContactRegionShareMenu.add(
+ createMenuItem( contactDisplayName,
+ regionDesktopSharingPrefix
+ contact.getAddress()
+ protocolProvider.getProtocolName(),
protocolIcon));
@@ -402,54 +424,69 @@ public class MetaContactRightButtonMenu
this.videoCallItem.addActionListener(this);
}
- if (desktopSharingMenu.getItemCount() > 1)
+ if (multiContactFullShareMenu.getItemCount() > 1)
{
- this.add(desktopSharingMenu);
+ add(multiContactFullShareMenu);
+ add(multiContactRegionShareMenu);
+
+ multiContactRegionShareMenu.setEnabled(false);
}
else
{
- this.add(desktopSharingItem);
- this.desktopSharingItem.setName("desktopSharing");
- this.desktopSharingItem.addActionListener(this);
+ // Create desktop sharing menu.
+ contactDesktopSharingMenu.add(
+ createMenuItem( GuiActivator.getResources()
+ .getI18NString("service.gui.SHARE_FULL_SCREEN"),
+ "shareFullScreen",
+ null));
+
+ JMenuItem menuItem = createMenuItem( GuiActivator.getResources()
+ .getI18NString("service.gui.SHARE_REGION"),
+ "shareRegion",
+ null);
+ menuItem.setEnabled(false);
+ contactDesktopSharingMenu.add(menuItem);
+
+ add(contactDesktopSharingMenu);
}
- this.add(sendFileItem);
+ add(sendFileItem);
- this.addSeparator();
+ addSeparator();
- this.add(moveToMenu);
- this.add(moveSubcontactMenu);
+ add(moveToMenu);
+ add(moveSubcontactMenu);
- this.addSeparator();
+ addSeparator();
- this.add(addContactItem);
+ add(addContactItem);
- this.addSeparator();
+ addSeparator();
- this.add(removeContactMenu);
- this.add(renameContactItem);
+ add(removeContactMenu);
+ add(renameContactItem);
- this.addSeparator();
+ addSeparator();
- this.add(viewHistoryItem);
+ add(viewHistoryItem);
- this.initPluginComponents();
+ initPluginComponents();
- this.sendMessageItem.setName("sendMessage");
+ sendMessageItem.setName("sendMessage");
- this.sendSmsItem.setName("sendSms");
- this.sendFileItem.setName("sendFile");
- this.moveToMenu.setName("moveToGroup");
- this.addContactItem.setName("addContact");
- this.renameContactItem.setName("renameContact");
- this.viewHistoryItem.setName("viewHistory");
+ sendSmsItem.setName("sendSms");
+ sendFileItem.setName("sendFile");
+ moveToMenu.setName("moveToGroup");
+ addContactItem.setName("addContact");
+ renameContactItem.setName("renameContact");
+ viewHistoryItem.setName("viewHistory");
- this.sendMessageItem.addActionListener(this);
- this.sendSmsItem.addActionListener(this);
- this.sendFileItem.addActionListener(this);
- this.renameContactItem.addActionListener(this);
- this.viewHistoryItem.addActionListener(this);
- this.addContactItem.addActionListener(this);
+ sendMessageItem.addActionListener(this);
+ sendSmsItem.addActionListener(this);
+ sendFileItem.addActionListener(this);
+ renameContactItem.addActionListener(this);
+ viewHistoryItem.addActionListener(this);
+ addContactItem.addActionListener(this);
// Disable all menu items that do nothing.
if (metaContact.getDefaultContact(
@@ -466,7 +503,7 @@ public class MetaContactRightButtonMenu
if (metaContact.getDefaultContact(
OperationSetDesktopSharingServer.class) == null)
- this.desktopSharingItem.setEnabled(false);
+ this.contactDesktopSharingMenu.setEnabled(false);
if (metaContact.getDefaultContact(
OperationSetBasicInstantMessaging.class) == null)
@@ -577,13 +614,13 @@ public class MetaContactRightButtonMenu
char desktopSharingMnemonic = GuiActivator.getResources()
.getI18nMnemonic("service.gui.SHARE_DESKTOP");
- if (desktopSharingMenu.getItemCount() > 1)
+ if (contactDesktopSharingMenu.getItemCount() > 1)
{
- this.desktopSharingMenu.setMnemonic(desktopSharingMnemonic);
+ this.contactDesktopSharingMenu.setMnemonic(desktopSharingMnemonic);
}
else
{
- this.desktopSharingItem.setMnemonic(desktopSharingMnemonic);
+ this.contactDesktopSharingMenu.setMnemonic(desktopSharingMnemonic);
}
this.sendSmsItem.setMnemonic(GuiActivator.getResources()
.getI18nMnemonic("service.gui.SEND_SMS"));
@@ -650,7 +687,7 @@ public class MetaContactRightButtonMenu
CallManager.createVideoCall(
contact.getProtocolProvider(), contact.getAddress());
}
- else if (itemName.equals("desktopSharing"))
+ else if (itemName.equals("shareFullScreen"))
{
contact = metaContact.getDefaultContact(
OperationSetVideoTelephony.class);
@@ -658,6 +695,14 @@ public class MetaContactRightButtonMenu
CallManager.createDesktopSharing(
contact.getProtocolProvider(), contact.getAddress());
}
+ else if (itemName.equals("shareRegion"))
+ {
+ contact = metaContact.getDefaultContact(
+ OperationSetVideoTelephony.class);
+
+ CallManager.createRegionDesktopSharing(
+ contact.getProtocolProvider(), contact.getAddress());
+ }
else if (itemName.equals("sendFile"))
{
SipCommFileChooser scfc = GenericFileDialog.create(
@@ -791,14 +836,23 @@ public class MetaContactRightButtonMenu
CallManager.createVideoCall(contact.getProtocolProvider(),
contact.getAddress());
}
- else if (itemName.startsWith(desktopSharingPrefix))
+ else if (itemName.startsWith(fullDesktopSharingPrefix))
{
contact = getContactFromMetaContact(
- itemName.substring(desktopSharingPrefix.length()));
+ itemName.substring(fullDesktopSharingPrefix.length()));
CallManager.createDesktopSharing( contact.getProtocolProvider(),
contact.getAddress());
}
+ else if (itemName.startsWith(regionDesktopSharingPrefix))
+ {
+ contact = getContactFromMetaContact(
+ itemName.substring(regionDesktopSharingPrefix.length()));
+
+ CallManager.createRegionDesktopSharing(
+ contact.getProtocolProvider(),
+ contact.getAddress());
+ }
}
/**
@@ -993,7 +1047,7 @@ public class MetaContactRightButtonMenu
videoCallItem.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.VIDEO_CALL)));
- desktopSharingItem.setIcon(new ImageIcon(
+ contactDesktopSharingMenu.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.DESKTOP_SHARING)));
sendMessageItem.setIcon(new ImageIcon(
diff --git a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
index 3ea66ea..e7a8922 100644
--- a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
+++ b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf
@@ -42,6 +42,7 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.util.swing.event,
net.java.sip.communicator.util.swing.plaf,
net.java.sip.communicator.util.skin,
+ net.java.sip.communicator.util.swing.transparent,
javax.accessibility,
javax.imageio,
javax.swing,
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index d24078b..aa1d72b 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -905,6 +905,12 @@ public class ImageLoader
public static final ImageID VOLUME_CONTROL_BUTTON
= new ImageID("service.gui.buttons.VOLUME_CONTROL");
+ /**
+ * The transparent window button background.
+ */
+ public static final ImageID TRANSPARENT_WINDOW_BUTTON
+ = new ImageID("service.gui.buttons.TRANSPARENT_WINDOW_BUTTON");
+
/*
* =======================================================================
* ------------------------ EDIT TOOLBAR ICONS ---------------------------
diff --git a/src/net/java/sip/communicator/util/swing/transparent/AWTUtilitiesWrapper.java b/src/net/java/sip/communicator/util/swing/transparent/AWTUtilitiesWrapper.java
new file mode 100644
index 0000000..2967ddd
--- /dev/null
+++ b/src/net/java/sip/communicator/util/swing/transparent/AWTUtilitiesWrapper.java
@@ -0,0 +1,170 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ *
+ * Based on the code of Anthony Petrov
+ * http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/
+ */
+package net.java.sip.communicator.util.swing.transparent;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.Shape;
+import java.awt.Window;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Yana Stamcheva
+ */
+public class AWTUtilitiesWrapper
+{
+ private static Class<?> awtUtilitiesClass;
+ private static Class<?> translucencyClass;
+ private static Method mIsTranslucencySupported, mIsTranslucencyCapable,
+ mSetWindowShape, mSetWindowOpacity, mSetWindowOpaque;
+
+ public static Object PERPIXEL_TRANSPARENT, TRANSLUCENT, PERPIXEL_TRANSLUCENT;
+
+ static void init()
+ {
+ try
+ {
+ awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
+ translucencyClass
+ = Class.forName("com.sun.awt.AWTUtilities$Translucency");
+
+ if (translucencyClass.isEnum())
+ {
+ Object[] kinds = translucencyClass.getEnumConstants();
+ if (kinds != null)
+ {
+ PERPIXEL_TRANSPARENT = kinds[0];
+ TRANSLUCENT = kinds[1];
+ PERPIXEL_TRANSLUCENT = kinds[2];
+ }
+ }
+ mIsTranslucencySupported = awtUtilitiesClass.getMethod(
+ "isTranslucencySupported", translucencyClass);
+ mIsTranslucencyCapable = awtUtilitiesClass.getMethod(
+ "isTranslucencyCapable", GraphicsConfiguration.class);
+ mSetWindowShape = awtUtilitiesClass.getMethod(
+ "setWindowShape", Window.class, Shape.class);
+ mSetWindowOpacity = awtUtilitiesClass.getMethod(
+ "setWindowOpacity", Window.class, float.class);
+ mSetWindowOpaque = awtUtilitiesClass.getMethod(
+ "setWindowOpaque", Window.class, boolean.class);
+ }
+ catch (NoSuchMethodException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (SecurityException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ }
+
+ static
+ {
+ init();
+ }
+
+ private static boolean isSupported(Method method, Object kind)
+ {
+ if (awtUtilitiesClass == null || method == null)
+ {
+ return false;
+ }
+ try
+ {
+ Object ret = method.invoke(null, kind);
+ if (ret instanceof Boolean)
+ {
+ return ((Boolean)ret).booleanValue();
+ }
+ }
+ catch (IllegalAccessException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (InvocationTargetException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ return false;
+ }
+
+ public static boolean isTranslucencySupported(Object kind)
+ {
+ if (translucencyClass == null)
+ return false;
+
+ return isSupported(mIsTranslucencySupported, kind);
+ }
+
+ public static boolean isTranslucencyCapable(GraphicsConfiguration gc)
+ {
+ return isSupported(mIsTranslucencyCapable, gc);
+ }
+
+ private static void set(Method method, Window window, Object value)
+ {
+ if (awtUtilitiesClass == null || method == null)
+ {
+ return;
+ }
+ try
+ {
+ method.invoke(null, window, value);
+ }
+ catch (IllegalAccessException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (IllegalArgumentException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ catch (InvocationTargetException ex)
+ {
+ Logger.getLogger(AWTUtilitiesWrapper.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public static void setWindowShape(Window window, Shape shape)
+ {
+ set(mSetWindowShape, window, shape);
+ }
+
+ public static void setWindowOpacity(Window window, float opacity)
+ {
+ set(mSetWindowOpacity, window, Float.valueOf(opacity));
+ }
+
+ public static void setWindowOpaque(Window window, boolean opaque)
+ {
+ set(mSetWindowOpaque, window, Boolean.valueOf(opaque));
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/util/swing/transparent/TransparentFrame.java b/src/net/java/sip/communicator/util/swing/transparent/TransparentFrame.java
new file mode 100644
index 0000000..f12916e
--- /dev/null
+++ b/src/net/java/sip/communicator/util/swing/transparent/TransparentFrame.java
@@ -0,0 +1,82 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.util.swing.transparent;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+/**
+ *
+ * @author Yana Stamcheva
+ */
+public class TransparentFrame
+ extends JFrame
+ implements RootPaneContainer
+{
+ /**
+ * Indicates if the transparency is supported from the current graphics
+ * environment.
+ */
+ public static boolean isTranslucencySupported;
+
+ /**
+ * Creates a transparent undecorated frame. If the transparency is not
+ * supported creates a normal undecorated frame.
+ *
+ * @return the created frame
+ */
+ public static TransparentFrame createTransparentFrame()
+ {
+ isTranslucencySupported
+ = AWTUtilitiesWrapper.isTranslucencySupported(
+ AWTUtilitiesWrapper.PERPIXEL_TRANSLUCENT);
+
+ GraphicsConfiguration translucencyCapableGC
+ = GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ if (!AWTUtilitiesWrapper.isTranslucencyCapable(translucencyCapableGC))
+ {
+ translucencyCapableGC = null;
+
+ GraphicsEnvironment env
+ = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice[] devices = env.getScreenDevices();
+
+ for (int i = 0; i < devices.length
+ && translucencyCapableGC == null; i++)
+ {
+ GraphicsConfiguration[] configs = devices[i].getConfigurations();
+ for (int j = 0; j < configs.length
+ && translucencyCapableGC == null; j++)
+ {
+ if (AWTUtilitiesWrapper.isTranslucencyCapable(configs[j]))
+ {
+ translucencyCapableGC = configs[j];
+ }
+ }
+ }
+ if (translucencyCapableGC == null)
+ {
+ isTranslucencySupported = false;
+ }
+ }
+
+ return new TransparentFrame(translucencyCapableGC);
+ }
+
+ /** Creates new form FancyFrame */
+ private TransparentFrame(GraphicsConfiguration gc)
+ {
+ super(gc);
+
+ setUndecorated(true);
+ AWTUtilitiesWrapper.setWindowOpaque(this, false);
+ AWTUtilitiesWrapper.setWindowOpacity(this, 1f);
+ }
+}
diff --git a/src/net/java/sip/communicator/util/util.manifest.mf b/src/net/java/sip/communicator/util/util.manifest.mf
index 7726cd6..140fd43 100644
--- a/src/net/java/sip/communicator/util/util.manifest.mf
+++ b/src/net/java/sip/communicator/util/util.manifest.mf
@@ -35,11 +35,13 @@ Import-Package: org.xml.sax,
net.java.sip.communicator.service.contactlist,
sun.awt.shell,
sun.net.util,
- sun.net.dns
+ sun.net.dns,
+ com.sun.awt
Export-Package: net.java.sip.communicator.util.xml,
net.java.sip.communicator.util.swing.plaf,
net.java.sip.communicator.util.swing.event,
net.java.sip.communicator.util.swing,
+ net.java.sip.communicator.util.swing.transparent,
net.java.sip.communicator.util.swing.border,
net.java.sip.communicator.util,
net.java.sip.communicator.util.skin,