Dear list,

attached is a patch that adds presentation mode capabilities to Xournal. It
opens a second window in full screen mode on another monitor with the zoom
level fixed to one. The standard window on the monitor with the pen enabled
is zoomable. This is intended to be used as teaching tool as replacement to
a blackboard in larger lecture halls. When simply mirroring the monitors I
figured one has to write quite big on the pen enabled monitor to be able to
write cleanly and thus wouldn't fit much content on a screen. With this
mode, one can zoom in on the control monitor to comfortably write cleanly,
while the studends see the whole page, also comfortable as it is projected
to a big overhead screen.

It is an ugly hack I do not request to be applied, but I want it to serve
as discussion base how to make this in a clean and portable way.

The main issue is that many calls to the canvas are direct, so it needed to
patch all the places that interact with the canvas at all. Since there is
also discussion to be able to replace the canvas implementation, would it
be a good idea to encapsulate a little more, to have "xo-canvas" as
pseudo-object class, that all places call, and where it could decide to
actually draw on two canvases, or to change the canvas implementation with
only having to alter a few places?

The second issue with this patch is more simpler pragmatic hacking. I
didn't bother to add options in the menu, it's simply another binary to be
called that will fail if it cannot detect two monitors. But thats less an
issue to add, when the former things are cleaned up. Some of the zooming
stuff is a little odd, since I didn't fully understand the code in
interaction with PDF, I changed it so the resolution looks good on the
presentation monitor, which is the important thing in this mode

Kind regards, Axel
diff --git a/src/main.c b/src/main.c
index 7d4e057..16b6417 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,7 +33,9 @@
 #include "xo-shapes.h"
 
 GtkWidget *winMain;
+GtkWidget *presentMain;
 GnomeCanvas *canvas;
+GnomeCanvas *canvas2;
 
 struct Journal journal; // the journal
 struct BgPdf bgpdf;  // the PDF loader stuff
@@ -45,13 +47,18 @@ double DEFAULT_ZOOM;
 void init_stuff (int argc, char *argv[])
 {
   GtkWidget *w;
+  GtkWidget *w2;
   GList *dev_list;
   GdkDevice *device;
+  GdkRectangle screenRect;
   GdkScreen *screen;
   int i, j;
   struct Brush *b;
   gboolean can_xinput, success;
   gchar *tmppath, *tmpfn;
+  gint mMon; // main monitor
+  gint nMon; // max monitors
+  gint pMon; // present monitor
 
   // create some data structures needed to populate the preferences
   ui.default_page.bg = g_new(struct Background, 1);
@@ -63,8 +70,35 @@ void init_stuff (int argc, char *argv[])
   ui.configfile = g_build_filename(tmppath, CONFIG_FILE, NULL);
   g_free(tmppath);
 
+  screen = gtk_widget_get_screen(winMain);
+  nMon = gdk_screen_get_n_monitors(screen);
+
+  if( nMon < 2 )
+  {
+    printf("No presentation monitor\n");
+
+    GtkWidget *dialog = gtk_message_dialog_new (
+       NULL,
+       GTK_DIALOG_DESTROY_WITH_PARENT,
+       GTK_MESSAGE_ERROR,
+       GTK_BUTTONS_OK,
+       "Cannot start Xournal in presentation mode\nas there is no presentation monitor.\n");
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (dialog);
+	exit(1);
+  }
+
+  mMon = gdk_screen_get_primary_monitor(screen);
+  pMon = mMon == 0 ? 1 : 0;
+  gdk_screen_get_monitor_geometry(screen, pMon, &screenRect);
+  gtk_window_move(GTK_WINDOW(presentMain), screenRect.x, screenRect.y);
+  gtk_window_fullscreen(GTK_WINDOW( presentMain ));
+ 
   // initialize preferences
-  init_config_default();
+  init_config_default(screenRect.width, screenRect.height);
+  gdk_screen_get_monitor_geometry(screen, mMon, &screenRect);
+  gtk_window_move(GTK_WINDOW(winMain), screenRect.x, screenRect.y);
+
   load_config_from_file();
   ui.font_name = g_strdup(ui.default_font_name);
   ui.font_size = ui.default_font_size;
@@ -72,6 +106,7 @@ void init_stuff (int argc, char *argv[])
 
   // we need an empty canvas prior to creating the journal structures
   canvas = GNOME_CANVAS (gnome_canvas_new_aa ());
+  canvas2 = GNOME_CANVAS (gnome_canvas_new_aa ());
 
   // initialize data
   ui.default_page.bg->canvas_item = NULL;
@@ -86,9 +121,9 @@ void init_stuff (int argc, char *argv[])
   undo = NULL; redo = NULL;
   journal.pages = NULL;
   bgpdf.status = STATUS_NOT_INIT;
-
-  new_journal();  
   
+  new_journal( );  
+
   ui.cur_item_type = ITEM_NONE;
   ui.cur_item = NULL;
   ui.cur_path.coords = NULL;
@@ -125,12 +160,12 @@ void init_stuff (int argc, char *argv[])
   reset_recognizer();
 
   // initialize various interface elements
-  
+
   gtk_window_set_default_size(GTK_WINDOW (winMain), ui.window_default_width, ui.window_default_height);
   if (ui.maximize_at_start) gtk_window_maximize(GTK_WINDOW (winMain));
   update_toolbar_and_menu();
   update_font_button();
-
+  
   gtk_check_menu_item_set_active(
     GTK_CHECK_MENU_ITEM(GET_COMPONENT("journalApplyAllPages")), ui.bg_apply_all_pages);
   gtk_check_menu_item_set_active(
@@ -154,6 +189,7 @@ void init_stuff (int argc, char *argv[])
           G_CALLBACK(handle_activate_signal), NULL);
   gtk_container_forall(GTK_CONTAINER(winMain), unset_flags, (gpointer)GTK_CAN_FOCUS);
   GTK_WIDGET_SET_FLAGS(GTK_WIDGET(canvas), GTK_CAN_FOCUS);
+  GTK_WIDGET_SET_FLAGS(GTK_WIDGET(canvas2), GTK_CAN_FOCUS);
   GTK_WIDGET_SET_FLAGS(GTK_WIDGET(GET_COMPONENT("spinPageNo")), GTK_CAN_FOCUS);
   
   // install hooks on button/key/activation events to make the spinPageNo lose focus
@@ -174,6 +210,21 @@ void init_stuff (int argc, char *argv[])
   gnome_canvas_set_center_scroll_region (canvas, TRUE);
   gtk_layout_get_hadjustment(GTK_LAYOUT (canvas))->step_increment = ui.scrollbar_step_increment;
   gtk_layout_get_vadjustment(GTK_LAYOUT (canvas))->step_increment = ui.scrollbar_step_increment;
+  
+  // set up and initialize the presentation canvas
+  
+  gtk_widget_show (GTK_WIDGET (canvas2));
+  w2 = GTK_WIDGET (g_object_get_data(G_OBJECT (presentMain), "presentMain"));
+  gtk_container_add (GTK_CONTAINER (w2), GTK_WIDGET (canvas2));
+  gtk_widget_set_events (GTK_WIDGET (canvas2), 
+     GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | 
+     GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | 
+     GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+     GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK);
+  gnome_canvas_set_pixels_per_unit (canvas2, 1.0);
+  gnome_canvas_set_center_scroll_region (canvas2, TRUE);
+  gtk_layout_get_hadjustment(GTK_LAYOUT (canvas2))->step_increment = ui.scrollbar_step_increment;
+  gtk_layout_get_vadjustment(GTK_LAYOUT (canvas2))->step_increment = ui.scrollbar_step_increment;
 
   // set up the page size and canvas size
   update_page_stuff();
@@ -213,7 +264,8 @@ void init_stuff (int argc, char *argv[])
                     NULL);
   g_object_set_data (G_OBJECT (winMain), "canvas", canvas);
 
-  screen = gtk_widget_get_screen(winMain);
+  g_object_set_data (G_OBJECT (presentMain), "canvas", canvas2);
+
   ui.screen_width = gdk_screen_get_width(screen);
   ui.screen_height = gdk_screen_get_height(screen);
   
@@ -272,6 +324,7 @@ void init_stuff (int argc, char *argv[])
   // show everything...
   
   gtk_widget_show (winMain);
+  gtk_widget_show (presentMain);
   update_cursor();
 
   /* this will cause extension events to get enabled/disabled, but
@@ -368,9 +421,11 @@ main (int argc, char *argv[])
    * the project. Delete any components that you don't want shown initially.
    */
   winMain = create_winMain ();
-  
+  presentMain = create_presentMain( );
+
   init_stuff (argc, argv);
   gtk_window_set_icon(GTK_WINDOW(winMain), create_pixbuf("xournal.png"));
+  gtk_window_set_icon(GTK_WINDOW(presentMain), create_pixbuf("xournal.png"));
   
   gtk_main ();
   
diff --git a/src/xo-callbacks.c b/src/xo-callbacks.c
index 128078f..92768c9 100644
--- a/src/xo-callbacks.c
+++ b/src/xo-callbacks.c
@@ -50,6 +50,7 @@ on_fileNew_activate                    (GtkMenuItem     *menuitem,
     update_page_stuff();
     gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
   }
 }
 
@@ -111,6 +112,7 @@ on_fileNewBackground_activate          (GtkMenuItem     *menuitem,
   new_journal();
   ui.zoom = ui.startup_zoom;
   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
   update_page_stuff();
   success = init_bgpdf(filename, TRUE, file_domain);
   set_cursor_busy(FALSE);
@@ -458,6 +460,7 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
   double tmp_x, tmp_y;
   gchar *tmpstr;
   GnomeCanvasGroup *group;
+  GnomeCanvasGroup *group2;
   
   end_text();
   if (undo == NULL) return; // nothing to undo!
@@ -466,7 +469,9 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
   if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT || undo->type == ITEM_IMAGE) {
     // we're keeping the stroke info, but deleting the canvas item
     gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
+    gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item2));
     undo->item->canvas_item = NULL;
+    undo->item->canvas_item2 = NULL;
     // we also remove the object from its layer!
     undo->layer->items = g_list_remove(undo->layer->items, undo->item);
     undo->layer->nitems--;
@@ -478,20 +483,30 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
       for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
         it = (struct Item *)itemlist->data;
         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
+        gtk_object_destroy(GTK_OBJECT(it->canvas_item2));
         it->canvas_item = NULL;
+        it->canvas_item2 = NULL;
         undo->layer->items = g_list_remove(undo->layer->items, it);
         undo->layer->nitems--;
       }
       // recreate the deleted one
-      make_canvas_item_one(undo->layer->group, erasure->item);
+      make_canvas_item_one(undo->layer->group, erasure->item, 1);
+      make_canvas_item_one(undo->layer->group2, erasure->item, 2);
       
       undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
                                                              erasure->npos);
       if (erasure->npos == 0)
+      {
         lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
+        lower_canvas_item_to(undo->layer->group2, erasure->item->canvas_item2, NULL);
+      }
       else
+      {
         lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
           ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
+        lower_canvas_item_to(undo->layer->group2, erasure->item->canvas_item2,
+          ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item2);
+      }
       undo->layer->nitems++;
     }
   }
@@ -531,9 +546,12 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
   else if (undo->type == ITEM_NEW_PAGE) {
     // unmap the page; keep the page & its empty layer in memory
     if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
+    if (undo->page->group2!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group2));
       // also destroys the background and layer's canvas items
     undo->page->group = NULL;
+    undo->page->group2 = NULL;
     undo->page->bg->canvas_item = NULL;
+    undo->page->bg->canvas_item2 = NULL;
     journal.pages = g_list_remove(journal.pages, undo->page);
     journal.npages--;
     if (ui.cur_page == undo->page) ui.cur_page = NULL;
@@ -552,9 +570,12 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
     for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
       it = (struct Item *)itemlist->data;
       if (it->canvas_item != NULL) {
-        if (undo->layer != undo->layer2)
+        if (undo->layer != undo->layer2) {
           gnome_canvas_item_reparent(it->canvas_item, undo->layer->group);
+          gnome_canvas_item_reparent(it->canvas_item2, undo->layer->group2);
+		}
         gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
+        gnome_canvas_item_move(it->canvas_item2, -undo->val_x, -undo->val_y);
       }
     }
     move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y,
@@ -569,7 +590,9 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
     for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
       it = (struct Item *)itemlist->data;
       gtk_object_destroy(GTK_OBJECT(it->canvas_item));
+      gtk_object_destroy(GTK_OBJECT(it->canvas_item2));
       it->canvas_item = NULL;
+      it->canvas_item2 = NULL;
       undo->layer->items = g_list_remove(undo->layer->items, it);
       undo->layer->nitems--;
     }
@@ -577,7 +600,9 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
   else if (undo->type == ITEM_NEW_LAYER) {
     // unmap the layer; keep the empty layer in memory
     if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
+    if (undo->layer->group2!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group2));
     undo->layer->group = NULL;
+    undo->layer->group2 = NULL;
     undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
     undo->page->nlayers--;
     do_switch_page(ui.pageno, FALSE, FALSE); // don't stay with bad cur_layer info
