[ekiga] ext-window: add remote video window



commit c139fc3102172fa84f8178c491667ca2844a0044
Author: VÃctor Manuel JÃquez Leal <vjaquez igalia com>
Date:   Thu Sep 6 17:05:05 2012 -0500

    ext-window: add remote video window
    
    This remote video widget will display the extended remote video stream.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687775

 lib/Makefile.am                            |    2 +
 lib/engine/gui/gtk-frontend/ext-window.cpp |  302 ++++++++++++++++++++++++++++
 lib/engine/gui/gtk-frontend/ext-window.h   |   68 +++++++
 3 files changed, 372 insertions(+), 0 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 43324c9..2f14b38 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -433,6 +433,8 @@ libekiga_la_SOURCES += \
 	$(engine_dir)/gui/gtk-frontend/book-view-gtk.cpp \
 	$(engine_dir)/gui/gtk-frontend/call-window.h \
 	$(engine_dir)/gui/gtk-frontend/call-window.cpp \
+	$(engine_dir)/gui/gtk-frontend/ext-window.h \
+	$(engine_dir)/gui/gtk-frontend/ext-window.cpp \
 	$(engine_dir)/gui/gtk-frontend/roster-view-gtk.h \
 	$(engine_dir)/gui/gtk-frontend/roster-view-gtk.cpp \
 	$(engine_dir)/gui/gtk-frontend/call-history-view-gtk.h \
