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