@@ -586,24 +611,35 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
     // special case of -1: deleted the last layer, created a new one
     if (undo->val == -1) {
       if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
+      if (undo->layer2->group2!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group2));
       undo->layer2->group = NULL;
+      undo->layer2->group2 = NULL;
       undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
       undo->page->nlayers--;
     }
     // re-map the layer
     undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       undo->page->group, gnome_canvas_group_get_type(), NULL);
+    undo->layer->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      undo->page->group2, gnome_canvas_group_get_type(), NULL);
+
     lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
       (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
             g_list_nth_data(undo->page->layers, undo->val-1))->group) :
             undo->page->bg->canvas_item);
+    lower_canvas_item_to(undo->page->group2, GNOME_CANVAS_ITEM(undo->layer->group2),
+      (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
+            g_list_nth_data(undo->page->layers, undo->val-1))->group2) :
+            undo->page->bg->canvas_item2);
     undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
                                      (undo->val >= 0) ? undo->val:0);
     undo->page->nlayers++;
     
     for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next)
-      make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data);
-
+    {
+      make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data, 1);
+      make_canvas_item_one(undo->layer->group2, (struct Item *)itemlist->data, 2);
+	}
     do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others...
   }
   else if (undo->type == ITEM_REPAINTSEL) {
@@ -616,12 +652,22 @@ on_editUndo_activate                   (GtkMenuItem     *menuitem,
       if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
         // remark: a variable-width item might have lost its variable-width
         group = (GnomeCanvasGroup *) it->canvas_item->parent;
+        group2 = (GnomeCanvasGroup *) it->canvas_item2->parent;
         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
-        make_canvas_item_one(group, it);
+        gtk_object_destroy(GTK_OBJECT(it->canvas_item2));
+        make_canvas_item_one(group, it, 1);
+        make_canvas_item_one(group2, it, 1);
       }
       if (it->type == ITEM_TEXT && it->canvas_item != NULL)
+      {
         gnome_canvas_item_set(it->canvas_item, 
           "fill-color-rgba", it->brush.color_rgba, NULL);
+	  }
+      if (it->type == ITEM_TEXT && it->canvas_item2 != NULL)
+      {
+        gnome_canvas_item_set(it->canvas_item2, 
+          "fill-color-rgba", it->brush.color_rgba, NULL);
+	  }
     }
   }
   else if (undo->type == ITEM_TEXT_EDIT) {
@@ -673,6 +719,7 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
   double tmp_x, tmp_y;
   gchar *tmpstr;
   GnomeCanvasGroup *group;
+  GnomeCanvasGroup *group2;
   
   end_text();
   if (redo == NULL) return; // nothing to redo!
@@ -680,7 +727,8 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
   reset_recognizer(); // safer
   if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT || redo->type == ITEM_IMAGE) {
     // re-create the canvas_item
-    make_canvas_item_one(redo->layer->group, redo->item);
+    make_canvas_item_one(redo->layer->group, redo->item, 1);
+    make_canvas_item_one(redo->layer->group2, redo->item, 2);
     // reinsert the item on its layer
     redo->layer->items = g_list_append(redo->layer->items, redo->item);
     redo->layer->nitems++;
@@ -692,14 +740,18 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
       // re-create all the created items
       for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
         it = (struct Item *)itemlist->data;
-        make_canvas_item_one(redo->layer->group, it);
+        make_canvas_item_one(redo->layer->group, it, 1);
+        make_canvas_item_one(redo->layer->group2, it, 2);
         redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
         redo->layer->nitems++;
         lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
+        lower_canvas_item_to(redo->layer->group2, it->canvas_item2, erasure->item->canvas_item2);
       }
       // re-delete the deleted one
       gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
+      gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item2));
       erasure->item->canvas_item = NULL;
+      erasure->item->canvas_item2 = NULL;
       redo->layer->items = g_list_delete_link(redo->layer->items, target);
       redo->layer->nitems--;
     }
@@ -742,11 +794,15 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
     redo->page->bg->canvas_item = NULL;
     redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
+    redo->page->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      gnome_canvas_root(canvas2), gnome_canvas_clipgroup_get_type(), NULL);
     make_page_clipbox(redo->page);
     update_canvas_bg(redo->page);
     l = (struct Layer *)redo->page->layers->data;
     l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       redo->page->group, gnome_canvas_group_get_type(), NULL);
+    l->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      redo->page->group2, gnome_canvas_group_get_type(), NULL);
     
     journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
     journal.npages++;
@@ -755,13 +811,17 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
   else if (redo->type == ITEM_DELETE_PAGE) {
     // unmap all the canvas items
     gtk_object_destroy(GTK_OBJECT(redo->page->group));
+    gtk_object_destroy(GTK_OBJECT(redo->page->group2));
     redo->page->group = NULL;
+    redo->page->group2 = NULL;
     redo->page->bg->canvas_item = NULL;
+    redo->page->bg->canvas_item2 = NULL;
     for (list = redo->page->layers; list!=NULL; list = list->next) {
       l = (struct Layer *)list->data;
       for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
         ((struct Item *)itemlist->data)->canvas_item = NULL;
       l->group = NULL;
+      l->group2 = NULL;
     }
     journal.pages = g_list_remove(journal.pages, redo->page);
     journal.npages--;
@@ -775,8 +835,12 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
       it = (struct Item *)itemlist->data;
       if (it->canvas_item != NULL) {
         if (redo->layer != redo->layer2)
+		{
           gnome_canvas_item_reparent(it->canvas_item, redo->layer2->group);
+          gnome_canvas_item_reparent(it->canvas_item2, redo->layer2->group2);
+		}
         gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
+        gnome_canvas_item_move(it->canvas_item2, redo->val_x, redo->val_y);
       }
     }
     move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y,
@@ -789,7 +853,8 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
   else if (redo->type == ITEM_PASTE) {
     for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
       it = (struct Item *)itemlist->data;
-      make_canvas_item_one(redo->layer->group, it);
+      make_canvas_item_one(redo->layer->group, it, 1);
+      make_canvas_item_one(redo->layer->group2, it, 2);
       redo->layer->items = g_list_append(redo->layer->items, it);
       redo->layer->nitems++;
     }
@@ -797,24 +862,39 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
   else if (redo->type == ITEM_NEW_LAYER) {
     redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
         redo->page->group, gnome_canvas_group_get_type(), NULL);
+    redo->layer->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+        redo->page->group2, gnome_canvas_group_get_type(), NULL);
+
     lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
       (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
             g_list_nth_data(redo->page->layers, redo->val-1))->group) :
             redo->page->bg->canvas_item);
+    lower_canvas_item_to(redo->page->group2, GNOME_CANVAS_ITEM(redo->layer->group2),
+      (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
+            g_list_nth_data(redo->page->layers, redo->val-1))->group2) :
+            redo->page->bg->canvas_item2);
+
     redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
     redo->page->nlayers++;
     do_switch_page(ui.pageno, FALSE, FALSE);
   }
   else if (redo->type == ITEM_DELETE_LAYER) {
     gtk_object_destroy(GTK_OBJECT(redo->layer->group));
+    gtk_object_destroy(GTK_OBJECT(redo->layer->group2));
     redo->layer->group = NULL;
+    redo->layer->group2 = NULL;
     for (list=redo->layer->items; list!=NULL; list=list->next)
+	{
       ((struct Item *)list->data)->canvas_item = NULL;
+      ((struct Item *)list->data)->canvas_item2 = NULL;
+	}
     redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
     redo->page->nlayers--;
     if (redo->val == -1) {
       redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
         redo->page->group, gnome_canvas_group_get_type(), NULL);
+      redo->layer2->group2 = (GnomeCanvasGroup *)gnome_canvas_item_new(
+        redo->page->group2, gnome_canvas_group_get_type(), NULL);
       redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
       redo->page->nlayers++;
     }
@@ -830,17 +910,31 @@ on_editRedo_activate                   (GtkMenuItem     *menuitem,
       if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
         // remark: a variable-width item might have lost its variable-width
         group = (GnomeCanvasGroup *) it->canvas_item->parent;
+        group2 = (GnomeCanvasGroup *) it->canvas_item2->parent;
         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
-        make_canvas_item_one(group, it);
+        gtk_object_destroy(GTK_OBJECT(it->canvas_item2));
+        make_canvas_item_one(group, it, 1);
+        make_canvas_item_one(group, it, 2);
       }
+
       if (it->type == ITEM_TEXT && it->canvas_item != NULL)
         gnome_canvas_item_set(it->canvas_item, 
           "fill-color-rgba", it->brush.color_rgba, NULL);
+      if (it->type == ITEM_TEXT && it->canvas_item != NULL)
+        gnome_canvas_item_set(it->canvas_item2, 
+          "fill-color-rgba", it->brush.color_rgba, NULL);
+
       if (it->type == ITEM_IMAGE && it->canvas_item != NULL) {
         // remark: a variable-width item might have lost its variable-width
         group = (GnomeCanvasGroup *) it->canvas_item->parent;
         gtk_object_destroy(GTK_OBJECT(it->canvas_item));
-        make_canvas_item_one(group, it);
+        make_canvas_item_one(group, it, 1);
+      }
+      if (it->type == ITEM_IMAGE && it->canvas_item2 != NULL) {
+        // remark: a variable-width item might have lost its variable-width
+        group = (GnomeCanvasGroup *) it->canvas_item2->parent;
+        gtk_object_destroy(GTK_OBJECT(it->canvas_item2));
+        make_canvas_item_one(group2, it, 2);
       }
     }
   }
@@ -933,6 +1027,7 @@ void do_view_modeswitch(int view_mode)
   gtk_adjustment_set_value(h_adj, xscroll + pg->hoffset*ui.zoom);
   // force a refresh
   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
 }
 
 void
@@ -1059,8 +1154,10 @@ on_viewShowLayer_activate              (GtkMenuItem     *menuitem,
   if (ui.layerno == ui.cur_page->nlayers-1) return;
   reset_selection();
   ui.layerno++;
+  printf("OVSA!!!\n"),
   ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
   gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+  gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group2));
   update_page_stuff();
 }
 
@@ -1073,7 +1170,9 @@ on_viewHideLayer_activate              (GtkMenuItem     *menuitem,
   if (ui.layerno == -1) return;
   reset_selection();
   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+  gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group2));
   ui.layerno--;
+  printf("OVHLA!!!\n");
   if (ui.layerno<0) ui.cur_layer = NULL;
   else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
   update_page_stuff();
