]> git.0d.be Git - empathy.git/blob - src/empathy-call-window-fullscreen.c
6da478fbd653a11b79381dc227e492f6ed604e0a
[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 "empathy-call-window-fullscreen.h"
26
27 #include "empathy-utils.h"
28 #include "empathy-ui-utils.h"
29
30 /* The number of seconds for which the "leave fullscreen" popup should
31    be shown */
32 #define FULLSCREEN_POPUP_TIMEOUT 5
33
34 G_DEFINE_TYPE (EmpathyCallWindowFullscreen, empathy_call_window_fullscreen,
35     G_TYPE_OBJECT)
36
37 /* private structure */
38 typedef struct _EmpathyCallWindowFullscreenPriv
39     EmpathyCallWindowFullscreenPriv;
40
41 struct _EmpathyCallWindowFullscreenPriv
42 {
43   EmpathyCallWindow *parent_window;
44
45   GtkWidget *leave_fullscreen_popup;
46   GtkWidget *video_widget;
47
48   guint popup_timeout;
49   gboolean popup_creation_in_progress;
50   gboolean dispose_has_run;
51 };
52
53 #define GET_PRIV(o) \
54   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, \
55     EmpathyCallWindowFullscreenPriv))
56
57 static void empathy_call_window_fullscreen_dispose (GObject *object);
58 static void empathy_call_window_fullscreen_finalize (GObject *object);
59
60 static gboolean empathy_call_window_fullscreen_hide_popup (
61     EmpathyCallWindowFullscreen *fs);
62
63 static void
64 empathy_call_window_fullscreen_set_cursor_visible (
65     EmpathyCallWindowFullscreen *fs,
66     gboolean show_cursor)
67 {
68   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
69   GdkWindow *window;
70
71   if (priv->video_widget == NULL)
72     return;
73
74   window = gtk_widget_get_window (priv->video_widget);
75
76   if (!show_cursor)
77     gdk_window_set_cursor (window, gdk_cursor_new (GDK_BLANK_CURSOR));
78   else
79     gdk_window_set_cursor (window, NULL);
80 }
81
82 static void
83 empathy_call_window_fullscreen_add_popup_timeout (
84     EmpathyCallWindowFullscreen *self)
85 {
86   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
87
88   if (priv->popup_timeout == 0)
89     {
90       priv->popup_timeout = g_timeout_add_seconds (FULLSCREEN_POPUP_TIMEOUT,
91           (GSourceFunc) empathy_call_window_fullscreen_hide_popup, self);
92     }
93 }
94
95 static void
96 empathy_call_window_fullscreen_remove_popup_timeout (
97     EmpathyCallWindowFullscreen *self)
98 {
99   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
100
101   if (priv->popup_timeout != 0)
102     {
103       g_source_remove (priv->popup_timeout);
104       priv->popup_timeout = 0;
105     }
106 }
107
108 void
109 empathy_call_window_fullscreen_show_popup (EmpathyCallWindowFullscreen *self)
110 {
111   gint leave_fullscreen_width, leave_fullscreen_height;
112   GdkScreen *screen;
113   GdkRectangle fullscreen_rect;
114   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
115
116   g_assert (self->is_fullscreen);
117
118   g_return_if_fail (priv->parent_window != NULL);
119
120   if (priv->popup_creation_in_progress)
121     return;
122
123   if (!gtk_window_is_active (GTK_WINDOW (priv->parent_window)))
124     return;
125
126   priv->popup_creation_in_progress = TRUE;
127
128   empathy_call_window_fullscreen_set_cursor_visible (self, TRUE);
129
130   /* Obtaining the screen rectangle */
131   screen = gtk_window_get_screen (GTK_WINDOW (priv->parent_window));
132   gdk_screen_get_monitor_geometry (screen,
133       gdk_screen_get_monitor_at_window (screen,
134           gtk_widget_get_window (GTK_WIDGET (priv->parent_window))),
135       &fullscreen_rect);
136
137   /* Getting the popup window sizes */
138   gtk_window_get_size (GTK_WINDOW (priv->leave_fullscreen_popup),
139       &leave_fullscreen_width, &leave_fullscreen_height);
140
141   /* Moving the popup to the top-right corner (if the direction is LTR) or the
142      top-left corner (if the direction is RTL).*/
143   if (gtk_widget_get_direction (priv->leave_fullscreen_popup)
144         == GTK_TEXT_DIR_LTR)
145     {
146       gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup),
147           fullscreen_rect.width + fullscreen_rect.x - leave_fullscreen_width,
148           fullscreen_rect.y);
149
150     }
151   else
152     {
153       gtk_window_move (GTK_WINDOW (priv->leave_fullscreen_popup),
154           fullscreen_rect.x, fullscreen_rect.y);
155     }
156
157   gtk_widget_show_all (priv->leave_fullscreen_popup);
158   empathy_call_window_fullscreen_add_popup_timeout (self);
159
160   priv->popup_creation_in_progress = FALSE;
161 }
162
163 static gboolean
164 empathy_call_window_fullscreen_hide_popup (EmpathyCallWindowFullscreen *fs)
165 {
166   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
167
168   if (priv->video_widget == NULL || !fs->is_fullscreen)
169     return TRUE;
170
171   gtk_widget_hide (priv->leave_fullscreen_popup);
172   empathy_call_window_fullscreen_remove_popup_timeout (fs);
173
174   empathy_call_window_fullscreen_set_cursor_visible (fs, FALSE);
175
176   return FALSE;
177 }
178
179 static void
180 empathy_call_window_fullscreen_init (EmpathyCallWindowFullscreen *self)
181 {
182   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
183   GtkBuilder *gui;
184   gchar *filename;
185
186   filename = empathy_file_lookup ("empathy-call-window-fullscreen.ui", "src");
187   gui = empathy_builder_get_file (filename,
188     "leave_fullscreen_window", &priv->leave_fullscreen_popup,
189     "leave_fullscreen_button", &self->leave_fullscreen_button,
190     NULL);
191
192   gtk_widget_add_events (priv->leave_fullscreen_popup, GDK_POINTER_MOTION_MASK);
193
194   g_object_unref (gui);
195   g_free (filename);
196 }
197
198 static void
199 empathy_call_window_fullscreen_class_init (
200     EmpathyCallWindowFullscreenClass *klass)
201 {
202   GObjectClass *object_class = G_OBJECT_CLASS (klass);
203
204   g_type_class_add_private (klass, sizeof (EmpathyCallWindowFullscreenPriv));
205
206   object_class->dispose = empathy_call_window_fullscreen_dispose;
207   object_class->finalize = empathy_call_window_fullscreen_finalize;
208 }
209
210 void
211 empathy_call_window_fullscreen_dispose (GObject *object)
212 {
213   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object);
214   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
215
216   if (priv->dispose_has_run)
217     return;
218
219   priv->dispose_has_run = TRUE;
220
221   if (priv->leave_fullscreen_popup != NULL)
222     gtk_widget_destroy (priv->leave_fullscreen_popup);
223   priv->leave_fullscreen_popup = NULL;
224
225   if (G_OBJECT_CLASS (empathy_call_window_fullscreen_parent_class)->dispose)
226     {
227       G_OBJECT_CLASS (
228           empathy_call_window_fullscreen_parent_class)->dispose (object);
229     }
230 }
231
232 void
233 empathy_call_window_fullscreen_finalize (GObject *object)
234 {
235   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (object);
236
237   empathy_call_window_fullscreen_remove_popup_timeout (self);
238
239   G_OBJECT_CLASS (
240       empathy_call_window_fullscreen_parent_class)->finalize (object);
241 }
242
243 static void
244 empathy_call_window_fullscreen_parent_window_notify (GtkWidget *parent_window,
245     GParamSpec *property, EmpathyCallWindowFullscreen *fs)
246 {
247   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
248
249   if (!fs->is_fullscreen)
250     return;
251
252   if (parent_window == GTK_WIDGET (priv->parent_window) &&
253         !gtk_window_is_active (GTK_WINDOW (parent_window)))
254     {
255       empathy_call_window_fullscreen_hide_popup (fs);
256       empathy_call_window_fullscreen_set_cursor_visible (fs, TRUE);
257     }
258 }
259
260 EmpathyCallWindowFullscreen *
261 empathy_call_window_fullscreen_new (EmpathyCallWindow *parent_window)
262 {
263   EmpathyCallWindowFullscreen *self = EMPATHY_CALL_WINDOW_FULLSCREEN (
264     g_object_new (EMPATHY_TYPE_CALL_WINDOW_FULLSCREEN, NULL));
265   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
266
267   priv->parent_window = parent_window;
268   g_signal_connect (G_OBJECT (priv->parent_window), "notify::is-active",
269     G_CALLBACK (empathy_call_window_fullscreen_parent_window_notify), self);
270
271   return self;
272 }
273
274 void
275 empathy_call_window_fullscreen_set_fullscreen (EmpathyCallWindowFullscreen *fs,
276   gboolean set_fullscreen)
277 {
278
279   if (set_fullscreen)
280       empathy_call_window_fullscreen_remove_popup_timeout (fs);
281   else
282       empathy_call_window_fullscreen_hide_popup (fs);
283
284   empathy_call_window_fullscreen_set_cursor_visible (fs, !set_fullscreen);
285   fs->is_fullscreen = set_fullscreen;
286 }
287
288 static void
289 video_widget_destroy_cb (GtkWidget *widget,
290     EmpathyCallWindowFullscreen *self)
291 {
292   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (self);
293
294   priv->video_widget = NULL;
295 }
296
297 void
298 empathy_call_window_fullscreen_set_video_widget (
299     EmpathyCallWindowFullscreen *fs,
300     GtkWidget *video_widget)
301 {
302   EmpathyCallWindowFullscreenPriv *priv = GET_PRIV (fs);
303   priv->video_widget = video_widget;
304
305   tp_g_signal_connect_object (video_widget, "destroy",
306       G_CALLBACK (video_widget_destroy_cb), fs, 0);
307 }