From d615efd1bc513e5782f6824cec0a26547ee43bdf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Luk=C3=A1=C5=A1=20Bezdi=C4=8Dka?= <255993@mail.muni.cz> Date: Mon, 4 Apr 2011 23:03:49 +0200 Subject: [PATCH] [shell] dualscreen progress --- shell/ev-dualscreen.c | 310 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 shell/ev-dualscreen.c diff --git a/shell/ev-dualscreen.c b/shell/ev-dualscreen.c new file mode 100644 index 00000000..0f94912e --- /dev/null +++ b/shell/ev-dualscreen.c @@ -0,0 +1,310 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */ +/* this file is part of evince, a gnome document viewer + * + * + * Evince 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. + * + * Evince 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "ev-dualscreen.h" +#include "ev-window.h" +#include "ev-view.h" + +struct _EvDSCWindowPrivate { + GtkWidget *main_box; + GtkWidget *menubar; + GtkWidget *overview; + GtkWidget *notesview; + EvDocumentModel *model; + EvDocument * notesdocument; + + GtkWidget *overview_scrolled_window; + GtkWidget *notesview_scrolled_window; + + EvWindow *presentation_window; + EvDocument * presentation_document; + gint moveback_monitor; +} EvDSCWindowPrivate; + +#define EV_DSCWINDOW_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_DSCWINDOW, EvDSCWindowPrivate)) +#define PAGE_CACHE_SIZE 52428800 /* 50MB */ + +/*static gpointer parent_class = NULL;*/ + +G_DEFINE_TYPE (EvDSCWindow, ev_dscwindow, GTK_TYPE_WINDOW) + +/** + * ev_dscwindow_switch_monitors: Bring the presentation window and the control window each on the other monitor. + * + * @widget: Callback widget + * @self: EvDSCWindow + **/ +static gboolean +ev_dscwindow_switch_monitors (GtkWidget *widget, EvDSCWindow *self) +{ +/* ++ if (!EV_IS_DSCWINDOW (self)) ++ return FALSE; ++ ++ EvDSCWindowPrivate *priv = EV_DSCWINDOW_GET_PRIVATE (self); ++ ++ gint num_monitors = get_num_monitors (GTK_WINDOW (self)); ++ ++ if (num_monitors == 2) { ++ GtkWindow * presentation_window = GTK_WINDOW (priv->presentation_window); ++ GdkScreen * screen = gtk_window_get_screen (presentation_window); ++ ++ gint monitor_1 = gdk_screen_get_monitor_at_window (screen, ++ GTK_WIDGET (presentation_window)->window); ++ ++ gint monitor_2 = (monitor_1 + 1) % 2; ++ ++ GdkRectangle coords; ++ gdk_screen_get_monitor_geometry (screen, monitor_2, &coords); ++ ev_window_stop_presentation (priv->presentation_window); ++ gtk_window_move (presentation_window, coords.x, coords.y); ++ ev_window_run_presentation (priv->presentation_window); ++ priv->moveback_monitor = monitor_1; ++ ++ gdk_screen_get_monitor_geometry (screen, monitor_1, &coords); ++ gtk_window_unmaximize (GTK_WINDOW (self)); ++ gtk_window_move (GTK_WINDOW (self), coords.x, coords.y); ++ gtk_window_maximize (GTK_WINDOW (self)); ++ }*/ + return TRUE; +} + +/** + * ev_dscwindow_notes_interaction: User wants to load a different file as notes. + **/ +static gboolean +ev_dscwindow_notes_interaction (GtkContainer *container, EvDSCWindow *self) +{ +/* ++ EvDSCWindowPrivate *priv = EV_DSCWINDOW_GET_PRIVATE (self); ++ GtkWidget *dialog; ++ ++ dialog = gtk_file_chooser_dialog_new ( ++ _("Open Document"), ++ GTK_WINDOW (self), ++ GTK_FILE_CHOOSER_ACTION_OPEN, ++ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, ++ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, ++ NULL); ++ ++ ev_document_factory_add_filters (dialog, NULL); ++ gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), FALSE); ++ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE); ++ ++ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) ++ { ++ char * uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); ++ GError * error = NULL; ++ ev_view_set_loading (EV_VIEW (priv->notesview), TRUE); ++ ++ if (priv->notesdocument) { ++ ev_document_load (priv->notesdocument, uri, &error); ++ } else { ++ priv->notesdocument = ev_document_factory_get_document (uri, ++ &error); ++ } ++ g_free (uri); ++ if (error == NULL){ ++ ev_view_set_document (EV_VIEW (priv->notesview), ++ priv->notesdocument); ++ /* TODO: go to the same page that is open at the moment, or ++ * move the presentation to the beginning. *//* ++ } ++ } ++ gtk_widget_destroy (dialog); +*/ + return TRUE; +} + +/** + * ev_dscwindow_end: Stop presentation mode. + */ +static gboolean +ev_dscwindow_end (GtkWidget *widget, GdkEvent *event) +{ + gtk_widget_destroy (GTK_WIDGET (ev_dscwindow_get_control ())); + return TRUE; +} + + + +/** +* ev_dscwindow_init: Initialize multihead presentation +* +* @self: EvDSCWindow. +* +* ev_dscwindow_set_presentation has to be called afterwards for loading in a document. TBD +**/ +static void +ev_dscwindow_init (EvDSCWindow *ev_dscwindow) +{ + ev_dscwindow->priv = EV_DSCWINDOW_GET_PRIVATE (ev_dscwindow); + ev_dscwindow->priv->moveback_monitor = -1; + ev_dscwindow->priv->notesdocument = NULL; + + gtk_window_set_title (GTK_WINDOW (self), _("Presentation Control")); + + GtkWidget *h = gtk_hpaned_new (); + GtkWidget *v = gtk_vbox_new (FALSE, 0); + + ev_dscwindow->priv->overview_scrolled_window = GTK_WIDGET (g_object_new ( + GTK_TYPE_SCROLLED_WINDOW, "shadow-type", GTK_SHADOW_IN, NULL)); + gtk_box_pack_start_defaults (GTK_BOX (v), priv->overview_scrolled_window); + + ev_dscwindow->priv->model = ev_document_model_new (); + ev_dscwindow->priv->overview = ev_view_new (); + ev_view_set_page_cache_size (EV_VIEW (ev_dscwindow->priv->overview), PAGE_CACHE_SIZE); + ev_view_set_model (EV_VIEW (ev_dscwindow->priv->overview), ev_dscwindow->priv->model); + ev_document_model_set_continuous (ev_dscwindow->priv->model, TRUE); + ev_document_model_set_dual_page (ev_dscwindow->priv->model, FALSE); + ev_document_model_set_sizing_mode (ev_dscwindow->priv->model, EV_SIZING_BEST_FIT); + + + gtk_container_add (GTK_CONTAINER (priv->overview_scrolled_window), + priv->overview); + + + GtkWidget *e = gtk_expander_new (_("Expensive features")); + gtk_expander_set_expanded (GTK_EXPANDER (e), TRUE); + + GtkWidget *t = gtk_toolbar_new (); + + GtkToolItem* b_switch = gtk_tool_button_new (NULL, _("Switch monitors")); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (b_switch), "object-flip-horizontal"); + gtk_toolbar_insert (GTK_TOOLBAR (t), b_switch, -1); + g_signal_connect (b_switch, "clicked", + G_CALLBACK (ev_dscwindow_switch_monitors), self); + + GtkToolItem* b_notes = gtk_tool_button_new (NULL, _("Load notes ...")); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (b_notes), "object-flip-horizontal"); + gtk_toolbar_insert (GTK_TOOLBAR (t), b_notes, -1); + g_signal_connect (b_notes, "clicked", + G_CALLBACK (ev_dscwindow_notes_interaction), self); + + GtkToolItem* b_close = gtk_tool_button_new (NULL, _("End presentation")); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (b_close), "view-restore"); + gtk_toolbar_insert (GTK_TOOLBAR (t), b_close, -1); + g_signal_connect (b_close, "clicked", + G_CALLBACK (ev_dscwindow_end), NULL); + + gtk_container_add (GTK_CONTAINER (e), t); + gtk_box_pack_end (GTK_BOX (v), e, FALSE, TRUE, 0); + gtk_paned_add1 (GTK_PANED (h), v); + +/* + priv->notesview_scrolled_window = GTK_WIDGET (g_object_new ( + GTK_TYPE_SCROLLED_WINDOW, "shadow-type", GTK_SHADOW_IN, NULL)); + gtk_paned_add2 (GTK_PANED (h), priv->notesview_scrolled_window); + + priv->notesview = ev_view_new (); + g_object_ref (priv->notesview); + ev_view_set_screen_dpi (EV_VIEW (priv->notesview), + get_screen_dpi (GTK_WINDOW (self))); ++ gtk_container_add (GTK_CONTAINER (priv->notesview_scrolled_window), ++ priv->notesview); ++ ++ ev_view_set_continuous (EV_VIEW (priv->notesview), FALSE); ++ ev_view_set_dual_page (EV_VIEW (priv->notesview), FALSE); ++ ev_view_set_sizing_mode (EV_VIEW (priv->notesview), EV_SIZING_BEST_FIT); ++ } ++ ++ gtk_paned_set_position (GTK_PANED (h), 400); ++ gtk_widget_show_all (h); ++ gtk_container_add (GTK_CONTAINER (self), h); ++ ++ /* fallback if we have >2 monitors (see window placement) */ +/*+ gtk_window_set_default_size (GTK_WINDOW (self), 800, 600); ++ ++ g_signal_connect (h, "notify::position", ++ G_CALLBACK (ev_dscwindow_handle_resized), self); ++ ++ g_signal_connect (self, "size-allocate", ++ G_CALLBACK (ev_dscwindow_handle_resized), self); ++ ++ /* This would just open new windows. */ +/*+ gtk_drag_dest_unset (GTK_WIDGET (priv->notesview)); ++ gtk_drag_dest_unset (GTK_WIDGET (priv->overview)); ++ ++ gint click = GDK_BUTTON1_MOTION_MASK | GDK_KEY_PRESS_MASK; ++ gtk_widget_add_events (GTK_WIDGET (priv->overview), click); ++ g_signal_connect (priv->notesview, "button-press-event", ++ G_CALLBACK (ev_dscwindow_notes_clicked), self); +*/ +} + + +static void +ev_dscwindow_dispose (GObject *obj) +{ + EvDSCWindow * self = EV_DSCWINDOW (obj); + EvDSCWindowPrivate *priv = ev_dscwindow->priv; + +/* if (EV_IS_VIEW (priv->overview) { + ev_document_model_set_document (priv->model, NULL); + ++ ev_view_set_document (EV_VIEW (priv->overview), NULL); ++ g_object_unref (priv->overview); ++ } ++ if (EV_IS_VIEW (priv->notesview)) { ++ ev_view_set_document (EV_VIEW (priv->notesview), NULL); ++ g_object_unref (priv->notesview); ++ }*/ + ev_window_stop_presentation (priv->presentation_window); + + if (priv->moveback_monitor >= 0) { + GtkWindow * presentation_window = GTK_WINDOW (priv->presentation_window); + GdkRectangle coords; + + gdk_screen_get_monitor_geometry ( + gtk_window_get_screen (presentation_window), + priv->moveback_monitor, &coords); + + gtk_window_move (presentation_window, coords.x, coords.y); + } + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + + +static void +ev_dscwindow_class_init (EvDSCWindowClass * klass) +{ +/* GObjectClass *g_object_class = G_OBJECT_CLASS (klass); + * parent_class = g_type_class_peek_parent (klass); + * g_type_class_add_private (klass, sizeof (EvDSCWindowPrivate)); + * g_object_class->dispose = ev_dscwindow_dispose; + */ +} + +GtkWidget * +ev_dscwindow_new (void) +{ + EvDSCWindow *dsc_window; + + dsc_window = g_object_new (EV_TYPE_DSCWINDOW, "type", GTK_WINDOW_TOPLEVEL, NULL); + return GTK_WIDGET (dsc_window); +} -- 2.39.3