@@ -1088,7 +1187,8 @@ on_journalNewPageBefore_activate       (GtkMenuItem     *menuitem,
 
   end_text();
   reset_selection();
-  pg = new_page(ui.cur_page);
+  //pg = new_page(ui.cur_page);
+  pg = new_page(&ui.default_page);
   journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
   journal.npages++;
   do_switch_page(ui.pageno, TRUE, TRUE);
@@ -1108,7 +1208,8 @@ on_journalNewPageAfter_activate        (GtkMenuItem     *menuitem,
 
   end_text();
   reset_selection();
-  pg = new_page(ui.cur_page);
+  //pg = new_page(ui.cur_page);
+  pg = new_page(&ui.default_page);
   journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
   journal.npages++;
   do_switch_page(ui.pageno+1, TRUE, TRUE);
@@ -1128,7 +1229,8 @@ on_journalNewPageEnd_activate          (GtkMenuItem     *menuitem,
 
   end_text();
   reset_selection();
-  pg = new_page((struct Page *)g_list_last(journal.pages)->data);
+  //pg = new_page((struct Page *)g_list_last(journal.pages)->data);
+  pg = new_page(&ui.default_page);
   journal.pages = g_list_append(journal.pages, pg);
   journal.npages++;
   do_switch_page(journal.npages-1, TRUE, TRUE);
@@ -1158,13 +1260,20 @@ on_journalDeletePage_activate          (GtkMenuItem     *menuitem,
 
   // unmap all the canvas items  
   gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
+  gtk_object_destroy(GTK_OBJECT(ui.cur_page->group2));
   ui.cur_page->group = NULL;
+  ui.cur_page->group2 = NULL;
   ui.cur_page->bg->canvas_item = NULL;
+  ui.cur_page->bg->canvas_item2 = NULL;
   for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
     l = (struct Layer *)layerlist->data;
     for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
+    {
       ((struct Item *)itemlist->data)->canvas_item = NULL;
+      ((struct Item *)itemlist->data)->canvas_item2 = NULL;
+    }
     l->group = NULL;
+    l->group2 = NULL;
   }
   
   journal.pages = g_list_remove(journal.pages, ui.cur_page);
@@ -1187,10 +1296,17 @@ on_journalNewLayer_activate            (GtkMenuItem     *menuitem,
   l = g_new(struct Layer, 1);
   l->items = NULL;
   l->nitems = 0;
+
   l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
     ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
+  l->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+    ui.cur_page->group2, gnome_canvas_group_get_type(), NULL);
+
   lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
     (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
+  lower_canvas_item_to(ui.cur_page->group2, GNOME_CANVAS_ITEM(l->group2),
+    (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group2)):(ui.cur_page->bg->canvas_item2));
+
   ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
   ui.cur_layer = l;
   ui.layerno++;
@@ -1223,9 +1339,14 @@ on_journalDeleteLayer_activate         (GtkMenuItem     *menuitem,
   undo->page = ui.cur_page;
   // delete all the canvas items
   gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
+  gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group2));
   ui.cur_layer->group = NULL;
+  ui.cur_layer->group2 = NULL;
   for (list=ui.cur_layer->items; list!=NULL; list=list->next)
+  {
     ((struct Item *)list->data)->canvas_item = NULL;
+    ((struct Item *)list->data)->canvas_item2 = NULL;
+  }
 
   ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
 
@@ -1239,8 +1360,12 @@ on_journalDeleteLayer_activate         (GtkMenuItem     *menuitem,
     ui.cur_layer = g_new(struct Layer, 1);
     ui.cur_layer->items = NULL;
     ui.cur_layer->nitems = 0;
+
     ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
+    ui.cur_layer->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      ui.cur_page->group2, gnome_canvas_group_get_type(), NULL);
+
     ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
     undo->val = -1;
     undo->layer2 = ui.cur_layer;
@@ -1562,13 +1687,14 @@ on_journalLoadBackground_activate      (GtkMenuItem     *menuitem,
   }
 
   g_list_free(bglist);
-  if (ui.zoom != DEFAULT_ZOOM) {
+//  if (ui.zoom != DEFAULT_ZOOM) {
     ui.zoom = DEFAULT_ZOOM;
     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
     rescale_text_items();
     rescale_bg_pixmaps();
     rescale_images();
-  }
+//  }
   do_switch_page(ui.pageno, TRUE, TRUE);
 }
 
@@ -1609,13 +1735,14 @@ on_journalScreenshot_activate          (GtkMenuItem     *menuitem,
   make_page_clipbox(ui.cur_page);
   update_canvas_bg(ui.cur_page);
 
-  if (ui.zoom != DEFAULT_ZOOM) {
+//  if (ui.zoom != DEFAULT_ZOOM) {
     ui.zoom = DEFAULT_ZOOM;
     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
     rescale_text_items();
     rescale_bg_pixmaps();
     rescale_images();
-  }
+//  }
   do_switch_page(ui.pageno, TRUE, TRUE);
 }
 
@@ -2695,6 +2822,11 @@ on_canvas_proximity_event              (GtkWidget       *widget,
   printf("DEBUG: proximity %s (%s)\n", 
      (event->type == GDK_PROXIMITY_IN)?"in":"out", event->device->name);
 #endif
+  // ignore proximity events from touch device
+  if(ui.use_xinput && !strcmp(event->device->name, ui.device_for_touch))
+  {
+    return FALSE;
+  }
   ui.in_proximity = (event->type==GDK_PROXIMITY_IN);
   return FALSE;
 }
@@ -2784,7 +2916,11 @@ on_canvas_motion_notify_event          (GtkWidget       *widget,
   GdkModifierType mask;
 
   // if pen is sending motion events then it's in proximity
-  if (event->device->source == GDK_SOURCE_PEN) ui.in_proximity = TRUE;
+  if (event->device->source == GDK_SOURCE_PEN
+    &&(!ui.use_xinput && !strcmp(event->device->name, ui.device_for_touch)))
+  {
+    ui.in_proximity = TRUE;
+  }
   
   /* we don't care about this event unless some operation is in progress;
      or if there's a selection (then we might want to change the mouse
@@ -2887,6 +3023,8 @@ on_canvas_motion_notify_event          (GtkWidget       *widget,
     ui.selection->bbox.bottom = pt[1];
     gnome_canvas_item_set(ui.selection->canvas_item,
                                "x2", pt[0], "y2", pt[1], NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2,
+                               "x2", pt[0], "y2", pt[1], NULL);
   }
   else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
     continue_movesel((GdkEvent *)event);
@@ -2919,11 +3057,14 @@ on_comboLayer_changed                  (GtkComboBox     *combobox,
   reset_selection();
   while (val>ui.layerno) {
     ui.layerno++;
+	printf("OCLC\n");
     ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
     gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+    gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group2));
   }
   while (val<ui.layerno) {
     gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
+    gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group2));
     ui.layerno--;
     if (ui.layerno<0) ui.cur_layer = NULL;
     else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
@@ -3121,7 +3262,9 @@ on_journalDefaultBackground_activate   (GtkMenuItem     *menuitem,
     pg->width = ui.default_page.width;
     pg->height = ui.default_page.height;
     pg->bg->canvas_item = undo->bg->canvas_item;
+    pg->bg->canvas_item2 = undo->bg->canvas_item2;
     undo->bg->canvas_item = NULL;
+    undo->bg->canvas_item2 = NULL;
   
     make_page_clipbox(pg);
     update_canvas_bg(pg);
diff --git a/src/xo-clipboard.c b/src/xo-clipboard.c
index 7b8c43d..d6c77ab 100644
--- a/src/xo-clipboard.c
+++ b/src/xo-clipboard.c
@@ -239,7 +239,14 @@ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
       "fill-color-rgba", 0x80808040,
       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1,
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
+      "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
   make_dashed(ui.selection->canvas_item);
+  make_dashed(ui.selection->canvas_item2);
 
   while (nitems-- > 0) {
     item = g_new(struct Item, 1);
@@ -263,7 +270,8 @@ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
       }
       else item->widths = NULL;
       update_item_bbox(item);
-      make_canvas_item_one(ui.cur_layer->group, item);
+      make_canvas_item_one(ui.cur_layer->group, item, 1);
+      make_canvas_item_one(ui.cur_layer->group2, item, 2);
     }
     if (item->type == ITEM_TEXT) {
       g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
@@ -278,10 +286,12 @@ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
       item->font_name = g_malloc(len+1);
       g_memmove(item->font_name, p, len+1); p+= len+1;
       g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double);
-      make_canvas_item_one(ui.cur_layer->group, item);
+      make_canvas_item_one(ui.cur_layer->group, item, 1);
+      make_canvas_item_one(ui.cur_layer->group2, item, 2);
     }
     if (item->type == ITEM_IMAGE) {
       item->canvas_item = NULL;
+      item->canvas_item2 = NULL;
       item->image_png = NULL;
       item->image_png_len = 0;
       g_memmove(&item->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
@@ -297,7 +307,8 @@ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
       } else {
         item->image = NULL;
       }
-      make_canvas_item_one(ui.cur_layer->group, item);
+      make_canvas_item_one(ui.cur_layer->group, item, 1);
+      make_canvas_item_one(ui.cur_layer->group2, item, 2);
     }
   }
 
@@ -340,7 +351,8 @@ void clipboard_paste_text(gchar *text)
   item->font_name = g_strdup(ui.font_name);
   item->font_size = ui.font_size;
   item->bbox.left = pt[0]; item->bbox.top = pt[1];
-  make_canvas_item_one(ui.cur_layer->group, item);
+  make_canvas_item_one(ui.cur_layer->group, item, 1);
+  make_canvas_item_one(ui.cur_layer->group2, item, 2);
   update_item_bbox(item);
 
   // move the text to fit on the page if needed
@@ -349,6 +361,7 @@ void clipboard_paste_text(gchar *text)
   if (item->bbox.bottom > ui.cur_page->height) item->bbox.top += ui.cur_page->height-item->bbox.bottom;
   if (item->bbox.top < 0) item->bbox.top = 0;
   gnome_canvas_item_set(item->canvas_item, "x", item->bbox.left, "y", item->bbox.top, NULL);
+  gnome_canvas_item_set(item->canvas_item2, "x", item->bbox.left, "y", item->bbox.top, NULL);
   update_item_bbox(item);
   
   ui.selection->bbox = item->bbox;
@@ -358,7 +371,14 @@ void clipboard_paste_text(gchar *text)
       "fill-color-rgba", 0x80808040,
       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1,
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
+      "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
   make_dashed(ui.selection->canvas_item);
+  make_dashed(ui.selection->canvas_item2);
 
   prepare_new_undo();
   undo->type = ITEM_PASTE;
diff --git a/src/xo-file.c b/src/xo-file.c
index 5c00f17..addb605 100644
--- a/src/xo-file.c
+++ b/src/xo-file.c
@@ -13,6 +13,9 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define DEFAULT_ZOOM2 1.0 
+#define SCALE_MAX 5
+
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
@@ -548,10 +551,13 @@ void xoj_parser_start_element(GMarkupParseContext *context,
     tmpPage->layers = NULL;
     tmpPage->nlayers = 0;
     tmpPage->group = NULL;
+    tmpPage->group2 = NULL;
     tmpPage->bg = g_new(struct Background, 1);
     tmpPage->bg->type = -1;
     tmpPage->bg->canvas_item = NULL;
+    tmpPage->bg->canvas_item2 = NULL;
     tmpPage->bg->pixbuf = NULL;
+    tmpPage->bg->pixbuf2 = NULL;
     tmpPage->bg->filename = NULL;
     tmpJournal.pages = g_list_append(tmpJournal.pages, tmpPage);
     tmpJournal.npages++;
@@ -705,6 +711,7 @@ void xoj_parser_start_element(GMarkupParseContext *context,
     tmpLayer->items = NULL;
     tmpLayer->nitems = 0;
     tmpLayer->group = NULL;
+    tmpLayer->group2 = NULL;
     tmpPage->layers = g_list_append(tmpPage->layers, tmpLayer);
     tmpPage->nlayers++;
   }
@@ -717,6 +724,7 @@ void xoj_parser_start_element(GMarkupParseContext *context,
     tmpItem->type = ITEM_STROKE;
     tmpItem->path = NULL;
     tmpItem->canvas_item = NULL;
+    tmpItem->canvas_item2 = NULL;
     tmpItem->widths = NULL;
     tmpLayer->items = g_list_append(tmpLayer->items, tmpItem);
     tmpLayer->nitems++;
@@ -792,6 +800,7 @@ void xoj_parser_start_element(GMarkupParseContext *context,
     tmpItem = (struct Item *)g_malloc0(sizeof(struct Item));
     tmpItem->type = ITEM_TEXT;
     tmpItem->canvas_item = NULL;
+    tmpItem->canvas_item2 = NULL;
     tmpLayer->items = g_list_append(tmpLayer->items, tmpItem);
     tmpLayer->nitems++;
     // scan for font, size, x, y, and color attributes
@@ -852,6 +861,7 @@ void xoj_parser_start_element(GMarkupParseContext *context,
     tmpItem = (struct Item *)g_malloc0(sizeof(struct Item));
     tmpItem->type = ITEM_IMAGE;
     tmpItem->canvas_item = NULL;
+    tmpItem->canvas_item2 = NULL;
     tmpItem->image=NULL;
     tmpItem->image_png = NULL;
     tmpItem->image_png_len = 0;
@@ -1090,7 +1100,9 @@ gboolean open_journal(char *filename)
     while (bgpdf.status != STATUS_NOT_INIT) gtk_main_iteration();
     new_journal();
     ui.zoom = ui.startup_zoom;
+    ui.zoom2 = DEFAULT_ZOOM2;
     gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+    gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
     update_page_stuff();
     return init_bgpdf(filename, TRUE, DOMAIN_ABSOLUTE);
   }
@@ -1148,8 +1160,10 @@ gboolean open_journal(char *filename)
   ui.layerno = ui.cur_page->nlayers-1;
   ui.cur_layer = (struct Layer *)(g_list_last(ui.cur_page->layers)->data);
   ui.zoom = ui.startup_zoom;
+  ui.zoom2 = DEFAULT_ZOOM2;
   update_file_name(g_strdup(filename));
   gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+  gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
   make_canvas_items();
   update_page_stuff();
   rescale_bg_pixmaps(); // this requests the PDF pages if need be
@@ -1350,9 +1364,11 @@ gboolean bgpdf_scheduler_callback(gpointer data)
   struct BgPdfRequest *req;
   struct BgPdfPage *bgpg;
   GdkPixbuf *pixbuf;
+  GdkPixbuf *pixbuf2;
   GtkWidget *dialog;
   PopplerPage *pdfpage;
   gdouble height, width;
+  gdouble scalex, scaley, scale, scaleu;
   int scaled_height, scaled_width;
   GdkPixmap *pixmap;
   cairo_t *cr;
@@ -1366,6 +1382,7 @@ gboolean bgpdf_scheduler_callback(gpointer data)
 
   // use poppler to generate the page
   pixbuf = NULL;
+  pixbuf2 = NULL;
   pdfpage = poppler_document_get_page(bgpdf.document, req->pageno-1);
   if (pdfpage) {
 //    printf("DEBUG: Processing request for page %d at %f dpi\n", req->pageno, req->dpi);
@@ -1373,6 +1390,14 @@ gboolean bgpdf_scheduler_callback(gpointer data)
     poppler_page_get_size(pdfpage, &width, &height);
     scaled_width = (int) (req->dpi * width/72);
     scaled_height = (int) (req->dpi * height/72);
+    
+//	scaled_width2 = (int) (req->dpi2 * width/72);
+//  scaled_height2 = (int) (req->dpi2 * height/72);
+
+	scalex = (float)req->pwidth / width;
+	scaley = (float)req->pheight / height;
+	scale = scalex > scaley ? scalex: scaley;
+
 
     if (ui.poppler_force_cairo) { // poppler -> cairo -> pixmap -> pixbuf
       pixmap = gdk_pixmap_new(GTK_WIDGET(canvas)->window, scaled_width, scaled_height, -1);
@@ -1387,11 +1412,26 @@ gboolean bgpdf_scheduler_callback(gpointer data)
       g_object_unref(pixmap);
     }
     else { // directly poppler -> pixbuf: faster, but bitmap font bug
-      pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
-                 FALSE, 8, scaled_width, scaled_height);
+//      pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+//                 FALSE, 8, scaled_width, scaled_height);
+//      wrapper_poppler_page_render_to_pixbuf(
+//                pdfpage, 0, 0, scaled_width, scaled_height,
+//                req->dpi/72, 0, pixbuf);
+     
+	  scaleu = req->dpi/72;
+	  if( scaleu> SCALE_MAX ) scaleu = SCALE_MAX;
+
+	  pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+                 FALSE, 8, scaleu * req->pwidth, scaleu * req->pheight);
+      wrapper_poppler_page_render_to_pixbuf(
+                pdfpage, 0, 0, scaleu * req->pwidth, scaleu * req->pheight,
+                scaleu * scale, 0, pixbuf);
+
+      pixbuf2 = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+                 FALSE, 8, req->pwidth, req->pheight);
       wrapper_poppler_page_render_to_pixbuf(
-                pdfpage, 0, 0, scaled_width, scaled_height,
-                req->dpi/72, 0, pixbuf);
+                pdfpage, 0, 0, req->pwidth, req->pheight,
+                scale, 0, pixbuf2);
     }
     g_object_unref(pdfpage);
     set_cursor_busy(FALSE);
@@ -1402,15 +1442,23 @@ gboolean bgpdf_scheduler_callback(gpointer data)
     while (req->pageno > bgpdf.npages) {
       bgpg = g_new(struct BgPdfPage, 1);
       bgpg->pixbuf = NULL;
+      bgpg->pixbuf2 = NULL;
       bgpdf.pages = g_list_append(bgpdf.pages, bgpg);
       bgpdf.npages++;
     }
     bgpg = g_list_nth_data(bgpdf.pages, req->pageno-1);
     if (bgpg->pixbuf!=NULL) g_object_unref(bgpg->pixbuf);
+    if (bgpg->pixbuf2!=NULL) g_object_unref(bgpg->pixbuf2);
     bgpg->pixbuf = pixbuf;
     bgpg->dpi = req->dpi;
     bgpg->pixel_height = scaled_height;
     bgpg->pixel_width = scaled_width;
+
+    bgpg->pixbuf2 = pixbuf2;
+    bgpg->dpi2 = scale * 72.0;
+    bgpg->pixel_height2 = req->pheight;
+    bgpg->pixel_width2 = req->pwidth;
+
     bgpdf_update_bg(req->pageno, bgpg); // update all pages that have this bg
   } else { // failure
     if (!bgpdf.has_failed) {
@@ -1430,7 +1478,7 @@ gboolean bgpdf_scheduler_callback(gpointer data)
 
 /* make a request */
 
-gboolean add_bgpdf_request(int pageno, double zoom)
+gboolean add_bgpdf_request(int pageno, double zoom, int pwidth, int pheight)
 {
   struct BgPdfRequest *req, *cmp_req;
   GList *list;
@@ -1440,6 +1488,8 @@ gboolean add_bgpdf_request(int pageno, double zoom)
   req = g_new(struct BgPdfRequest, 1);
   req->pageno = pageno;
   req->dpi = 72*zoom;
+  req->pwidth = pwidth;
+  req->pheight = pheight;
 //  printf("DEBUG: Enqueuing request for page %d at %f dpi\n", pageno, req->dpi);
 
   // cancel any request this may supersede
@@ -1470,6 +1520,7 @@ void shutdown_bgpdf(void)
   for (list = bgpdf.pages; list != NULL; list = list->next) {
     pdfpg = (struct BgPdfPage *)list->data;
     if (pdfpg->pixbuf!=NULL) g_object_unref(pdfpg->pixbuf);
+    if (pdfpg->pixbuf2!=NULL) g_object_unref(pdfpg->pixbuf2);
     g_free(pdfpg);
   }
   g_list_free(bgpdf.pages);
@@ -1501,6 +1552,7 @@ gboolean init_bgpdf(char *pdfname, gboolean create_pages, int file_domain)
   struct Page *pg;
   PopplerPage *pdfpage;
   gdouble width, height;
+  gdouble scalex, scaley, scale;
   gchar *uri;
   
   if (bgpdf.status != STATUS_NOT_INIT) return FALSE;
@@ -1558,10 +1610,20 @@ gboolean init_bgpdf(char *pdfname, gboolean create_pages, int file_domain)
     bg->file_domain = bgpdf.file_domain;
     bg->file_page_seq = i;
     bg->pixbuf = NULL;
+    bg->pixbuf2 = NULL;
     bg->pixbuf_scale = 0;
     poppler_page_get_size(pdfpage, &width, &height);
     g_object_unref(pdfpage);
+
+	scalex = width / ui.pwidth;
+	scaley = height / ui.pheight;
+	scale = scalex > scaley ? scalex : scaley;
+
+	width = width / scale;
+	height = height / scale;
+
     if (pg == NULL) {
+      //pg = new_page_with_bg(bg, width, height);
       pg = new_page_with_bg(bg, width, height);
       journal.pages = g_list_append(journal.pages, pg);
       journal.npages++;
@@ -1588,9 +1650,14 @@ void bgpdf_update_bg(int pageno, struct BgPdfPage *bgpg)
     pg = (struct Page *)list->data;
     if (pg->bg->type == BG_PDF && pg->bg->file_page_seq == pageno) {
       if (pg->bg->pixbuf!=NULL) g_object_unref(pg->bg->pixbuf);
+      if (pg->bg->pixbuf2!=NULL) g_object_unref(pg->bg->pixbuf2);
       pg->bg->pixbuf = g_object_ref(bgpg->pixbuf);
+      pg->bg->pixbuf2 = g_object_ref(bgpg->pixbuf2);
       pg->bg->pixel_width = bgpg->pixel_width;
       pg->bg->pixel_height = bgpg->pixel_height;
+      
+	  pg->bg->pixel_width2 = bgpg->pixel_width2;
+      pg->bg->pixel_height2 = bgpg->pixel_height2;
       update_canvas_bg(pg);
     }
   }
@@ -1691,19 +1758,24 @@ void save_mru_list(void)
   fclose(f);
 }
 
-void init_config_default(void)
+void init_config_default( double pwidth, double pheight )
 {
   int i, j;
-
   DEFAULT_ZOOM = DISPLAY_DPI_DEFAULT/72.0;
+  ui.pwidth = pwidth;
+  ui.pheight = pheight;
   ui.zoom = ui.startup_zoom = 1.0*DEFAULT_ZOOM;
-  ui.default_page.height = 792.0;
-  ui.default_page.width = 612.0;
+  ui.zoom2 = DEFAULT_ZOOM2;
+//  ui.default_page.height = 792.0;
+//  ui.default_page.width = 612.0;
+  ui.default_page.height = pheight;
+  ui.default_page.width = pwidth;
   ui.default_page.bg->type = BG_SOLID;
   ui.default_page.bg->color_no = COLOR_WHITE;
   ui.default_page.bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE];
-  ui.default_page.bg->ruling = RULING_LINED;
-  ui.view_continuous = VIEW_MODE_CONTINUOUS;
+  ui.default_page.bg->ruling = RULING_GRAPH;
+  //ui.view_continuous = VIEW_MODE_CONTINUOUS;
+  ui.view_continuous = VIEW_MODE_ONE_PAGE;
   ui.allow_xinput = TRUE;
   ui.discard_corepointer = FALSE;
   ui.ignore_other_devices = TRUE;
@@ -2290,6 +2362,7 @@ void load_config_from_file(void)
   if (parse_keyval_float("general", "initial_zoom", &f, 
               MIN_ZOOM*100/DEFAULT_ZOOM, MAX_ZOOM*100/DEFAULT_ZOOM))
     ui.zoom = ui.startup_zoom = DEFAULT_ZOOM*f/100.0;
+  ui.zoom2 = DEFAULT_ZOOM2;
   parse_keyval_boolean("general", "window_maximize", &ui.maximize_at_start);
   parse_keyval_boolean("general", "window_fullscreen", &ui.fullscreen);
   parse_keyval_int("general", "window_width", &ui.window_default_width, 10, 5000);
@@ -2328,8 +2401,8 @@ void load_config_from_file(void)
   parse_keyval_boolean("general", "exportpdf_prefer_legacy", &ui.exportpdf_prefer_legacy);
   parse_keyval_boolean("general", "exportpdf_layers", &ui.exportpdf_layers);
   
-  parse_keyval_float("paper", "width", &ui.default_page.width, 1., 5000.);
-  parse_keyval_float("paper", "height", &ui.default_page.height, 1., 5000.);
+//  parse_keyval_float("paper", "width", &ui.default_page.width, 1., 5000.);
+//  parse_keyval_float("paper", "height", &ui.default_page.height, 1., 5000.);
   parse_keyval_enum_color("paper", "color", 
      &(ui.default_page.bg->color_no), &(ui.default_page.bg->color_rgba), 
      bgcolor_names, predef_bgcolors_rgba, COLOR_MAX);
diff --git a/src/xo-file.h b/src/xo-file.h
index 03556a4..b80c4c6 100644
--- a/src/xo-file.h
+++ b/src/xo-file.h
@@ -36,7 +36,7 @@ GList *attempt_load_gv_bg(char *filename);
 struct Background *attempt_screenshot_bg(void);
 
 void cancel_bgpdf_request(struct BgPdfRequest *req);
-gboolean add_bgpdf_request(int pageno, double zoom);
+gboolean add_bgpdf_request(int pageno, double zoom, int pwidth, int pheight);
 gboolean bgpdf_scheduler_callback(gpointer data);
 void shutdown_bgpdf(void);
 gboolean init_bgpdf(char *pdfname, gboolean create_pages, int file_domain);
@@ -50,7 +50,7 @@ void new_mru_entry(char *name);
 void delete_mru_entry(int which);
 void save_mru_list(void);
 
-void init_config_default(void);
+void init_config_default( double width, double height );
 void load_config_from_file(void);
 void save_config_to_file(void);
 
diff --git a/src/xo-image.c b/src/xo-image.c
index c16f8f4..8d7e667 100644
--- a/src/xo-image.c
+++ b/src/xo-image.c
@@ -49,6 +49,7 @@ void create_image_from_pixbuf(GdkPixbuf *pixbuf, double *pt)
   item = g_new(struct Item, 1);
   item->type = ITEM_IMAGE;
   item->canvas_item = NULL;
+  item->canvas_item2 = NULL;
   item->bbox.left = pt[0];
   item->bbox.top = pt[1];
   item->image = pixbuf;
@@ -67,7 +68,8 @@ void create_image_from_pixbuf(GdkPixbuf *pixbuf, double *pt)
   ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
   ui.cur_layer->nitems++;
   
-  make_canvas_item_one(ui.cur_layer->group, item);
+  make_canvas_item_one(ui.cur_layer->group, item, 1);
+  make_canvas_item_one(ui.cur_layer->group2, item, 2);
 
   // add undo information
   prepare_new_undo();
@@ -90,7 +92,14 @@ void create_image_from_pixbuf(GdkPixbuf *pixbuf, double *pt)
       "fill-color-rgba", 0x80808040,
       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1,
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
+      "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
   make_dashed(ui.selection->canvas_item);
+  make_dashed(ui.selection->canvas_item2);
   update_copy_paste_enabled();
 }
 
diff --git a/src/xo-interface.c b/src/xo-interface.c
index 9a05776..7853e6e 100644
--- a/src/xo-interface.c
+++ b/src/xo-interface.c
@@ -3257,3 +3257,18 @@ create_zoomDialog (void)
   return zoomDialog;
 }
 