diff --git a/lib/engine/gui/gtk-frontend/ext-window.cpp b/lib/engine/gui/gtk-frontend/ext-window.cpp
new file mode 100644
index 0000000..d6e0139
--- /dev/null
+++ b/lib/engine/gui/gtk-frontend/ext-window.cpp
@@ -0,0 +1,302 @@
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2012, Xunta de Galicia <ocfloss xunta es>
+ *
+ * Author: Victor Jaquez, Igalia S.L., AGASOL. <vjaquez igalia com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+#include "config.h"
+#include "ext-window.h"
+
+#ifndef WIN32
+#include <gdk/gdkx.h>
+#else
+#include "platform/winpaths.h"
+#include <gdk/gdkwin32.h>
+#endif
+
+#define USER_INTERFACE_KEY "/apps/" PACKAGE_NAME "/general/user_interface/"
+#define VIDEO_DISPLAY_KEY USER_INTERFACE_KEY "video_display/"
+
+G_DEFINE_TYPE (EkigaExtWindow, ekiga_ext_window, GTK_TYPE_WINDOW);
+
+struct _EkigaExtWindowPrivate {
+#ifndef WIN32
+  GdkGC* gc;
+#endif
+  GtkWidget *video, *zin, *zout;
+  boost::shared_ptr<Ekiga::VideoOutputCore> vocore;
+};
+
+static void
+set_zoom_buttons_sensitive (EkigaExtWindow *ew, guint zoom)
+{
+  gtk_widget_set_sensitive (ew->priv->zin, zoom != 200);
+  gtk_widget_set_sensitive (ew->priv->zout, zoom != 50);
+}
+
+static void
+zoom_in (G_GNUC_UNUSED GtkWidget *widget, gpointer user_data)
+{
+  guint zoom;
+
+  zoom = gm_conf_get_int (VIDEO_DISPLAY_KEY "ext_zoom");
+  if (zoom < 200)
+    zoom = zoom * 2;
+  gm_conf_set_int (VIDEO_DISPLAY_KEY "ext_zoom", zoom);
+
+  set_zoom_buttons_sensitive (EKIGA_EXT_WINDOW (user_data), zoom);
+}
+
+static void
+zoom_out (G_GNUC_UNUSED GtkWidget *widget, gpointer user_data)
+{
+  guint zoom;
+
+  zoom = gm_conf_get_int (VIDEO_DISPLAY_KEY "ext_zoom");
+  if (zoom > 50)
+    zoom = (guint) zoom / 2;
+  gm_conf_set_int (VIDEO_DISPLAY_KEY "ext_zoom", zoom);
+
+  set_zoom_buttons_sensitive (EKIGA_EXT_WINDOW (user_data), zoom);
+}
+
+static void
+gui_layout (EkigaExtWindow *ew)
+{
+  GtkWidget *zin, *zout, *vbox, *hbox;
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (ew), vbox);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  zin = gtk_button_new_from_stock (GTK_STOCK_ZOOM_IN);
+  gtk_box_pack_start (GTK_BOX (hbox), zin, FALSE, FALSE, 0);
+
+  zout = gtk_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
+  gtk_box_pack_start (GTK_BOX (hbox), zout, FALSE, FALSE, 0);
+
+  ew->priv->video = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), ew->priv->video, FALSE, FALSE, 0);
+
+  ew->priv->zin = zin;
+  ew->priv->zout = zout;
+
+  g_signal_connect (zin, "clicked", G_CALLBACK (zoom_in), ew);
+  g_signal_connect (zout, "clicked", G_CALLBACK (zoom_out), ew);
+
+  gtk_widget_show_all (vbox);
+
+  gtk_window_set_resizable (GTK_WINDOW (ew), FALSE);
+}
+
+static inline void
+clear_display_info (EkigaExtWindow *ew)
+{
+  Ekiga::DisplayInfo info;
+
+  info.x = 0;
+  info.y = 0;
+  info.widget_info_set = false;
+  info.zoom = 0;
+  info.mode = Ekiga::VO_MODE_UNSET;
+  info.config_info_set = false;
+#ifdef WIN32
+  info.hwnd = 0;
+#else
+  info.gc = 0;
+  info.window = 0;
+#endif
+
+  ew->priv->vocore->set_ext_display_info (info);
+}
+
+static GObject *
+constructor (GType type, guint n_properties, GObjectConstructParam *params)
+{
+  GObject *object;
+
+  object = G_OBJECT_CLASS (ekiga_ext_window_parent_class)->constructor (type,
+                                                                        n_properties,
+                                                                        params);
+
+  gui_layout (EKIGA_EXT_WINDOW (object));
+
+  return object;
+}
+
+static void
+finalize (GObject* gobject)
+{
+  EkigaExtWindow *ew = EKIGA_EXT_WINDOW (gobject);
+
+#ifndef WIN32
+  if (ew->priv->gc) {
+    g_object_unref (ew->priv->gc);
+    ew->priv->gc = NULL;
+  }
+#endif
+
+  clear_display_info (ew);
+
+  G_OBJECT_CLASS (ekiga_ext_window_parent_class)->finalize (gobject);
+}
+
+static gboolean
+focus_in_event (GtkWidget *widget, GdkEventFocus *event)
+{
+  if (gtk_window_get_urgency_hint (GTK_WINDOW (widget)))
+    gtk_window_set_urgency_hint (GTK_WINDOW (widget), false);
+
+  return GTK_WIDGET_CLASS (ekiga_ext_window_parent_class)->focus_in_event (widget,
+                                                                           event);
+}
+
+static void
+show (GtkWidget *widget)
+{
+  GdkWindow *w = gtk_widget_get_window (widget);
+
+  if (w && gm_conf_get_bool (VIDEO_DISPLAY_KEY "stay_on_top"))
+    gdk_window_set_keep_above (w, true);
+
+  GTK_WIDGET_CLASS (ekiga_ext_window_parent_class)->show (widget);
+
+  gtk_widget_queue_draw (widget);
+}
+
+static gboolean
+expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+  EkigaExtWindow *ew = EKIGA_EXT_WINDOW (widget);
+  Ekiga::DisplayInfo info;
+  gboolean handled;
+  GtkAllocation alloc;
+
+  handled = GTK_WIDGET_CLASS (ekiga_ext_window_parent_class)->expose_event (widget,
+                                                                            event);
+
+  gtk_widget_get_allocation (ew->priv->video, &alloc);
+  info.x = alloc.x;
+  info.y = alloc.y;
+
+#ifdef WIN32
+  info.hwnd = (HWND) GDK_WINDOW_HWND (gtk_widget_get_window (ew->priv->video));
+#else
+  if (!ew->priv->gc) {
+    ew->priv->gc = gdk_gc_new (gtk_widget_get_window (ew->priv->video));
+    g_return_val_if_fail (ew->priv->gc != NULL, handled);
+  }
+
+  info.gc = GDK_GC_XGC (ew->priv->gc);
+
+  info.window = GDK_WINDOW_XWINDOW (gtk_widget_get_window (ew->priv->video));
+  g_return_val_if_fail (info.window != 0, handled);
+
+  gdk_flush ();
+#endif
+
+  info.widget_info_set = TRUE;
+  info.mode = Ekiga::VO_MODE_REMOTE_EXT;
+  info.config_info_set = TRUE;
+
+  ew->priv->vocore->set_ext_display_info (info);
+
+  return handled;
+}
+
+static void
+ekiga_ext_window_class_init (EkigaExtWindowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructor = constructor;
+  object_class->finalize = finalize;
+
+  widget_class->show = show;
+  widget_class->expose_event = expose_event;
+  widget_class->focus_in_event = focus_in_event;
+
+  g_type_class_add_private (klass, sizeof (EkigaExtWindowPrivate));
+
+}
+
+static void
+ekiga_ext_window_init (EkigaExtWindow *ew)
+{
+  ew->priv = G_TYPE_INSTANCE_GET_PRIVATE (ew, EKIGA_TYPE_EXT_WINDOW,
+                                          EkigaExtWindowPrivate);
+}
+
+GtkWidget *
+ext_window_new (boost::shared_ptr<Ekiga::VideoOutputCore> &vocore)
+{
+  EkigaExtWindow *ew =
+    EKIGA_EXT_WINDOW (g_object_new (EKIGA_TYPE_EXT_WINDOW, NULL));
+
+  g_signal_connect (ew, "delete-event", G_CALLBACK (gtk_true), NULL);
+
+  ew->priv->vocore = vocore;
+
+  return GTK_WIDGET (ew);
+}
+
+void
+ekiga_ext_window_set_size (EkigaExtWindow *ew, int width, int height)
+{
+  int pw, ph;
+
+  g_return_if_fail (width > 0 && height > 0);
+
+  gtk_widget_get_size_request (ew->priv->video, &pw, &ph);
+
+  /* No size requisition yet
+   * It's our first call so we silently set the new requisition and exit...
+   */
+  if (pw == -1) {
+    gtk_widget_set_size_request (ew->priv->video, width, height);
+    return;
+  }
+
+  /* Do some kind of filtering here. We often get duplicate "size-changed" events...
+   * Note that we currently only bother about the width of the video.
+   */
+  if (pw == width)
+    return;
+
+  gtk_widget_set_size_request (ew->priv->video, width, height);
+  gdk_window_invalidate_rect (gtk_widget_get_window (GTK_WIDGET (ew)), NULL, TRUE);
+}
+
+void
+ekiga_ext_window_destroy (EkigaExtWindow *ew)
+{
+  clear_display_info (ew);
+
+  /* dirty cheats done dirt cheap: if gtk_widget_destroy it crashes */
+  gtk_widget_hide (GTK_WIDGET (ew));
+}
diff --git a/lib/engine/gui/gtk-frontend/ext-window.h b/lib/engine/gui/gtk-frontend/ext-window.h
new file mode 100644
index 0000000..f4f97b7
--- /dev/null
+++ b/lib/engine/gui/gtk-frontend/ext-window.h
@@ -0,0 +1,68 @@
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2012, Xunta de Galicia <ocfloss xunta es>
+ *
+ * Author: Victor Jaquez, Igalia S.L., AGASOL. <vjaquez igalia com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+#ifndef __EXT_WINDOW_H__
+#define __EXT_WINDOW_H__
+
+#include "gmwindow.h"
+#include "videooutput-core.h"
+
+G_BEGIN_DECLS
+
+#define EKIGA_TYPE_EXT_WINDOW			\
+	(ekiga_ext_window_get_type ())
+#define EKIGA_EXT_WINDOW(obj)			\
+	(G_TYPE_CHECK_INSTANCE_CAST ((obj), EKIGA_TYPE_EXT_WINDOW, EkigaExtWindow))
+#define EKIGA_EXT_WINDOW_CLASS(klass)		\
+	(G_TYPE_CHECK_CLASS_CAST ((klass), EKIGA_TYPE_EXT_WINDOW, EkigaExtWindowClass))
+#define EKIGA_IS_EXT_WINDOW(obj)		\
+	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EKIGA_TYPE_EXT_WINDOW))
+#define EKIGA_IS_EXT_WINDOW_CLASS(klass)	\
+	(G_TYPE_CHECK_CLASS_TYPE ((klass), EKIGA_TYPE_EXT_WINDOW))
+
+typedef struct _EkigaExtWindowPrivate EkigaExtWindowPrivate;
+typedef struct _EkigaExtWindow EkigaExtWindow;
+typedef struct _EkigaExtWindowClass EkigaExtWindowClass;
+
+struct _EkigaExtWindow {
+  GmWindow parent;
+  EkigaExtWindowPrivate *priv;
+};
+
+struct _EkigaExtWindowClass {
+  GmWindowClass parent;
+};
+
+GType ekiga_ext_window_get_type ();
+GtkWidget *ext_window_new (boost::shared_ptr<Ekiga::VideoOutputCore> &vocore);
+void ekiga_ext_window_set_size (EkigaExtWindow *cw, int width, int height);
+void ekiga_ext_window_destroy (EkigaExtWindow *ew);
+
+G_END_DECLS
+
+#endif /* __EXT_WINDOW_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]