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