+GtkWidget*
+create_presentMain (void)
+{
+  GtkWidget *presentMain;
+
+  presentMain = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (presentMain), _("Xournal Presentation"));
+  gtk_window_set_decorated (GTK_WINDOW (presentMain), FALSE);
+
+  /* Store pointers to all widgets, for use by lookup_widget(). */
+  GLADE_HOOKUP_OBJECT_NO_REF (presentMain, presentMain, "presentMain");
+
+  return presentMain;
+}
+
diff --git a/src/xo-interface.h b/src/xo-interface.h
index 1e86792..b9ebdca 100644
--- a/src/xo-interface.h
+++ b/src/xo-interface.h
@@ -6,3 +6,4 @@ GtkWidget* create_winMain (void);
 GtkWidget* create_papersizeDialog (void);
 GtkWidget* create_aboutDialog (void);
 GtkWidget* create_zoomDialog (void);
+GtkWidget* create_presentMain (void);
diff --git a/src/xo-misc.c b/src/xo-misc.c
index 330d5ee..8ad93b1 100644
--- a/src/xo-misc.c
+++ b/src/xo-misc.c
@@ -23,6 +23,7 @@
 #include <libgnomecanvas/libgnomecanvas.h>
 #include <gdk/gdkkeysyms.h>
 #include <time.h>
