diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-05-13 01:21:17 +0800 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2009-05-13 01:21:17 +0800 |
commit | 072a3efa99f100d3d65e7d3cfa389cf332dbcb7d (patch) | |
tree | 7c1475157fe5676166c056b13bea33bffcc80be2 /src | |
parent | ff5143dd2d5294ef3465f50c03e39fd3201a0385 (diff) | |
parent | 0493b4a30bc60e0b282cdae95cdc35d8bcbac481 (diff) | |
download | gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar.gz gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar.bz2 gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar.lz gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar.xz gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.tar.zst gsoc2013-empathy-072a3efa99f100d3d65e7d3cfa389cf332dbcb7d.zip |
Merge commit 'jtellier/bug-580771'
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/empathy-call-window-fullscreen.c | 294 | ||||
-rw-r--r-- | src/empathy-call-window-fullscreen.h | 77 | ||||
-rw-r--r-- | src/empathy-call-window-fullscreen.ui | 23 | ||||
-rw-r--r-- | src/empathy-call-window.c | 293 | ||||
-rw-r--r-- | src/empathy-call-window.h | 3 | ||||
-rw-r--r-- | src/empathy-call-window.ui | 11 |
7 files changed, 688 insertions, 15 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f24ef3e95..9641a1837 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,6 +28,7 @@ empathy_SOURCES = \ empathy-about-dialog.c empathy-about-dialog.h \ empathy-accounts-dialog.c empathy-accounts-dialog.h \ empathy-call-window.c empathy-call-window.h \ + empathy-call-window-fullscreen.c empathy-call-window-fullscreen.h \ empathy-chatrooms-window.c empathy-chatrooms-window.h \ empathy-chat-window.c empathy-chat-window.h \ empathy-event-manager.c empathy-event-manager.h \ @@ -51,6 +52,7 @@ uidir = $(datadir)/empathy ui_DATA = \ empathy-accounts-dialog.ui \ empathy-call-window.ui \ + empathy-call-window-fullscreen.ui \ empathy-chatrooms-window.ui \ empathy-chat-window.ui \ empathy-ft-manager.ui \ diff --git a/src/empathy-call-window-fullscreen.c b/src/empathy-call-window-fullscreen.c new file mode 100644 index 000000000..33f4085b3 --- /dev/null +++ b/src/empathy-call-window-fullscreen.c @@ -0,0 +1,294 @@ +/* + * empathy-call-window-fullscreen.c - Source for EmpathyCallWindowFullscreen + * Copyright (C) 2009 Collabora Ltd. + * + * Some code is based on the Totem Movie Player, especially + * totem-fullscreen.c which has the following copyright: + * Copyright (C) 2001-2007 Bastien Nocera <hadess@hadess.net> + * Copyright (C) 2007 Sunil Mohan Adapa <sunilmohan@gnu.org.in> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "empathy-call-window-fullscreen.h" + +#include <gtk/gtk.h> + +#include <libempathy/empathy-utils.h> +#include <libempathy-gtk/empathy-ui-utils.h> + +/* The number of seconds for which the "leave fullscreen" popup should + be shown */ +#define FULLSCREEN_POPUP_TIMEOUT 5 + +G_DEFINE_TYPE (EmpathyCallWindowFullscreen, empathy_call_window_fullscreen, + G_TYPE_OBJECT) + +/* private structure */ +typedef struct _EmpathyCallWindowFullscreenPriv + EmpathyCallWindowFullscreenPriv; + +struct _EmpathyCallWindowFullscreenPriv +{ + EmpathyCallWindow *parent_window; + + GtkWidget *leave_fullscreen_popup; + GtkWidget *video_widget; + + guint popup_timeout; + gboolean popup_creation_in_progress; + gboolean dispose_has_run; +}; + +#define GET_PRIV(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \ + EmpathyCallWindowFullscreenPriv)) + +static void empathy_call_window_fullscreen_dispose (GObject *object); +static void empathy_call_window_fullscreen_finalize (GObject *object); + +static gboolean empathy_call_window_fullscreen_hide_popup ( + EmpathyCallWindowFullscreen *fs); + +static void +empathy_call_window_fullscreen_set_cursor_visible ( + EmpathyCallWindowFullscreen *fs, + gboolean show_cursor) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs); + + if (priv->video_widget != NULL && !show_cursor) + { + gdk_window_set_cursor (priv->video_widget->window, + gdk_cursor_new (GDK_BLANK_CURSOR)); + } + else + gdk_window_set_cursor (priv->video_widget->window, NULL); +} + +static void +empathy_call_window_fullscreen_add_popup_timeout ( + EmpathyCallWindowFullscreen *self) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + + if (priv->popup_timeout == 0) + { + priv->popup_timeout = g_timeout_add_seconds (FULLSCREEN_POPUP_TIMEOUT, + (GSourceFunc) empathy_call_window_fullscreen_hide_popup, self); + } +} + +static void +empathy_call_window_fullscreen_remove_popup_timeout ( + EmpathyCallWindowFullscreen *self) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + + if (priv->popup_timeout != 0) + { + g_source_remove (priv->popup_timeout); + priv->popup_timeout = 0; + } +} + +void +empathy_call_window_fullscreen_show_popup (EmpathyCallWindowFullscreen *self) +{ + gint leave_fullscreen_width, leave_fullscreen_height; + GdkScreen *screen; + GdkRectangle fullscreen_rect; + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + + g_assert (self->is_fullscreen); + + g_return_if_fail (priv->parent_window != NULL); + + if (priv->popup_creation_in_progress) + return; + + if (!gtk_window_is_active (GTK_WINDOW (priv->parent_window))) + return; + + priv->popup_creation_in_progress = TRUE; + + empathy_call_window_fullscreen_set_cursor_visible (self, TRUE); + + /* Obtaining the screen rectangle */ + screen = gtk_window_get_screen (GTK_WINDOW (priv->parent_window)); + gdk_screen_get_monitor_geometry (screen, + gdk_screen_get_monitor_at_window (screen, + GTK_WIDGET (priv->parent_window)->window), + &fullscreen_rect); + + /* Getting the popup window sizes */ + gtk_window_get_size (GTK_WINDOW (priv->leave_fullscreen_popup), + &leave_fullscreen_width, &leave_fullscreen_height); + + /* Moving the popup to the top-right corner (if the direction is LTR) or the + top-left corner (if the direction is RTL).*/ + if (gtk_widget_get_direction (priv->leave_fullscreen_popup) + == GTK_TEXT_DIR_LTR) + { + gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup), + fullscreen_rect.width + fullscreen_rect.x - leave_fullscreen_width, + fullscreen_rect.y); + + } + else + { + gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup), + fullscreen_rect.x, fullscreen_rect.y); + } + + gtk_widget_show_all (priv->leave_fullscreen_popup); + empathy_call_window_fullscreen_add_popup_timeout (self); + + priv->popup_creation_in_progress = FALSE; +} + +static gboolean +empathy_call_window_fullscreen_hide_popup (EmpathyCallWindowFullscreen *fs) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs); + + if (priv->video_widget == NULL || !fs->is_fullscreen) + return TRUE; + + gtk_widget_hide (priv->leave_fullscreen_popup); + empathy_call_window_fullscreen_remove_popup_timeout (fs); + + empathy_call_window_fullscreen_set_cursor_visible (fs, FALSE); + + return FALSE; +} + +static void +empathy_call_window_fullscreen_init (EmpathyCallWindowFullscreen *self) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + GtkBuilder *gui; + gchar *filename; + + filename = empathy_file_lookup ("empathy-call-window-fullscreen.ui", "src"); + gui = empathy_builder_get_file (filename, + "leave_fullscreen_window", &priv->leave_fullscreen_popup, + "leave_fullscreen_button", &self->leave_fullscreen_button, + NULL); + + gtk_widget_add_events (priv->leave_fullscreen_popup, GDK_POINTER_MOTION_MASK); + + g_object_unref (gui); + g_free (filename); +} + +static void +empathy_call_window_fullscreen_class_init ( + EmpathyCallWindowFullscreenClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EmpathyCallWindowFullscreenPriv)); + + object_class->dispose = empathy_call_window_fullscreen_dispose; + object_class->finalize = empathy_call_window_fullscreen_finalize; +} + +void +empathy_call_window_fullscreen_dispose (GObject *object) +{ + EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object); + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->leave_fullscreen_popup != NULL) + gtk_widget_destroy (priv->leave_fullscreen_popup); + priv->leave_fullscreen_popup = NULL; + + if (G_OBJECT_CLASS (empathy_call_window_fullscreen_parent_class)->dispose) + { + G_OBJECT_CLASS ( + empathy_call_window_fullscreen_parent_class)->dispose (object); + } +} + +void +empathy_call_window_fullscreen_finalize (GObject *object) +{ + EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object); + + empathy_call_window_fullscreen_remove_popup_timeout (self); + + G_OBJECT_CLASS ( + empathy_call_window_fullscreen_parent_class)->finalize (object); +} + +static void +empathy_call_window_fullscreen_parent_window_notify (GtkWidget *parent_window, + GParamSpec *property, EmpathyCallWindowFullscreen *fs) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs); + + if (!fs->is_fullscreen) + return; + + if (parent_window == GTK_WIDGET (priv->parent_window) && + !gtk_window_is_active (GTK_WINDOW (parent_window))) + { + empathy_call_window_fullscreen_hide_popup (fs); + empathy_call_window_fullscreen_set_cursor_visible (fs, TRUE); + } +} + +EmpathyCallWindowFullscreen * +empathy_call_window_fullscreen_new (EmpathyCallWindow *parent_window) +{ + EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN ( + g_object_new (EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, NULL)); + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self); + + priv->parent_window = parent_window; + g_signal_connect (G_OBJECT (priv->parent_window), "notify::is-active", + G_CALLBACK (empathy_call_window_fullscreen_parent_window_notify), self); + + return self; +} + +void +empathy_call_window_fullscreen_set_fullscreen (EmpathyCallWindowFullscreen *fs, + gboolean set_fullscreen) +{ + + if (set_fullscreen) + empathy_call_window_fullscreen_remove_popup_timeout (fs); + else + empathy_call_window_fullscreen_hide_popup (fs); + + empathy_call_window_fullscreen_set_cursor_visible (fs, !set_fullscreen); + fs->is_fullscreen = set_fullscreen; +} + +void +empathy_call_window_fullscreen_set_video_widget ( + EmpathyCallWindowFullscreen *fs, + GtkWidget *video_widget) +{ + EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs); + priv->video_widget = video_widget; +} diff --git a/src/empathy-call-window-fullscreen.h b/src/empathy-call-window-fullscreen.h new file mode 100644 index 000000000..1ae1e98e7 --- /dev/null +++ b/src/empathy-call-window-fullscreen.h @@ -0,0 +1,77 @@ +/* + * empathy-call-window-fullscreen.h - Header for EmpathyCallWindowFullscreen + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_CALL_WINDOW_FULLSCREEN_H__ +#define __EMPATHY_CALL_WINDOW_FULLSCREEN_H__ + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "empathy-call-window.h" + +G_BEGIN_DECLS + +typedef struct _EmpathyCallWindowFullscreen EmpathyCallWindowFullscreen; +typedef struct _EmpathyCallWindowFullscreenClass + EmpathyCallWindowFullscreenClass; + +struct _EmpathyCallWindowFullscreenClass { + GObjectClass parent_class; +}; + +struct _EmpathyCallWindowFullscreen { + GObject parent; + gboolean is_fullscreen; + GtkWidget *leave_fullscreen_button; +}; + +GType empathy_call_window_fullscreen_get_type(void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN \ + (empathy_call_window_fullscreen_get_type()) +#define EMPATHY_CALL_WINDOW_FULLSCREEN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \ + EmpathyCallWindowFullscreen)) +#define EMPATHY_CALL_WINDOW_FULLSCREEN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \ + EmpathyCallWindowClassFullscreen)) +#define EMPATHY_IS_CALL_WINDOW_FULLSCREEN(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN)) +#define EMPATHY_IS_CALL_WINDOW_FULLSCREEN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN)) +#define EMPATHY_CALL_WINDOW_FULLSCREEN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \ + EmpathyCallWindowFullscreenClass)) + +EmpathyCallWindowFullscreen *empathy_call_window_fullscreen_new ( + EmpathyCallWindow *parent); + +void empathy_call_window_fullscreen_set_fullscreen ( + EmpathyCallWindowFullscreen *fs, + gboolean set_fullscreen); +void empathy_call_window_fullscreen_set_video_widget ( + EmpathyCallWindowFullscreen *fs, + GtkWidget *video_widget); +void empathy_call_window_fullscreen_show_popup ( + EmpathyCallWindowFullscreen *fs); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_CALL_WINDOW_FULLSCREEN_H__*/
\ No newline at end of file diff --git a/src/empathy-call-window-fullscreen.ui b/src/empathy-call-window-fullscreen.ui new file mode 100644 index 000000000..5bf5e509b --- /dev/null +++ b/src/empathy-call-window-fullscreen.ui @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<interface> + <requires lib="gtk+" version="2.16"/> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkWindow" id="leave_fullscreen_window"> + <property name="type">popup</property> + <property name="resizable">False</property> + <property name="skip_taskbar_hint">True</property> + <property name="skip_pager_hint">True</property> + <property name="decorated">False</property> + <property name="deletable">False</property> + <signal name="motion_notify_event" handler="empathy_call_window_fullscreen_motion_notify_cb"/> + <child> + <object class="GtkButton" id="leave_fullscreen_button"> + <property name="label" translatable="yes">gtk-leave-fullscreen</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </object> + </child> + </object> +</interface> diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c index 22a9eef44..9a9119b97 100644 --- a/src/empathy-call-window.c +++ b/src/empathy-call-window.c @@ -24,6 +24,7 @@ #include <math.h> +#include <gdk/gdkkeysyms.h> #include <gst/gst.h> #include <gtk/gtk.h> #include <glib/gi18n.h> @@ -39,10 +40,15 @@ #include "empathy-call-window.h" +#include "empathy-call-window-fullscreen.h" #include "empathy-sidebar.h" #define BUTTON_ID "empathy-call-dtmf-button-id" +#define CONTENT_HBOX_BORDER_WIDTH 6 +#define CONTENT_HBOX_SPACING 3 +#define CONTENT_HBOX_CHILDREN_PACKING_PADDING 3 + G_DEFINE_TYPE(EmpathyCallWindow, empathy_call_window, GTK_TYPE_WINDOW) /* signal enum */ @@ -82,6 +88,17 @@ struct _EmpathyCallWindowPriv GtkWidget *toolbar; GtkWidget *pane; GtkAction *send_video; + GtkAction *menu_fullscreen; + + /* We keep a reference on the hbox which contains the main content so we can + easilly repack everything when toggling fullscreen */ + GtkWidget *content_hbox; + + /* This vbox is contained in the content_hbox. When toggling fullscreen, + it needs to be repacked. We keep a reference on it for easier access. */ + GtkWidget *vbox; + + gulong video_output_motion_handler_id; gdouble volume; GtkAdjustment *audio_input_adj; @@ -109,6 +126,15 @@ struct _EmpathyCallWindowPriv GMutex *lock; gboolean call_started; gboolean sending_video; + + EmpathyCallWindowFullscreen *fullscreen; + gboolean is_fullscreen; + + /* Those fields represent the state of the window before it actually was in + fullscreen mode. */ + gboolean sidebar_was_visible_before_fs; + gint original_width_before_fs; + gint original_height_before_fs; }; #define GET_PRIV(o) \ @@ -119,7 +145,10 @@ static void empathy_call_window_realized_cb (GtkWidget *widget, EmpathyCallWindow *window); static gboolean empathy_call_window_delete_cb (GtkWidget *widget, - GdkEvent*event, EmpathyCallWindow *window); + GdkEvent *event, EmpathyCallWindow *window); + +static gboolean empathy_call_window_state_event_cb (GtkWidget *widget, + GdkEventWindowState *event, EmpathyCallWindow *window); static void empathy_call_window_sidebar_toggled_cb (GtkToggleButton *toggle, EmpathyCallWindow *window); @@ -139,9 +168,29 @@ static void empathy_call_window_mic_toggled_cb ( static void empathy_call_window_sidebar_hidden_cb (EmpathySidebar *sidebar, EmpathyCallWindow *window); +static void empathy_call_window_sidebar_shown_cb (EmpathySidebar *sidebar, + EmpathyCallWindow *window); + static void empathy_call_window_hangup_cb (gpointer object, EmpathyCallWindow *window); +static void empathy_call_window_fullscreen_cb (gpointer object, + EmpathyCallWindow *window); + +static void empathy_call_window_fullscreen_toggle (EmpathyCallWindow *window); + +static gboolean empathy_call_window_video_button_press_cb (GtkWidget *video_output, + GdkEventButton *event, EmpathyCallWindow *window); + +static gboolean empathy_call_window_key_press_cb (GtkWidget *video_output, + GdkEventKey *event, EmpathyCallWindow *window); + +static gboolean empathy_call_window_video_output_motion_notify (GtkWidget *widget, + GdkEventMotion *event, EmpathyCallWindow *window); + +static void empathy_call_window_video_menu_popup (EmpathyCallWindow *window, + guint button); + static void empathy_call_window_status_message (EmpathyCallWindow *window, gchar *message); @@ -459,8 +508,8 @@ empathy_call_window_init (EmpathyCallWindow *self) { EmpathyCallWindowPriv *priv = GET_PRIV (self); GtkBuilder *gui; - GtkWidget *vbox, *top_vbox; - GtkWidget *hbox, *h; + GtkWidget *top_vbox; + GtkWidget *h; GtkWidget *arrow; GtkWidget *page; GstBus *bus; @@ -476,6 +525,7 @@ empathy_call_window_init (EmpathyCallWindow *self) "toolbar", &priv->toolbar, "send_video", &priv->send_video, "ui_manager", &priv->ui_manager, + "menufullscreen", &priv->menu_fullscreen, NULL); empathy_builder_connect (gui, self, @@ -485,6 +535,7 @@ empathy_call_window_init (EmpathyCallWindow *self) "camera", "toggled", empathy_call_window_camera_toggled_cb, "send_video", "toggled", empathy_call_window_send_video_toggled_cb, "show_preview", "toggled", empathy_call_window_show_preview_toggled_cb, + "menufullscreen", "activate", empathy_call_window_fullscreen_cb, NULL); priv->lock = g_mutex_new (); @@ -495,27 +546,34 @@ empathy_call_window_init (EmpathyCallWindow *self) priv->pipeline = gst_pipeline_new (NULL); - hbox = gtk_hbox_new (FALSE, 3); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); - gtk_paned_pack1 (GTK_PANED (priv->pane), hbox, TRUE, FALSE); + priv->content_hbox = gtk_hbox_new (FALSE, CONTENT_HBOX_SPACING); + gtk_container_set_border_width (GTK_CONTAINER (priv->content_hbox), + CONTENT_HBOX_BORDER_WIDTH); + gtk_paned_pack1 (GTK_PANED (priv->pane), priv->content_hbox, TRUE, FALSE); bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline)); gst_bus_add_watch (bus, empathy_call_window_bus_message, self); priv->video_output = empathy_video_widget_new (bus); - gtk_box_pack_start (GTK_BOX (hbox), priv->video_output, TRUE, TRUE, 3); + gtk_box_pack_start (GTK_BOX (priv->content_hbox), priv->video_output, + TRUE, TRUE, CONTENT_HBOX_CHILDREN_PACKING_PADDING); + gtk_widget_add_events (priv->video_output, + GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + g_signal_connect (G_OBJECT (priv->video_output), "button-press-event", + G_CALLBACK (empathy_call_window_video_button_press_cb), self); priv->video_tee = gst_element_factory_make ("tee", NULL); gst_object_ref (priv->video_tee); gst_object_sink (priv->video_tee); - vbox = gtk_vbox_new (FALSE, 3); - gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 3); + priv->vbox = gtk_vbox_new (FALSE, 3); + gtk_box_pack_start (GTK_BOX (priv->content_hbox), priv->vbox, + FALSE, FALSE, CONTENT_HBOX_CHILDREN_PACKING_PADDING); priv->video_preview = empathy_video_widget_new_with_size (bus, 160, 120); g_object_set (priv->video_preview, "sync", FALSE, "async", TRUE, NULL); - gtk_box_pack_start (GTK_BOX (vbox), priv->video_preview, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->vbox), priv->video_preview, FALSE, FALSE, 0); priv->video_input = empathy_video_src_new (); gst_object_ref (priv->video_input); @@ -539,13 +597,14 @@ empathy_call_window_init (EmpathyCallWindow *self) gtk_button_set_image (GTK_BUTTON (priv->sidebar_button), arrow); h = gtk_hbox_new (FALSE, 3); - gtk_box_pack_end (GTK_BOX (vbox), h, FALSE, FALSE, 3); + gtk_box_pack_end (GTK_BOX (priv->vbox), h, FALSE, FALSE, 3); gtk_box_pack_end (GTK_BOX (h), priv->sidebar_button, FALSE, FALSE, 3); priv->sidebar = empathy_sidebar_new (); g_signal_connect (G_OBJECT (priv->sidebar), - "hide", G_CALLBACK (empathy_call_window_sidebar_hidden_cb), - self); + "hide", G_CALLBACK (empathy_call_window_sidebar_hidden_cb), self); + g_signal_connect (G_OBJECT (priv->sidebar), + "show", G_CALLBACK (empathy_call_window_sidebar_shown_cb), self); gtk_paned_pack2 (GTK_PANED (priv->pane), priv->sidebar, FALSE, FALSE); priv->dtmf_panel = empathy_call_window_create_dtmf (self); @@ -566,18 +625,30 @@ empathy_call_window_init (EmpathyCallWindow *self) gtk_widget_hide (priv->sidebar); + priv->fullscreen = empathy_call_window_fullscreen_new (self); + empathy_call_window_fullscreen_set_video_widget (priv->fullscreen, priv->video_output); + g_signal_connect (G_OBJECT (priv->fullscreen->leave_fullscreen_button), + "clicked", G_CALLBACK (empathy_call_window_fullscreen_cb), self); + g_signal_connect (G_OBJECT (self), "realize", G_CALLBACK (empathy_call_window_realized_cb), self); g_signal_connect (G_OBJECT (self), "delete-event", G_CALLBACK (empathy_call_window_delete_cb), self); + g_signal_connect (G_OBJECT (self), "window-state-event", + G_CALLBACK (empathy_call_window_state_event_cb), self); + + g_signal_connect (G_OBJECT (self), "key-press-event", + G_CALLBACK (empathy_call_window_key_press_cb), self); + empathy_call_window_status_message (self, _("Connecting...")); priv->timer = g_timer_new (); g_object_ref (priv->ui_manager); g_object_unref (gui); + g_free (filename); } static void @@ -748,6 +819,13 @@ empathy_call_window_finalize (GObject *object) EmpathyCallWindow *self = EMPATHY_CALL_WINDOW (object); EmpathyCallWindowPriv *priv = GET_PRIV (self); + if (priv->video_output_motion_handler_id != 0) + { + g_signal_handler_disconnect (G_OBJECT (priv->video_output), + priv->video_output_motion_handler_id); + priv->video_output_motion_handler_id = 0; + } + /* free any data held directly by the object here */ g_mutex_free (priv->lock); @@ -1166,6 +1244,108 @@ empathy_call_window_delete_cb (GtkWidget *widget, GdkEvent*event, } static void +show_controls (EmpathyCallWindow *window, gboolean set_fullscreen) +{ + GtkWidget *menu; + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + menu = gtk_ui_manager_get_widget (priv->ui_manager, + "/menubar1"); + + if (set_fullscreen) + { + gtk_widget_hide (priv->sidebar); + gtk_widget_hide (menu); + gtk_widget_hide (priv->vbox); + gtk_widget_hide (priv->statusbar); + gtk_widget_hide (priv->toolbar); + } + else + { + if (priv->sidebar_was_visible_before_fs) + gtk_widget_show (priv->sidebar); + + gtk_widget_show (menu); + gtk_widget_show (priv->vbox); + gtk_widget_show (priv->statusbar); + gtk_widget_show (priv->toolbar); + + gtk_window_resize (GTK_WINDOW (window), priv->original_width_before_fs, + priv->original_height_before_fs); + } +} + +static void +show_borders (EmpathyCallWindow *window, gboolean set_fullscreen) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + gtk_container_set_border_width (GTK_CONTAINER (priv->content_hbox), + set_fullscreen ? 0 : CONTENT_HBOX_BORDER_WIDTH); + gtk_box_set_spacing (GTK_BOX (priv->content_hbox), + set_fullscreen ? 0 : CONTENT_HBOX_SPACING); + gtk_box_set_child_packing (GTK_BOX (priv->content_hbox), + priv->video_output, TRUE, TRUE, + set_fullscreen ? 0 : CONTENT_HBOX_CHILDREN_PACKING_PADDING, + GTK_PACK_START); + gtk_box_set_child_packing (GTK_BOX (priv->content_hbox), + priv->vbox, TRUE, TRUE, + set_fullscreen ? 0 : CONTENT_HBOX_CHILDREN_PACKING_PADDING, + GTK_PACK_START); +} + +static gboolean +empathy_call_window_state_event_cb (GtkWidget *widget, + GdkEventWindowState *event, EmpathyCallWindow *window) +{ + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + { + EmpathyCallWindowPriv *priv = GET_PRIV (window); + gboolean set_fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + + if (set_fullscreen) + { + gboolean sidebar_was_visible; + gint original_width = GTK_WIDGET (window)->allocation.width; + gint original_height = GTK_WIDGET (window)->allocation.height; + + g_object_get (priv->sidebar, "visible", &sidebar_was_visible, NULL); + + priv->sidebar_was_visible_before_fs = sidebar_was_visible; + priv->original_width_before_fs = original_width; + priv->original_height_before_fs = original_height; + + if (priv->video_output_motion_handler_id == 0 && + priv->video_output != NULL) + { + priv->video_output_motion_handler_id = g_signal_connect ( + G_OBJECT (priv->video_output), "motion-notify-event", + G_CALLBACK (empathy_call_window_video_output_motion_notify), window); + } + } + else + { + if (priv->video_output_motion_handler_id != 0) + { + g_signal_handler_disconnect (G_OBJECT (priv->video_output), + priv->video_output_motion_handler_id); + priv->video_output_motion_handler_id = 0; + } + } + + empathy_call_window_fullscreen_set_fullscreen (priv->fullscreen, + set_fullscreen); + show_controls (window, set_fullscreen); + show_borders (window, set_fullscreen); + gtk_action_set_stock_id(priv->menu_fullscreen, + (set_fullscreen ? "gtk-leave-fullscreen" : "gtk-fullscreen")); + priv->is_fullscreen = set_fullscreen; + } + + return FALSE; +} + +static void empathy_call_window_sidebar_toggled_cb (GtkToggleButton *toggle, EmpathyCallWindow *window) { @@ -1290,6 +1470,16 @@ empathy_call_window_sidebar_hidden_cb (EmpathySidebar *sidebar, } static void +empathy_call_window_sidebar_shown_cb (EmpathySidebar *sidebar, + EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->sidebar_button), + TRUE); +} + +static void empathy_call_window_hangup_cb (gpointer object, EmpathyCallWindow *window) { @@ -1300,6 +1490,83 @@ empathy_call_window_hangup_cb (gpointer object, } static void +empathy_call_window_fullscreen_cb (gpointer object, + EmpathyCallWindow *window) +{ + empathy_call_window_fullscreen_toggle (window); +} + +static void +empathy_call_window_fullscreen_toggle (EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + if (priv->is_fullscreen) + gtk_window_unfullscreen (GTK_WINDOW (window)); + else + gtk_window_fullscreen (GTK_WINDOW (window)); +} + +static gboolean +empathy_call_window_video_button_press_cb (GtkWidget *video_output, + GdkEventButton *event, EmpathyCallWindow *window) +{ + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + empathy_call_window_video_menu_popup (window, event->button); + return TRUE; + } + + return FALSE; +} + +static gboolean +empathy_call_window_key_press_cb (GtkWidget *video_output, + GdkEventKey *event, EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + if (priv->is_fullscreen && event->keyval == GDK_Escape) + { + /* Since we are in fullscreen mode, toggling will bring us back to + normal mode. */ + empathy_call_window_fullscreen_toggle (window); + return TRUE; + } + + return FALSE; +} + +static gboolean +empathy_call_window_video_output_motion_notify (GtkWidget *widget, + GdkEventMotion *event, EmpathyCallWindow *window) +{ + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + if (priv->is_fullscreen) + { + empathy_call_window_fullscreen_show_popup (priv->fullscreen); + return TRUE; + } + + return FALSE; +} + +static void +empathy_call_window_video_menu_popup (EmpathyCallWindow *window, + guint button) +{ + GtkWidget *menu; + EmpathyCallWindowPriv *priv = GET_PRIV (window); + + menu = gtk_ui_manager_get_widget (priv->ui_manager, + "/video-popup"); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + button, gtk_get_current_event_time ()); + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE); +} + +static void empathy_call_window_status_message (EmpathyCallWindow *window, gchar *message) { diff --git a/src/empathy-call-window.h b/src/empathy-call-window.h index 26b0e7881..cda7af2f6 100644 --- a/src/empathy-call-window.h +++ b/src/empathy-call-window.h @@ -57,8 +57,7 @@ GType empathy_call_window_get_type(void); (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_CALL_WINDOW, \ EmpathyCallWindowClass)) -EmpathyCallWindow * -empathy_call_window_new (EmpathyCallHandler *handler); +EmpathyCallWindow *empathy_call_window_new (EmpathyCallHandler *handler); G_END_DECLS diff --git a/src/empathy-call-window.ui b/src/empathy-call-window.ui index ce3d85b56..a0e1e1304 100644 --- a/src/empathy-call-window.ui +++ b/src/empathy-call-window.ui @@ -36,6 +36,13 @@ <property name="label" translatable="yes">Video preview</property> </object> </child> + <child> + <object class="GtkAction" id="menufullscreen"> + <property name="stock_id">gtk-fullscreen</property> + <property name="name">menufullscreen</property> + </object> + <accelerator key="F11"/> + </child> </object> </child> <ui> @@ -46,8 +53,12 @@ </menu> <menu action="view"> <menuitem action="show_preview"/> + <menuitem action="menufullscreen"/> </menu> </menubar> + <popup name="video-popup"> + <menuitem name="menufullscreen" action="menufullscreen"/> + </popup> </ui> </object> <object class="GtkVBox" id="call_window_vbox"> |