]> git.0d.be Git - empathy.git/blob - src/empathy-call-window-fullscreen.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / src / empathy-call-window-fullscreen.c
1 /*
2  * empathy-call-window-fullscreen.c - Source for EmpathyCallWindowFullscreen
3  * Copyright (C) 2009-2011 Collabora Ltd.
4  *
5  * Some code is based on the Totem Movie Player, especially
6  * totem-fullscreen.c which has the following copyright:
7  * Copyright (C) 2001-2007 Bastien Nocera <hadess@hadess.net>
8  * Copyright (C) 2007 Sunil Mohan Adapa <sunilmohan@gnu.org.in>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  */
24
25 #include "config.h"
26 #include "empathy-call-window-fullscreen.h"
27
28 #include "empathy-ui-utils.h"
29 #include "empathy-utils.h"
30
31 /* The number of seconds for which the "leave fullscreen" popup should
32    be shown */
33 #define FULLSCREEN_POPUP_TIMEOUT 5
34
35 G_DEFINE_TYPE (EmpathyCallWindowFullscreen, empathy_call_window_fullscreen,
36     G_TYPE_OBJECT)
37
38 /* private structure */
39 typedef struct _EmpathyCallWindowFullscreenPriv
40     EmpathyCallWindowFullscreenPriv;
41
42 struct _EmpathyCallWindowFullscreenPriv
43 {
44   EmpathyCallWindow *parent_window;
45
46   GtkWidget *leave_fullscreen_popup;
47   GtkWidget *video_widget;
48
49   guint popup_timeout;
50   gboolean popup_creation_in_progress;
51   gboolean dispose_has_run;
52 };
53
54 #define GET_PRIV(o) \
55   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \
56     EmpathyCallWindowFullscreenPriv))
57
58 static void empathy_call_window_fullscreen_dispose (GObject *object);
59 static void empathy_call_window_fullscreen_finalize (GObject *object);
60
61 static gboolean empathy_call_window_fullscreen_hide_popup (
62     EmpathyCallWindowFullscreen *fs);
63
64 static void
65 empathy_call_window_fullscreen_set_cursor_visible (
66     EmpathyCallWindowFullscreen *fs,
67     gboolean show_cursor)
68 {
69   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
70   GdkWindow *window;
71
72   if (priv->video_widget == NULL)
73     return;
74
75   window = gtk_widget_get_window (priv->video_widget);
76
77   if (!show_cursor)
78     gdk_window_set_cursor (window, gdk_cursor_new (GDK_BLANK_CURSOR));
79   else
80     gdk_window_set_cursor (window, NULL);
81 }
82
83 static void
84 empathy_call_window_fullscreen_add_popup_timeout (
85     EmpathyCallWindowFullscreen *self)
86 {
87   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
88
89   if (priv->popup_timeout == 0)
90     {
91       priv->popup_timeout = g_timeout_add_seconds (FULLSCREEN_POPUP_TIMEOUT,
92           (GSourceFunc) empathy_call_window_fullscreen_hide_popup, self);
93     }
94 }
95
96 static void
97 empathy_call_window_fullscreen_remove_popup_timeout (
98     EmpathyCallWindowFullscreen *self)
99 {
100   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
101
102   if (priv->popup_timeout != 0)
103     {
104       g_source_remove (priv->popup_timeout);
105       priv->popup_timeout = 0;
106     }
107 }
108
109 void
110 empathy_call_window_fullscreen_show_popup (EmpathyCallWindowFullscreen *self)
111 {
112   gint leave_fullscreen_width, leave_fullscreen_height;
113   GdkScreen *screen;
114   GdkRectangle fullscreen_rect;
115   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
116
117   g_assert (self->is_fullscreen);
118
119   g_return_if_fail (priv->parent_window != NULL);
120
121   if (priv->popup_creation_in_progress)
122     return;
123
124   if (!gtk_window_is_active (GTK_WINDOW (priv->parent_window)))
125     return;
126
127   priv->popup_creation_in_progress = TRUE;
128
129   empathy_call_window_fullscreen_set_cursor_visible (self, TRUE);
130
131   /* Obtaining the screen rectangle */
132   screen = gtk_window_get_screen (GTK_WINDOW (priv->parent_window));
133   gdk_screen_get_monitor_geometry (screen,
134       gdk_screen_get_monitor_at_window (screen,
135           gtk_widget_get_window (GTK_WIDGET (priv->parent_window))),
136       &fullscreen_rect);
137
138   /* Getting the popup window sizes */
139   gtk_window_get_size (GTK_WINDOW (priv->leave_fullscreen_popup),
140       &leave_fullscreen_width, &leave_fullscreen_height);
141
142   /* Moving the popup to the top-right corner (if the direction is LTR) or the
143      top-left corner (if the direction is RTL).*/
144   if (gtk_widget_get_direction (priv->leave_fullscreen_popup)
145         == GTK_TEXT_DIR_LTR)
146     {
147       gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup),
148           fullscreen_rect.width + fullscreen_rect.x - leave_fullscreen_width,
149           fullscreen_rect.y);
150
151     }
152   else
153     {
154       gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup),
155           fullscreen_rect.x, fullscreen_rect.y);
156     }
157
158   gtk_widget_show_all (priv->leave_fullscreen_popup);
159   empathy_call_window_fullscreen_add_popup_timeout (self);
160
161   priv->popup_creation_in_progress = FALSE;
162 }
163
164 static gboolean
165 empathy_call_window_fullscreen_hide_popup (EmpathyCallWindowFullscreen *fs)
166 {
167   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
168
169   if (priv->video_widget == NULL || !fs->is_fullscreen)
170     return TRUE;
171
172   gtk_widget_hide (priv->leave_fullscreen_popup);
173   empathy_call_window_fullscreen_remove_popup_timeout (fs);
174
175   empathy_call_window_fullscreen_set_cursor_visible (fs, FALSE);
176
177   return FALSE;
178 }
179
180 static void
181 empathy_call_window_fullscreen_init (EmpathyCallWindowFullscreen *self)
182 {
183   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
184   GtkBuilder *gui;
185   gchar *filename;
186
187   filename = empathy_file_lookup ("empathy-call-window-fullscreen.ui", "src");
188   gui = empathy_builder_get_file (filename,
189     "leave_fullscreen_window", &priv->leave_fullscreen_popup,
190     "leave_fullscreen_button", &self->leave_fullscreen_button,
191     NULL);
192
193   gtk_widget_add_events (priv->leave_fullscreen_popup, GDK_POINTER_MOTION_MASK);
194
195   g_object_unref (gui);
196   g_free (filename);
197 }
198
199 static void
200 empathy_call_window_fullscreen_class_init (
201     EmpathyCallWindowFullscreenClass *klass)
202 {
203   GObjectClass *object_class = G_OBJECT_CLASS (klass);
204
205   g_type_class_add_private (klass, sizeof (EmpathyCallWindowFullscreenPriv));
206
207   object_class->dispose = empathy_call_window_fullscreen_dispose;
208   object_class->finalize = empathy_call_window_fullscreen_finalize;
209 }
210
211 void
212 empathy_call_window_fullscreen_dispose (GObject *object)
213 {
214   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object);
215   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
216
217   if (priv->dispose_has_run)
218     return;
219
220   priv->dispose_has_run = TRUE;
221
222   if (priv->leave_fullscreen_popup != NULL)
223     gtk_widget_destroy (priv->leave_fullscreen_popup);
224   priv->leave_fullscreen_popup = NULL;
225
226   if (G_OBJECT_CLASS (empathy_call_window_fullscreen_parent_class)->dispose)
227     {
228       G_OBJECT_CLASS (
229           empathy_call_window_fullscreen_parent_class)->dispose (object);
230     }
231 }
232
233 void
234 empathy_call_window_fullscreen_finalize (GObject *object)
235 {
236   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object);
237
238   empathy_call_window_fullscreen_remove_popup_timeout (self);
239
240   G_OBJECT_CLASS (
241       empathy_call_window_fullscreen_parent_class)->finalize (object);
242 }
243
244 static void
245 empathy_call_window_fullscreen_parent_window_notify (GtkWidget *parent_window,
246     GParamSpec *property, EmpathyCallWindowFullscreen *fs)
247 {
248   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
249
250   if (!fs->is_fullscreen)
251     return;
252
253   if (parent_window == GTK_WIDGET (priv->parent_window) &&
254         !gtk_window_is_active (GTK_WINDOW (parent_window)))
255     {
256       empathy_call_window_fullscreen_hide_popup (fs);
257       empathy_call_window_fullscreen_set_cursor_visible (fs, TRUE);
258     }
259 }
260
261 EmpathyCallWindowFullscreen *
262 empathy_call_window_fullscreen_new (EmpathyCallWindow *parent_window)
263 {
264   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (
265     g_object_new (EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, NULL));
266   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
267
268   priv->parent_window = parent_window;
269   g_signal_connect (G_OBJECT (priv->parent_window), "notify::is-active",
270     G_CALLBACK (empathy_call_window_fullscreen_parent_window_notify), self);
271
272   return self;
273 }
274
275 void
276 empathy_call_window_fullscreen_set_fullscreen (EmpathyCallWindowFullscreen *fs,
277   gboolean set_fullscreen)
278 {
279
280   if (set_fullscreen)
281       empathy_call_window_fullscreen_remove_popup_timeout (fs);
282   else
283       empathy_call_window_fullscreen_hide_popup (fs);
284
285   empathy_call_window_fullscreen_set_cursor_visible (fs, !set_fullscreen);
286   fs->is_fullscreen = set_fullscreen;
287 }
288
289 static void
290 video_widget_destroy_cb (GtkWidget *widget,
291     EmpathyCallWindowFullscreen *self)
292 {
293   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
294
295   priv->video_widget = NULL;
296 }
297
298 void
299 empathy_call_window_fullscreen_set_video_widget (
300     EmpathyCallWindowFullscreen *fs,
301     GtkWidget *video_widget)
302 {
303   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
304   priv->video_widget = video_widget;
305
306   tp_g_signal_connect_object (video_widget, "destroy",
307       G_CALLBACK (video_widget_destroy_cb), fs, 0);
308 }