+#include <assert.h>
 
 #include "xournal.h"
 #include "xo-interface.h"
@@ -93,7 +94,7 @@ struct Page *new_page(struct Page *template)
 {
   struct Page *pg = (struct Page *) g_memdup(template, sizeof(struct Page));
   struct Layer *l = g_new(struct Layer, 1);
-  
+ 
   l->items = NULL;
   l->nitems = 0;
   pg->layers = g_list_append(NULL, l);
@@ -103,16 +104,22 @@ struct Page *new_page(struct Page *template)
   else 
     pg->bg = (struct Background *)g_memdup(template->bg, sizeof(struct Background));
   pg->bg->canvas_item = NULL;
+  pg->bg->canvas_item2 = NULL;
   if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
     g_object_ref(pg->bg->pixbuf);
+    g_object_ref(pg->bg->pixbuf2);
     refstring_ref(pg->bg->filename);
   }
   pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
+  pg->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      gnome_canvas_root(canvas2), gnome_canvas_clipgroup_get_type(), NULL);
   make_page_clipbox(pg);
   update_canvas_bg(pg);
   l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       pg->group, gnome_canvas_group_get_type(), NULL);
+  l->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      pg->group2, gnome_canvas_group_get_type(), NULL);
   
   return pg;
 }
@@ -125,21 +132,26 @@ struct Page *new_page_with_bg(struct Background *bg, double width, double height
 {
   struct Page *pg = g_new(struct Page, 1);
   struct Layer *l = g_new(struct Layer, 1);
-  
+
   l->items = NULL;
   l->nitems = 0;
   pg->layers = g_list_append(NULL, l);
   pg->nlayers = 1;
   pg->bg = bg;
   pg->bg->canvas_item = NULL;
+  pg->bg->canvas_item2 = NULL;
   pg->height = height;
   pg->width = width;
   pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
+  pg->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      gnome_canvas_root(canvas2), gnome_canvas_clipgroup_get_type(), NULL);
   make_page_clipbox(pg);
   update_canvas_bg(pg);
   l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
       pg->group, gnome_canvas_group_get_type(), NULL);
+  l->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+      pg->group2, gnome_canvas_group_get_type(), NULL);
   
   return pg;
 }
@@ -263,12 +275,14 @@ void clear_redo_stack(void)
           || redo->type == ITEM_NEW_DEFAULT_BG) {
       if (redo->bg->type == BG_PIXMAP || redo->bg->type == BG_PDF) {
         if (redo->bg->pixbuf!=NULL) g_object_unref(redo->bg->pixbuf);
+        if (redo->bg->pixbuf2!=NULL) g_object_unref(redo->bg->pixbuf2);
         refstring_unref(redo->bg->filename);
       }
       g_free(redo->bg);
     }
     else if (redo->type == ITEM_NEW_PAGE) {
       redo->page->group = NULL;
+      redo->page->group2 = NULL;
       delete_page(redo->page);
     }
     else if (redo->type == ITEM_MOVESEL || redo->type == ITEM_REPAINTSEL) {
@@ -335,6 +349,7 @@ void clear_undo_stack(void)
           || undo->type == ITEM_NEW_DEFAULT_BG) {
       if (undo->bg->type == BG_PIXMAP || undo->bg->type == BG_PDF) {
         if (undo->bg->pixbuf!=NULL) g_object_unref(undo->bg->pixbuf);
+        if (undo->bg->pixbuf2!=NULL) g_object_unref(undo->bg->pixbuf2);
         refstring_unref(undo->bg->filename);
       }
       g_free(undo->bg);
@@ -350,10 +365,12 @@ void clear_undo_stack(void)
     }
     else if (undo->type == ITEM_DELETE_LAYER) {
       undo->layer->group = NULL;
+      undo->layer->group2 = NULL;
       delete_layer(undo->layer);
     }
     else if (undo->type == ITEM_DELETE_PAGE) {
       undo->page->group = NULL;
+      undo->page->group2 = NULL;
       delete_page(undo->page);
     }
     else if (undo->type == ITEM_TEXT_EDIT || undo->type == ITEM_TEXT_ATTRIB) {
@@ -385,13 +402,16 @@ void delete_page(struct Page *pg)
   while (pg->layers!=NULL) {
     l = (struct Layer *)pg->layers->data;
     l->group = NULL;
+    l->group2 = NULL;
     delete_layer(l);
     pg->layers = g_list_delete_link(pg->layers, pg->layers);
   }
   if (pg->group!=NULL) gtk_object_destroy(GTK_OBJECT(pg->group));
+  if (pg->group2!=NULL) gtk_object_destroy(GTK_OBJECT(pg->group2));
               // this also destroys the background's canvas items
   if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
     if (pg->bg->pixbuf != NULL) g_object_unref(pg->bg->pixbuf);
+    if (pg->bg->pixbuf2 != NULL) g_object_unref(pg->bg->pixbuf2);
     if (pg->bg->filename != NULL) refstring_unref(pg->bg->filename);
   }
   g_free(pg->bg);
@@ -420,6 +440,7 @@ void delete_layer(struct Layer *l)
     l->items = g_list_delete_link(l->items, l->items);
   }
   if (l->group!= NULL) gtk_object_destroy(GTK_OBJECT(l->group));
+  if (l->group2!= NULL) gtk_object_destroy(GTK_OBJECT(l->group2));
   g_free(l);
 }
 
@@ -614,7 +635,7 @@ void update_item_bbox(struct Item *item)
 void make_page_clipbox(struct Page *pg)
 {
   GnomeCanvasPathDef *pg_clip;
-  
+ 
   pg_clip = gnome_canvas_path_def_new_sized(4);
   gnome_canvas_path_def_moveto(pg_clip, 0., 0.);
   gnome_canvas_path_def_lineto(pg_clip, 0., pg->height);
@@ -622,35 +643,73 @@ void make_page_clipbox(struct Page *pg)
   gnome_canvas_path_def_lineto(pg_clip, pg->width, 0.);
   gnome_canvas_path_def_closepath(pg_clip);
   gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group), "path", pg_clip, NULL);
+  gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group2), "path", pg_clip, NULL);
   gnome_canvas_path_def_unref(pg_clip);
 }
 
-void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item)
+void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item, int which)
 {
   PangoFontDescription *font_desc;
   GnomeCanvasPoints points;
   GtkWidget *dialog;
   int j;
 
+  assert( which == 1 || which == 2 );
+
   if (item->type == ITEM_STROKE) {
     if (!item->brush.variable_width)
-      item->canvas_item = gnome_canvas_item_new(group,
-            gnome_canvas_line_get_type(), "points", item->path,   
-            "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
-            "fill-color-rgba", item->brush.color_rgba,  
-            "width-units", item->brush.thickness, NULL);
+	{
+	  switch( which )
+	  {
+	  case 1 :
+        item->canvas_item = gnome_canvas_item_new(group,
+              gnome_canvas_line_get_type(), "points", item->path,   
+              "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+              "fill-color-rgba", item->brush.color_rgba,  
+              "width-units", item->brush.thickness, NULL);
+		break;
+	  case 2 :
+        item->canvas_item2 = gnome_canvas_item_new(group,
+              gnome_canvas_line_get_type(), "points", item->path,   
+              "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+              "fill-color-rgba", item->brush.color_rgba,  
+              "width-units", item->brush.thickness, NULL);
+		break;
+      }
+	}
     else {
-      item->canvas_item = gnome_canvas_item_new(group,
-            gnome_canvas_group_get_type(), NULL);
+      switch(which)
+	  {
+      case 1:
+        item->canvas_item = gnome_canvas_item_new(group,
+              gnome_canvas_group_get_type(), NULL);
+	    break;
+      case 2:
+        item->canvas_item2 = gnome_canvas_item_new(group,
+              gnome_canvas_group_get_type(), NULL);
+	    break;
+	  }
       points.num_points = 2;
       points.ref_count = 1;
       for (j = 0; j < item->path->num_points-1; j++) {
         points.coords = item->path->coords+2*j;
-        gnome_canvas_item_new((GnomeCanvasGroup *) item->canvas_item,
-              gnome_canvas_line_get_type(), "points", &points, 
-              "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, 
-              "fill-color-rgba", item->brush.color_rgba,
-              "width-units", item->widths[j], NULL);
+		switch(which)
+		{
+		case 1 :
+          gnome_canvas_item_new((GnomeCanvasGroup *) item->canvas_item,
+                gnome_canvas_line_get_type(), "points", &points, 
+                "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, 
+                "fill-color-rgba", item->brush.color_rgba,
+                "width-units", item->widths[j], NULL);
+		  break;
+		case 2 :
+          gnome_canvas_item_new((GnomeCanvasGroup *) item->canvas_item2,
+                gnome_canvas_line_get_type(), "points", &points, 
+                "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND, 
+                "fill-color-rgba", item->brush.color_rgba,
+                "width-units", item->widths[j], NULL);
+		  break;
+		}
       }
     }
   }
@@ -667,11 +726,23 @@ void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item)
     font_desc = pango_font_description_from_string(item->font_name);
     pango_font_description_set_absolute_size(font_desc, 
             item->font_size*ui.zoom*PANGO_SCALE);
-    item->canvas_item = gnome_canvas_item_new(group,
-          gnome_canvas_text_get_type(),
-          "x", item->bbox.left, "y", item->bbox.top, "anchor", GTK_ANCHOR_NW,
-          "font-desc", font_desc, "fill-color-rgba", item->brush.color_rgba,
-          "text", item->text, NULL);
+    switch(which)
+    {
+    case 1:
+      item->canvas_item = gnome_canvas_item_new(group,
+            gnome_canvas_text_get_type(),
+            "x", item->bbox.left, "y", item->bbox.top, "anchor", GTK_ANCHOR_NW,
+            "font-desc", font_desc, "fill-color-rgba", item->brush.color_rgba,
+            "text", item->text, NULL);
+	  break;
+	case 2 :
+      item->canvas_item2 = gnome_canvas_item_new(group,
+            gnome_canvas_text_get_type(),
+            "x", item->bbox.left, "y", item->bbox.top, "anchor", GTK_ANCHOR_NW,
+            "font-desc", font_desc, "fill-color-rgba", item->brush.color_rgba,
+            "text", item->text, NULL);
+	  break;
+	}
     update_item_bbox(item);
 #ifdef WIN32 // done
     if (!ui.warned_generate_fontconfig)  {
@@ -682,14 +753,29 @@ void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item)
 #endif
   }
   if (item->type == ITEM_IMAGE) {
-    item->canvas_item = gnome_canvas_item_new(group,
-          gnome_canvas_pixbuf_get_type(),
-          "pixbuf", item->image,
-          "x", item->bbox.left, "y", item->bbox.top,
-          "width", item->bbox.right - item->bbox.left,
-          "height", item->bbox.bottom - item->bbox.top,
-          "width-set", TRUE, "height-set", TRUE,
-          NULL);
+    switch(which)
+	{
+    case 1:
+      item->canvas_item = gnome_canvas_item_new(group,
+            gnome_canvas_pixbuf_get_type(),
+            "pixbuf", item->image,
+            "x", item->bbox.left, "y", item->bbox.top,
+            "width", item->bbox.right - item->bbox.left,
+            "height", item->bbox.bottom - item->bbox.top,
+            "width-set", TRUE, "height-set", TRUE,
+            NULL);
+    break;
+	case 2:
+      item->canvas_item2 = gnome_canvas_item_new(group,
+            gnome_canvas_pixbuf_get_type(),
+            "pixbuf", item->image,
+            "x", item->bbox.left, "y", item->bbox.top,
+            "width", item->bbox.right - item->bbox.left,
+            "height", item->bbox.bottom - item->bbox.top,
+            "width-set", TRUE, "height-set", TRUE,
+            NULL);
+  	  break;
+	}
   }
 }
 
@@ -707,16 +793,29 @@ void make_canvas_items(void)
          gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
       make_page_clipbox(pg);
     }
+    if (pg->group2 == NULL) {
+      pg->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+         gnome_canvas_root(canvas2), gnome_canvas_clipgroup_get_type(), NULL);
+    }
     if (pg->bg->canvas_item == NULL) update_canvas_bg(pg);
     for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
       l = (struct Layer *)layerlist->data;
+
       if (l->group == NULL)
         l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
            pg->group, gnome_canvas_group_get_type(), NULL);
+
+      if (l->group2 == NULL)
+        l->group2 = (GnomeCanvasGroup *) gnome_canvas_item_new(
+           pg->group2, gnome_canvas_group_get_type(), NULL);
+
       for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
         item = (struct Item *)itemlist->data;
+
         if (item->canvas_item == NULL)
-          make_canvas_item_one(l->group, item);
+          make_canvas_item_one(l->group, item, 1);
+        if (item->canvas_item2 == NULL)
+          make_canvas_item_one(l->group2, item, 2);
       }
     }
   }
@@ -725,6 +824,7 @@ void make_canvas_items(void)
 void update_canvas_bg(struct Page *pg)
 {
   GnomeCanvasGroup *group;
+  GnomeCanvasGroup *group2;
   GnomeCanvasPoints *seg;
   GdkPixbuf *scaled_pix;
   double *pt;
@@ -734,17 +834,27 @@ void update_canvas_bg(struct Page *pg)
   
   if (pg->bg->canvas_item != NULL)
     gtk_object_destroy(GTK_OBJECT(pg->bg->canvas_item));
+  if (pg->bg->canvas_item2 != NULL)
+    gtk_object_destroy(GTK_OBJECT(pg->bg->canvas_item2));
   pg->bg->canvas_item = NULL;
-  
+  pg->bg->canvas_item2 = NULL;
+ 
   if (pg->bg->type == BG_SOLID)
   {
     pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
                                gnome_canvas_group_get_type(), NULL);
+    pg->bg->canvas_item2 = gnome_canvas_item_new(pg->group2,
+                               gnome_canvas_group_get_type(), NULL);
     group = GNOME_CANVAS_GROUP(pg->bg->canvas_item);
+    group2 = GNOME_CANVAS_GROUP(pg->bg->canvas_item2);
     lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
+    lower_canvas_item_to(pg->group2, pg->bg->canvas_item2, NULL);
     gnome_canvas_item_new(group, gnome_canvas_rect_get_type(),
       "x1", 0., "x2", pg->width, "y1", 0., "y2", pg->height,
       "fill-color-rgba", pg->bg->color_rgba, NULL);
+    gnome_canvas_item_new(group2, gnome_canvas_rect_get_type(),
+      "x1", 0., "x2", pg->width, "y1", 0., "y2", pg->height,
+      "fill-color-rgba", pg->bg->color_rgba, NULL);
     if (pg->bg->ruling == RULING_NONE) return;
     seg = gnome_canvas_points_new(2);
     pt = seg->coords;
@@ -801,20 +911,47 @@ void update_canvas_bg(struct Page *pg)
     if (pg->bg->pixbuf == NULL) return;
     is_well_scaled = (fabs(pg->bg->pixel_width - pg->width*ui.zoom) < 2.
                    && fabs(pg->bg->pixel_height - pg->height*ui.zoom) < 2.);
+	/*
     if (is_well_scaled)
+	{
       pg->bg->canvas_item = gnome_canvas_item_new(pg->group, 
           gnome_canvas_pixbuf_get_type(), 
           "pixbuf", pg->bg->pixbuf,
           "width-in-pixels", TRUE, "height-in-pixels", TRUE, 
           NULL);
+	}
     else
+	{
+			*/
       pg->bg->canvas_item = gnome_canvas_item_new(pg->group, 
           gnome_canvas_pixbuf_get_type(), 
           "pixbuf", pg->bg->pixbuf,
           "width", pg->width, "height", pg->height, 
           "width-set", TRUE, "height-set", TRUE, 
           NULL);
+//	}
     lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
+
+	// XXX
+/*    if (is_well_scaled)
+	{
+      pg->bg->canvas_item2 = gnome_canvas_item_new(pg->group2, 
+          gnome_canvas_pixbuf_get_type(), 
+          "pixbuf", pg->bg->pixbuf2,
+          "width-in-pixels", TRUE, "height-in-pixels", TRUE, 
+          NULL);
+	}
+    else
+	{*/
+      pg->bg->canvas_item2 = gnome_canvas_item_new(pg->group2, 
+          gnome_canvas_pixbuf_get_type(), 
+          "pixbuf", pg->bg->pixbuf2,
+          "width", pg->width, "height", pg->height, 
+          "width-set", TRUE, "height-set", TRUE, 
+          NULL);
+//	}
+
+    lower_canvas_item_to(pg->group2, pg->bg->canvas_item2, NULL);
   }
 }
 
@@ -848,6 +985,7 @@ void rescale_bg_pixmaps(void)
   GdkPixbuf *pix;
   gboolean is_well_scaled;
   gdouble zoom_to_request;
+  gdouble zoom_to_request2;
   
   for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
     pg = (struct Page *)pglist->data;
@@ -875,9 +1013,13 @@ void rescale_bg_pixmaps(void)
       }
       // request an asynchronous update to a better pixmap if needed
       zoom_to_request = MIN(ui.zoom, MAX_SAFE_RENDER_DPI/72.0);
-      if (pg->bg->pixbuf_scale == zoom_to_request) continue;
-      if (add_bgpdf_request(pg->bg->file_page_seq, zoom_to_request))
+//      zoom_to_request2 = MIN(ui.zoom2, MAX_SAFE_RENDER_DPI/72.0);
+//      if (pg->bg->pixbuf_scale == zoom_to_request) continue; XXX
+      if (add_bgpdf_request(pg->bg->file_page_seq, zoom_to_request, pg->width, pg->height))
+	  {
         pg->bg->pixbuf_scale = zoom_to_request;
+		// XXX
+      }
     }
   }
 }
@@ -1411,6 +1553,8 @@ void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all)
       layer = (struct Layer *)list->data;
       if (layer->group!=NULL)
         gnome_canvas_item_show(GNOME_CANVAS_ITEM(layer->group));
+      if (layer->group2!=NULL)
+        gnome_canvas_item_show(GNOME_CANVAS_ITEM(layer->group2));
     }
   
   ui.cur_page = g_list_nth_data(journal.pages, ui.pageno);
@@ -1428,12 +1572,19 @@ void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all)
     gnome_canvas_scroll_to(canvas, cx, cy);
     
     if (refresh_all) 
+	{
       gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+      gnome_canvas_set_pixels_per_unit(canvas2, ui.zoom2);
+	}
     else if (!ui.view_continuous)
+	{
       gnome_canvas_item_move(GNOME_CANVAS_ITEM(ui.cur_page->group), 0., 0.);
+      gnome_canvas_item_move(GNOME_CANVAS_ITEM(ui.cur_page->group2), 0., 0.);
+	}
   }
 }
 
+// XXX
 void update_page_stuff(void)
 {
   gchar tmp[10];
@@ -1488,11 +1639,29 @@ void update_page_stuff(void)
             "x", pg->hoffset, "y", pg->voffset, NULL);
         gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
       } else {
-        if (pg->group!=NULL) gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group));
+        if (pg->group!=NULL)
+		{
+		  gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group));
+		}
       }
     }
     gnome_canvas_set_scroll_region(canvas, 0, 0, ui.cur_page->width, ui.cur_page->height);
   }
+    
+  for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
+    pg = (struct Page *)pglist->data;
+    if (pg == ui.cur_page && pg->group!=NULL) {
+      gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group2), 
+          "x", 0., "y", 0., NULL);
+      gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group2));
+    } else {
+      if (pg->group!=NULL)
+  	  { 
+        gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group2));
+      }
+    }
+  }
+  gnome_canvas_set_scroll_region(canvas2, 0, 0, ui.cur_page->width, ui.cur_page->height);
 
   // update the page / layer info at bottom of screen
 
@@ -1873,6 +2042,7 @@ void process_paperstyle_activate(GtkMenuItem *menuitem, int style)
         pg->bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE];
         pg->bg->filename = NULL;
         pg->bg->pixbuf = NULL;
+        pg->bg->pixbuf2 = NULL;
         must_upd = TRUE;
       }
       pg->bg->ruling = style;
@@ -1929,6 +2099,8 @@ void reset_selection(void)
   if (ui.selection == NULL) return;
   if (ui.selection->canvas_item != NULL) 
     gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item));
+  if (ui.selection->canvas_item2 != NULL) 
+    gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item2));
   g_list_free(ui.selection->items);
   g_free(ui.selection);
   ui.selection = NULL;
@@ -1982,6 +2154,7 @@ void move_journal_items_by(GList *itemlist, double dx, double dy,
         if (link != NULL) refitem = ((struct Item *)(link->data))->canvas_item;
         else refitem = NULL;
         lower_canvas_item_to(l2->group, item->canvas_item, refitem);
+        lower_canvas_item_to(l2->group2, item->canvas_item2, refitem);
       }
       depths = depths->next;
     }
@@ -2058,7 +2231,11 @@ void resize_journal_items_by(GList *itemlist, double scaling_x, double scaling_y
     if (item->canvas_item!=NULL) {
       group = (GnomeCanvasGroup *) item->canvas_item->parent;
       gtk_object_destroy(GTK_OBJECT(item->canvas_item));
-      make_canvas_item_one(group, item);
+      make_canvas_item_one(group, item, 1);
+
+	  group = (GnomeCanvasGroup *) item->canvas_item2->parent;
+      gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
+      make_canvas_item_one(group, item, 2);
     }
   }
 }
diff --git a/src/xo-misc.h b/src/xo-misc.h
index 177ab36..21d521a 100644
--- a/src/xo-misc.h
+++ b/src/xo-misc.h
@@ -47,7 +47,7 @@ void emergency_enable_xinput(GdkInputMode mode);
 void update_item_bbox(struct Item *item);
 void make_page_clipbox(struct Page *pg);
 void make_canvas_items(void);
-void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item);
+void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item, int which);
 void update_canvas_bg(struct Page *pg);
 gboolean is_visible(struct Page *pg);
 void rescale_bg_pixmaps(void);
diff --git a/src/xo-paint.c b/src/xo-paint.c
index 2331ff7..f562e03 100644
--- a/src/xo-paint.c
+++ b/src/xo-paint.c
@@ -146,6 +146,7 @@ void update_cursor(void)
   }
   
   gdk_window_set_cursor(GTK_WIDGET(canvas)->window, ui.cursor);
+  gdk_window_set_cursor(GTK_WIDGET(canvas2)->window, ui.cursor);
 }
 
 /* adjust the cursor shape if it hovers near a selection box */
@@ -239,10 +240,21 @@ void create_new_stroke(GdkEvent *event)
       "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
       "fill-color-rgba", ui.cur_item->brush.color_rgba,
       "width-units", ui.cur_item->brush.thickness, NULL);
+    ui.cur_item->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_line_get_type(),
+      "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+      "fill-color-rgba", ui.cur_item->brush.color_rgba,
+      "width-units", ui.cur_item->brush.thickness, NULL);
     ui.cur_item->brush.variable_width = FALSE;
-  } else
+  }
+  else
+  {
     ui.cur_item->canvas_item = gnome_canvas_item_new(
       ui.cur_layer->group, gnome_canvas_group_get_type(), NULL);
+
+    ui.cur_item->canvas_item2 = gnome_canvas_item_new(
+      ui.cur_layer->group2, gnome_canvas_group_get_type(), NULL);
+  }
 }
 
 void continue_stroke(GdkEvent *event)
@@ -289,13 +301,23 @@ void continue_stroke(GdkEvent *event)
      into an internal structure */
 
   if (ui.cur_brush->ruler)
+  {
     gnome_canvas_item_set(ui.cur_item->canvas_item, "points", &seg, NULL);
+    gnome_canvas_item_set(ui.cur_item->canvas_item2, "points", &seg, NULL);
+  }
   else
+  {
     gnome_canvas_item_new((GnomeCanvasGroup *)ui.cur_item->canvas_item,
        gnome_canvas_line_get_type(), "points", &seg,
        "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
        "fill-color-rgba", ui.cur_item->brush.color_rgba,
        "width-units", current_width, NULL);
+    gnome_canvas_item_new((GnomeCanvasGroup *)ui.cur_item->canvas_item2,
+       gnome_canvas_line_get_type(), "points", &seg,
+       "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
+       "fill-color-rgba", ui.cur_item->brush.color_rgba,
+       "width-units", current_width, NULL);
+  }
 }
 
 void abort_stroke(void)
@@ -303,6 +325,7 @@ void abort_stroke(void)
   if (ui.cur_item_type != ITEM_STROKE || ui.cur_item == NULL) return;
   ui.cur_path.num_points = 0;
   gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item));
+  gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item2));
   g_free(ui.cur_item);
   ui.cur_item = NULL;
   ui.cur_item_type = ITEM_NONE;
@@ -333,8 +356,10 @@ void finalize_stroke(void)
   if (!ui.cur_item->brush.variable_width) {
     // destroy the entire group of temporary line segments
     gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item));
+    gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item2));
     // make a new line item to replace it
-    make_canvas_item_one(ui.cur_layer->group, ui.cur_item);
+    make_canvas_item_one(ui.cur_layer->group, ui.cur_item, 1);
+    make_canvas_item_one(ui.cur_layer->group2, ui.cur_item, 2);
   }
 
   // add undo information
@@ -367,6 +392,7 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius,
       if (erasure == NULL) {
         item->type = ITEM_TEMP_STROKE;
         gnome_canvas_item_hide(item->canvas_item);  
+        gnome_canvas_item_hide(item->canvas_item2);
             /*  we'll use this hidden item as an insertion point later */
         erasure = (struct UndoErasureData *)g_malloc(sizeof(struct UndoErasureData));
         item->erasure = erasure;
@@ -404,6 +430,7 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius,
               (item->path->num_points-i-1)*sizeof(gdouble));
           else newtail->widths = NULL;
           newtail->canvas_item = NULL;
+          newtail->canvas_item2 = NULL;
         }
       }
       if (item->type == ITEM_STROKE) { 
@@ -411,7 +438,10 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius,
         gnome_canvas_points_free(item->path);
         if (item->brush.variable_width) g_free(item->widths);
         if (item->canvas_item != NULL) 
+	    {
           gtk_object_destroy(GTK_OBJECT(item->canvas_item));
+          gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
+		}
         erasure->nrepl--;
         erasure->replacement_items = g_list_remove(erasure->replacement_items, item);
         g_free(item);
@@ -419,9 +449,12 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius,
       // add the new head
       if (newhead != NULL) {
         update_item_bbox(newhead);
-        make_canvas_item_one(ui.cur_layer->group, newhead);
+        make_canvas_item_one(ui.cur_layer->group, newhead, 1);
+        make_canvas_item_one(ui.cur_layer->group2, newhead, 2);
         lower_canvas_item_to(ui.cur_layer->group,
                   newhead->canvas_item, erasure->item->canvas_item);
+        lower_canvas_item_to(ui.cur_layer->group2,
+                  newhead->canvas_item2, erasure->item->canvas_item2);
         erasure->replacement_items = g_list_prepend(erasure->replacement_items, newhead);
         erasure->nrepl++;
         // prepending ensures it won't get processed twice
@@ -438,9 +471,12 @@ void erase_stroke_portions(struct Item *item, double x, double y, double radius,
   // add the tail if needed
   if (!need_recalc) return;
   update_item_bbox(item);
-  make_canvas_item_one(ui.cur_layer->group, item);
+  make_canvas_item_one(ui.cur_layer->group, item, 1);
+  make_canvas_item_one(ui.cur_layer->group2, item, 2);
   lower_canvas_item_to(ui.cur_layer->group, item->canvas_item, 
                                       erasure->item->canvas_item);
+  lower_canvas_item_to(ui.cur_layer->group2, item->canvas_item2, 
+                                      erasure->item->canvas_item2);
 }
 
 
@@ -554,6 +590,11 @@ void resize_textview(gpointer *toplevel, gpointer *data)
   gnome_canvas_item_set(ui.cur_item->canvas_item, 
     "size-pixels", TRUE, 
     "width", (gdouble)width, "height", (gdouble)height, NULL);
+  /*XXX
+  gnome_canvas_item_set(ui.cur_item->canvas_item2, 
+    "size-pixels", TRUE, 
+    "width", (gdouble)width, "height", (gdouble)height, NULL);
+  */
   ui.cur_item->bbox.right = ui.cur_item->bbox.left + width/ui.zoom;
   ui.cur_item->bbox.bottom = ui.cur_item->bbox.top + height/ui.zoom;
 }
@@ -563,6 +604,7 @@ void start_text(GdkEvent *event, struct Item *item)
   double pt[2];
   GtkTextBuffer *buffer;
   GnomeCanvasItem *canvas_item;
+  GnomeCanvasItem *canvas_item2;
   PangoFontDescription *font_desc;
   GdkColor color;
 
@@ -574,6 +616,7 @@ void start_text(GdkEvent *event, struct Item *item)
     item = g_new(struct Item, 1);
     item->text = NULL;
     item->canvas_item = NULL;
+    item->canvas_item2 = NULL;
     item->bbox.left = pt[0];
     item->bbox.top = pt[1];
     item->bbox.right = ui.cur_page->width;
@@ -606,12 +649,25 @@ void start_text(GdkEvent *event, struct Item *item)
     "width", item->bbox.right-item->bbox.left, 
     "height", item->bbox.bottom-item->bbox.top,
     "widget", item->widget, NULL);
+  /* XXX
+  canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+    gnome_canvas_widget_get_type(),
+    "x", item->bbox.left, "y", item->bbox.top, 
+    "width", item->bbox.right-item->bbox.left, 
+    "height", item->bbox.bottom-item->bbox.top,
+    "widget", item->widget, NULL);
+  */
   // TODO: width/height?
   if (item->canvas_item!=NULL) {
     lower_canvas_item_to(ui.cur_layer->group, canvas_item, item->canvas_item);
     gtk_object_destroy(GTK_OBJECT(item->canvas_item));
   }
+  if (item->canvas_item2!=NULL) {
+    lower_canvas_item_to(ui.cur_layer->group2, canvas_item2, item->canvas_item2);
+    gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
+  }
   item->canvas_item = canvas_item;
+  item->canvas_item2 = canvas_item2;
 
   gtk_widget_show(item->widget);
   ui.resize_signal_handler = 
@@ -630,6 +686,7 @@ void end_text(void)
   gchar *new_text;
   struct UndoErasureData *erasure;
   GnomeCanvasItem *tmpitem;
+  GnomeCanvasItem *tmpitem2;
 
   if (ui.cur_item_type!=ITEM_TEXT) return; // nothing for us to do!
 
@@ -647,6 +704,7 @@ void end_text(void)
     g_signal_handler_disconnect(winMain, ui.resize_signal_handler);
     gtk_object_destroy(GTK_OBJECT(ui.cur_item->canvas_item));
     ui.cur_item->canvas_item = NULL;
+    ui.cur_item->canvas_item2 = NULL;
     if (ui.cur_item->text == NULL) // nothing happened
       g_free(ui.cur_item->font_name);
     else { // treat this as an erasure
@@ -681,10 +739,14 @@ void end_text(void)
   ui.cur_item->widget = NULL;
   // replace the canvas item
   tmpitem = ui.cur_item->canvas_item;
-  make_canvas_item_one(ui.cur_layer->group, ui.cur_item);
+  tmpitem2 = ui.cur_item->canvas_item2;
+  make_canvas_item_one(ui.cur_layer->group, ui.cur_item, 1);
+  make_canvas_item_one(ui.cur_layer->group2, ui.cur_item, 2);
   update_item_bbox(ui.cur_item);
   lower_canvas_item_to(ui.cur_layer->group, ui.cur_item->canvas_item, tmpitem);
+  lower_canvas_item_to(ui.cur_layer->group2, ui.cur_item->canvas_item2, tmpitem2);
   gtk_object_destroy(GTK_OBJECT(tmpitem));
+  //gtk_object_destroy(GTK_OBJECT(tmpitem2)); XXX
 }
 
 /* update the items in the canvas so they're of the right font size */
@@ -695,6 +757,7 @@ void update_text_item_displayfont(struct Item *item)
 
   if (item->type != ITEM_TEXT && item->type != ITEM_TEMP_TEXT) return;
   if (item->canvas_item==NULL) return;
+  if (item->canvas_item2==NULL) return;
   font_desc = pango_font_description_from_string(item->font_name);
   pango_font_description_set_absolute_size(font_desc, 
         item->font_size*ui.zoom*PANGO_SCALE);
@@ -702,6 +765,7 @@ void update_text_item_displayfont(struct Item *item)
     gtk_widget_modify_font(item->widget, font_desc);
   else {
     gnome_canvas_item_set(item->canvas_item, "font-desc", font_desc, NULL);
+    gnome_canvas_item_set(item->canvas_item2, "font-desc", font_desc, NULL);
     update_item_bbox(item);
   }
   pango_font_description_free(font_desc);
diff --git a/src/xo-selection.c b/src/xo-selection.c
index 7359bd8..45aa1fa 100644
--- a/src/xo-selection.c
+++ b/src/xo-selection.c
@@ -68,6 +68,11 @@ void start_selectrect(GdkEvent *event)
       "outline-color-rgba", 0x000000ff,
       "fill-color-rgba", 0x80808040,
       "x1", pt[0], "x2", pt[0], "y1", pt[1], "y2", pt[1], NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1, 
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", pt[0], "x2", pt[0], "y1", pt[1], "y2", pt[1], NULL);
   update_cursor();
 }
 
@@ -110,11 +115,17 @@ void finalize_selectrect(void)
       gnome_canvas_item_set(ui.selection->canvas_item,
         "x1", item->bbox.left, "x2", item->bbox.right, 
         "y1", item->bbox.top, "y2", item->bbox.bottom, NULL);
+      gnome_canvas_item_set(ui.selection->canvas_item2,
+        "x1", item->bbox.left, "x2", item->bbox.right, 
+        "y1", item->bbox.top, "y2", item->bbox.bottom, NULL);
     }
   }
   
   if (ui.selection->items == NULL) reset_selection();
-  else make_dashed(ui.selection->canvas_item);
+  else {
+    make_dashed(ui.selection->canvas_item);
+    make_dashed(ui.selection->canvas_item2);
+  }
   update_cursor();
   update_copy_paste_enabled();
   update_font_button();
@@ -146,7 +157,13 @@ void start_selectregion(GdkEvent *event)
       "outline-color-rgba", 0x000000ff,
       "fill-color-rgba", 0x80808040,
       NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_polygon_get_type(), "width-pixels", 1, 
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      NULL);
   make_dashed(ui.selection->canvas_item);
+  make_dashed(ui.selection->canvas_item2);
   update_cursor();
 }
 
@@ -163,6 +180,8 @@ void continue_selectregion(GdkEvent *event)
   if (ui.cur_path.num_points>2)
     gnome_canvas_item_set(ui.selection->canvas_item, 
      "points", &ui.cur_path, NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2, 
+     "points", &ui.cur_path, NULL);
 }
 
 /* check whether a point, resp. an item, is inside a lasso selection */
@@ -268,6 +287,15 @@ void finalize_selectregion(void)
       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
     make_dashed(ui.selection->canvas_item);
+    
+	gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item2));
+    ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1, 
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
+      "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+    make_dashed(ui.selection->canvas_item2);
     ui.selection->type = ITEM_SELECTRECT;
   }
 
@@ -299,6 +327,7 @@ gboolean start_movesel(GdkEvent *event)
     ui.selection->move_layer = ui.selection->layer;
     ui.selection->move_pagedelta = 0.;
     gnome_canvas_item_set(ui.selection->canvas_item, "dash", NULL, NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2, "dash", NULL, NULL);
     update_cursor();
     return TRUE;
   }
@@ -346,6 +375,7 @@ gboolean start_resizesel(GdkEvent *event)
     ui.selection->new_x1 = ui.selection->bbox.left;
     ui.selection->new_x2 = ui.selection->bbox.right;
     gnome_canvas_item_set(ui.selection->canvas_item, "dash", NULL, NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2, "dash", NULL, NULL);
     update_cursor_for_resize(pt);
     return TRUE;
   }
@@ -388,6 +418,11 @@ void start_vertspace(GdkEvent *event)
       "outline-color-rgba", 0x000000ff,
       "fill-color-rgba", 0x80808040,
       "x1", -100.0, "x2", ui.cur_page->width+100, "y1", pt[1], "y2", pt[1], NULL);
+  ui.selection->canvas_item2 = gnome_canvas_item_new(ui.cur_layer->group2,
+      gnome_canvas_rect_get_type(), "width-pixels", 1, 
+      "outline-color-rgba", 0x000000ff,
+      "fill-color-rgba", 0x80808040,
+      "x1", -100.0, "x2", ui.cur_page->width+100, "y1", pt[1], "y2", pt[1], NULL);
   update_cursor();
 }
 
@@ -452,10 +487,13 @@ void continue_movesel(GdkEvent *event)
       ui.selection->move_layer = (struct Layer *)(g_list_last(
         ((struct Page *)g_list_nth_data(journal.pages, tmppageno))->layers)->data);
     gnome_canvas_item_reparent(ui.selection->canvas_item, ui.selection->move_layer->group);
+    gnome_canvas_item_reparent(ui.selection->canvas_item2, ui.selection->move_layer->group2);
     for (list = ui.selection->items; list!=NULL; list = list->next) {
       item = (struct Item *)list->data;
       if (item->canvas_item!=NULL)
         gnome_canvas_item_reparent(item->canvas_item, ui.selection->move_layer->group);
+      if (item->canvas_item2!=NULL)
+        gnome_canvas_item_reparent(item->canvas_item2, ui.selection->move_layer->group2);
     }
     // avoid a refresh bug
     gnome_canvas_item_move(GNOME_CANVAS_ITEM(ui.selection->move_layer->group), 0., 0.);
@@ -464,6 +502,9 @@ void continue_movesel(GdkEvent *event)
         "x2", tmppage->width+100, 
         "y1", ui.selection->anchor_y+ui.selection->move_pagedelta, NULL);
             /* note: moving across pages for vert. space only works in vertical continuous mode */
+      gnome_canvas_item_set(ui.selection->canvas_item2,
+        "x2", tmppage->width+100, 
+        "y1", ui.selection->anchor_y+ui.selection->move_pagedelta, NULL);
   }
   
   // now, process things normally
@@ -476,14 +517,22 @@ void continue_movesel(GdkEvent *event)
 
   // move the canvas items
   if (ui.cur_item_type == ITEM_MOVESEL_VERT)
+  {
     gnome_canvas_item_set(ui.selection->canvas_item, "y2", pt[1], NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2, "y2", pt[1], NULL);
+  }
   else 
+  {
     gnome_canvas_item_move(ui.selection->canvas_item, dx, dy);
+    gnome_canvas_item_move(ui.selection->canvas_item2, dx, dy);
+  }
   
   for (list = ui.selection->items; list != NULL; list = list->next) {
     item = (struct Item *)list->data;
     if (item->canvas_item != NULL)
       gnome_canvas_item_move(item->canvas_item, dx, dy);
+    if (item->canvas_item2 != NULL)
+      gnome_canvas_item_move(item->canvas_item2, dx, dy);
   }
 }
 
@@ -501,6 +550,9 @@ void continue_resizesel(GdkEvent *event)
   gnome_canvas_item_set(ui.selection->canvas_item, 
     "x1", ui.selection->new_x1, "x2", ui.selection->new_x2,
     "y1", ui.selection->new_y1, "y2", ui.selection->new_y2, NULL);
+  gnome_canvas_item_set(ui.selection->canvas_item2, 
+    "x1", ui.selection->new_x1, "x2", ui.selection->new_x2,
+    "y1", ui.selection->new_y1, "y2", ui.selection->new_y2, NULL);
 }
 
 void finalize_movesel(void)
@@ -539,13 +591,18 @@ void finalize_movesel(void)
     ui.selection->bbox.top += undo->val_y;
     ui.selection->bbox.bottom += undo->val_y;
     make_dashed(ui.selection->canvas_item);
+    make_dashed(ui.selection->canvas_item2);
     /* update selection box object's offset to be trivial, and its internal 
        coordinates to agree with those of the bbox; need this since resize
        operations will modify the box by setting its coordinates directly */
     gnome_canvas_item_affine_absolute(ui.selection->canvas_item, NULL);
+    gnome_canvas_item_affine_absolute(ui.selection->canvas_item2, NULL);
     gnome_canvas_item_set(ui.selection->canvas_item, 
       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+    gnome_canvas_item_set(ui.selection->canvas_item2, 
+      "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
+      "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
   }
   ui.cur_item_type = ITEM_NONE;
   update_cursor();
@@ -600,6 +657,7 @@ void finalize_resizesel(void)
     ui.selection->bbox.bottom = ui.selection->new_y1;
   }
   make_dashed(ui.selection->canvas_item);
+  make_dashed(ui.selection->canvas_item2);
 
   ui.cur_item_type = ITEM_NONE;
   update_cursor();
@@ -620,6 +678,8 @@ void selection_delete(void)
     item = (struct Item *)itemlist->data;
     if (item->canvas_item!=NULL)
       gtk_object_destroy(GTK_OBJECT(item->canvas_item));
+    if (item->canvas_item2!=NULL)
+      gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
     erasure = g_new(struct UndoErasureData, 1);
     erasure->item = item;
     erasure->npos = g_list_index(ui.selection->layer->items, item);
@@ -670,7 +730,17 @@ void recolor_selection(int color_no, guint color_rgba)
       else {
         group = (GnomeCanvasGroup *) item->canvas_item->parent;
         gtk_object_destroy(GTK_OBJECT(item->canvas_item));
-        make_canvas_item_one(group, item);
+        make_canvas_item_one(group, item, 1);
+      }
+    }
+    if (item->canvas_item2!=NULL) {
+      if (!item->brush.variable_width)
+        gnome_canvas_item_set(item->canvas_item2, 
+           "fill-color-rgba", item->brush.color_rgba, NULL);
+      else {
+        group = (GnomeCanvasGroup *) item->canvas_item2->parent;
+        gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
+        make_canvas_item_one(group, item, 2);
       }
     }
   }
@@ -707,7 +777,18 @@ void rethicken_selection(int val)
         group = (GnomeCanvasGroup *) item->canvas_item->parent;
         gtk_object_destroy(GTK_OBJECT(item->canvas_item));
         item->brush.variable_width = FALSE;
-        make_canvas_item_one(group, item);
+        make_canvas_item_one(group, item, 1);
+      }
+    }
+    if (item->canvas_item2!=NULL) {
+      if (!item->brush.variable_width)
+        gnome_canvas_item_set(item->canvas_item2, 
+           "width-units", item->brush.thickness, NULL);
+      else {
+        group = (GnomeCanvasGroup *) item->canvas_item2->parent;
+        gtk_object_destroy(GTK_OBJECT(item->canvas_item2));
+        item->brush.variable_width = FALSE;
+        make_canvas_item_one(group, item, 2);
       }
     }
   }
diff --git a/src/xo-shapes.c b/src/xo-shapes.c
index f8d978e..383ab65 100644
--- a/src/xo-shapes.c
+++ b/src/xo-shapes.c
@@ -313,6 +313,8 @@ void remove_recognized_strokes(struct RecoSegment *rs, int num_old_items)
     undo->erasurelist = g_list_append(undo->erasurelist, erasure);
     if (old_item->canvas_item != NULL)
       gtk_object_destroy(GTK_OBJECT(old_item->canvas_item));
+    if (old_item->canvas_item2 != NULL)
+      gtk_object_destroy(GTK_OBJECT(old_item->canvas_item2));
     ui.cur_layer->items = g_list_remove(ui.cur_layer->items, old_item);
     ui.cur_layer->nitems--;
   }
@@ -340,7 +342,8 @@ struct Item *insert_recognized_curpath(void)
   erasure->replacement_items = g_list_append(erasure->replacement_items, item);
   ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
   ui.cur_layer->nitems++;
-  make_canvas_item_one(ui.cur_layer->group, item);
+  make_canvas_item_one(ui.cur_layer->group, item, 1);
+  make_canvas_item_one(ui.cur_layer->group2, item, 2);
   return item;
 }
 
diff --git a/src/xournal.h b/src/xournal.h
index 66e6850..501e87d 100644
--- a/src/xournal.h
+++ b/src/xournal.h
@@ -85,16 +85,19 @@ typedef struct Refstring {
 typedef struct Background {
   int type;
   GnomeCanvasItem *canvas_item;
+  GnomeCanvasItem *canvas_item2;
   int color_no;
   guint color_rgba;
   int ruling;
   GdkPixbuf *pixbuf;
+  GdkPixbuf *pixbuf2;
   Refstring *filename;
   int file_domain;
   int file_page_seq;
   double pixbuf_scale; // for PIXMAP, this is the *current* zoom value
                        // for PDF, this is the *requested* zoom value
   int pixel_height, pixel_width; // PDF only: pixel size of current pixbuf
+  int pixel_height2, pixel_width2; // PDF only: pixel size of current pixbuf2
 } Background;
 
 #define BG_SOLID 0
@@ -176,6 +179,7 @@ typedef struct Item {
   GnomeCanvasPoints *path;
   gdouble *widths;
   GnomeCanvasItem *canvas_item; // the corresponding canvas item, or NULL
+  GnomeCanvasItem *canvas_item2; // the corresponding canvas item, or NULL
   struct BBox bbox;
   struct UndoErasureData *erasure; // for temporary use during erasures
   // the following fields for ITEM_TEXT:
@@ -224,6 +228,7 @@ typedef struct Layer {
   GList *items; // the items on the layer, from bottom to top
   int nitems;
   GnomeCanvasGroup *group;
+  GnomeCanvasGroup *group2;
 } Layer;
 
 typedef struct Page {
@@ -233,6 +238,7 @@ typedef struct Page {
   double hoffset, voffset; // offsets of canvas group rel. to canvas root
   struct Background *bg;
   GnomeCanvasGroup *group;
+  GnomeCanvasGroup *group2;
 } Page;
 
 typedef struct Journal {
@@ -249,6 +255,7 @@ typedef struct Selection {
   gboolean resizing_top, resizing_bottom, resizing_left, resizing_right; // for selection resizing
   double new_x1, new_x2, new_y1, new_y2; // for selection resizing
   GnomeCanvasItem *canvas_item; // if the selection box is on screen 
+  GnomeCanvasItem *canvas_item2; // if the selection box is on screen 
   GList *items; // the selected items (a list of struct Item)
   int move_pageno, orig_pageno; // if selection moves to a different page
   struct Layer *move_layer;
@@ -283,6 +290,7 @@ typedef struct UIData {
   int cur_path_storage_alloc;
   int cur_widths_storage_alloc;
   double zoom; // zoom factor, in pixels per pt
+  double zoom2; // zoom factor, in pixels per pt
   gboolean use_xinput; // use input devices instead of core pointer
   gboolean allow_xinput; // allow use of xinput ?
   gboolean discard_corepointer; // discard core pointer events in XInput mode
@@ -348,6 +356,7 @@ typedef struct UIData {
 #endif
   gboolean poppler_force_cairo; // force poppler to use cairo
   gboolean warned_generate_fontconfig; // for win32 fontconfig cache
+  int pwidth, pheight; // presentation mode width and height
 } UIData;
 
 #define BRUSH_LINKED 0
@@ -387,12 +396,18 @@ typedef struct UndoItem {
 typedef struct BgPdfRequest {
   int pageno;
   double dpi;
+  int pheight, pwidth;
 } BgPdfRequest;
 
 typedef struct BgPdfPage {
   double dpi;
+  double dpi2;
+
   GdkPixbuf *pixbuf;
+  GdkPixbuf *pixbuf2;
+
   int pixel_height, pixel_width; // pixel size of pixbuf
+  int pixel_height2, pixel_width2; // pixel size of pixbuf2
 } BgPdfPage;
 
 typedef struct BgPdf {
@@ -430,7 +445,9 @@ typedef struct BgPdf {
 // the main window and the canvas
 
 extern GtkWidget *winMain;
+extern GtkWidget *presentMain;
 extern GnomeCanvas *canvas;
+extern GnomeCanvas *canvas2;
 
 // the data
 
diff --git a/xournal.glade b/xournal.glade
index 38ae9f2..faca482 100644
--- a/xournal.glade
+++ b/xournal.glade
@@ -656,6 +656,7 @@
 		      <property name="visible">True</property>
 		      <property name="label" translatable="yes">New Pages Keep Background</property>
 		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
 		      <signal name="activate" handler="on_journalNewPageKeepsBG_activate" last_modification_time="Mon, 26 May 2014 19:50:07 GMT"/>
 		    </widget>
 		  </child>
@@ -1580,8 +1581,8 @@
 			  <child>
 			    <widget class="GtkCheckMenuItem" id="optionsButtonMappings">
 			      <property name="visible">True</property>
-		 	      <property name="label" translatable="yes">_Eraser Tip</property>
-		 	      <property name="use_underline">True</property>
+			      <property name="label" translatable="yes">_Eraser Tip</property>
+			      <property name="use_underline">True</property>
 			      <property name="active">False</property>
 			      <signal name="activate" handler="on_optionsButtonMappings_activate" last_modification_time="Thu, 26 Jan 2006 03:45:32 GMT"/>
 			    </widget>
@@ -1613,7 +1614,7 @@
 			      <property name="label" translatable="yes">_Touchscreen as Hand Tool</property>
 			      <property name="use_underline">True</property>
 			      <property name="active">False</property>
-			      <signal name="activate" handler="on_optionsTouchAsHandTool_activate" last_modification_time="Thu, 23 Mar 2014 03:45:32 GMT"/>
+			      <signal name="activate" handler="on_optionsTouchAsHandTool_activate" last_modification_time="Sun, 23 Mar 2014 03:45:32 GMT"/>
 			    </widget>
 			  </child>
 
@@ -1632,15 +1633,14 @@
 			      <property name="visible">True</property>
 			      <property name="label" translatable="yes">Designate as Touchscreen...</property>
 			      <property name="use_underline">True</property>
-			      <property name="active">False</property>
 			      <signal name="activate" handler="on_optionsDesignateTouchscreen_activate" last_modification_time="Sat, 24 May 2014 22:16:32 GMT"/>
 			    </widget>
 			  </child>
+			</widget>
+		      </child>
+		    </widget>
+		  </child>
 
-		         </widget>
-			</child>
-		       </widget>
-		     </child>
 		  <child>
 		    <widget class="GtkMenuItem" id="button2_mapping">
 		      <property name="visible">True</property>
@@ -1977,7 +1977,7 @@
 		      <property name="label" translatable="yes">Layers in PDF Export</property>
 		      <property name="use_underline">True</property>
 		      <property name="active">False</property>
-		      <signal name="activate" handler="on_optionsLayersPDFExport_activate" last_modification_time="Sat, 4 Jul 2015 20:42:27 GMT"/>
+		      <signal name="activate" handler="on_optionsLayersPDFExport_activate" last_modification_time="Sat, 04 Jul 2015 20:42:27 GMT"/>
 		    </widget>
 		  </child>
 
@@ -3978,4 +3978,25 @@ and other contributors
   </child>
 </widget>
 
+<widget class="GtkWindow" id="presentMain">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Xournal Presentation</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">False</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+
+  <child>
+    <placeholder/>
+  </child>
+</widget>
+
 </glade-interface>
------------------------------------------------------------------------------
Mobile security can be enabling, not merely restricting. Employees who
bring their own devices (BYOD) to work are irked by the imposition of MDM
restrictions. Mobile Device Manager Plus allows you to control only the
apps on BYO-devices by containerizing them, leaving personal data untouched!
https://ad.doubleclick.net/ddm/clk/304595813;131938128;j
_______________________________________________
Xournal-devel mailing list
Xournal-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/xournal-devel

Reply via email to