]> git.donarmstrong.com Git - xournal.git/blobdiff - src/xo-callbacks.c
custom color chooser; misc patches
[xournal.git] / src / xo-callbacks.c
index c38299659be2ee8879e32c4ccca16f20d4be8404..71771cd2f0199e6c1aa3a415c1bf6d24466f6e98 100644 (file)
@@ -7,7 +7,6 @@
 #include <gtk/gtk.h>
 #include <libgnomecanvas/libgnomecanvas.h>
 #include <time.h>
-#include <libgnomeprintui/gnome-print-dialog.h>
 #include <glib/gstdio.h>
 #include <gdk/gdkkeysyms.h>
 
@@ -287,87 +286,57 @@ on_filePrintOptions_activate           (GtkMenuItem     *menuitem,
 
 }
 
-
 void
 on_filePrint_activate                  (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  GtkWidget *printDialog;
-  GnomePrintJob *gpj;
+#if GTK_CHECK_VERSION(2, 10, 0)
+  GtkPrintOperation *print;
+  GtkPrintOperationResult res;
+  
   int fromPage, toPage;
   int response;
-  char *in_fn;
-  guchar *s;
-  GnomePrintConfig *config = gnome_print_config_default();
+  char *in_fn, *p;
 
   end_text();
   reset_focus();
-  if (ui.filename!=NULL) {
-    if (g_str_has_suffix(ui.filename, ".xoj")) {
-      in_fn = g_strdup(ui.filename);
-      g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
-    } 
-    else
-      in_fn = g_strdup_printf("%s.pdf", ui.filename);
-    gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"PDF");
-    gnome_print_config_set(config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
-    gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
-    g_strlcpy(g_strrstr(in_fn, "pdf"), "ps", 3);
-    gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"GENERIC");
-    gnome_print_config_set (config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
-    s = gnome_print_config_get(config, (guchar *)"Settings.Transport.Backend.FileName");
-    if (s != NULL) {
-      g_free(s);
-      gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
-    }
-    g_free(in_fn);
-  }
-  
-  gpj = gnome_print_job_new(config); /* was NULL */
-  gnome_print_config_unref(config);
-/* end */
-  printDialog = gnome_print_dialog_new(gpj, (guchar *) _("Print"), GNOME_PRINT_DIALOG_RANGE);
-  gnome_print_dialog_construct_range_page(GNOME_PRINT_DIALOG(printDialog),
-    GNOME_PRINT_RANGE_ALL | GNOME_PRINT_RANGE_RANGE,
-    1, journal.npages, (guchar *) _("Current page"), (guchar *) _("Pages"));
-  /* don't have "Current page" as option, else it becomes the default!! */
-  
-  gtk_dialog_set_response_sensitive(GTK_DIALOG(printDialog),
-                         GNOME_PRINT_DIALOG_RESPONSE_PREVIEW, FALSE);
-  /* the print-job-preview "feature" is completely, hopelessly broken */                       
-
-  response = gtk_dialog_run(GTK_DIALOG(printDialog));
-  if (response <= 0) {
-    gtk_widget_destroy(printDialog);
-    return;
-  }
-
+  if (!gtk_check_version(2, 10, 0)) {
+    print = gtk_print_operation_new();
 /*
-  if (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW) {
-    print_job_render(gpj, 0, journal.npages-1);
-    gtk_widget_destroy(printDialog);
-    preview = gnome_print_job_preview_new(gpj, (guchar *)"Preview");
-    try_fix_print_preview_ui(preview);
-    gtk_window_set_modal(GTK_WINDOW(preview), TRUE);
-    gtk_widget_show_all(preview);
-  }
+    if (!ui.print_settings)
+      ui.print_settings = gtk_print_settings_new();
+    if (ui.filename!=NULL) {
+      if (g_str_has_suffix(ui.filename, ".xoj")) {
+        in_fn = g_strdup(ui.filename);
+        g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
+      } 
+      else in_fn = g_strdup_printf("%s.pdf", ui.filename);
+      gtk_print_settings_set(ui.print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI,
+         g_filename_to_uri(in_fn, NULL, NULL));
+      g_free(in_fn);
+    }
 */
-
-  if (response == GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
-    switch(gnome_print_dialog_get_range(GNOME_PRINT_DIALOG(printDialog))) {
-      case GNOME_PRINT_RANGE_RANGE: 
-        gnome_print_dialog_get_range_page(GNOME_PRINT_DIALOG(printDialog), &fromPage, &toPage);
-        fromPage--;
-        toPage--;
-        break;
-      default: 
-        fromPage = 0; 
-        toPage = journal.npages-1;
+    if (ui.print_settings!=NULL)
+       gtk_print_operation_set_print_settings (print, ui.print_settings);
+    gtk_print_operation_set_n_pages(print, journal.npages);
+    gtk_print_operation_set_current_page(print, ui.pageno);
+    gtk_print_operation_set_show_progress(print, TRUE);
+    if (ui.filename!=NULL) {
+      p = g_utf8_strrchr(ui.filename, -1, '/');
+      if (p==NULL) p = ui.filename;
+      else p++;
+      gtk_print_operation_set_job_name(print, p);
     }
-
-    gtk_widget_destroy(printDialog);
-    print_job_render(gpj, fromPage, toPage);
+    g_signal_connect (print, "draw_page", G_CALLBACK (print_job_render_page), NULL);
+    res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+                                  GTK_WINDOW(winMain), NULL);
+    if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+      if (ui.print_settings!=NULL) g_object_unref(ui.print_settings);
+      ui.print_settings = g_object_ref(gtk_print_operation_get_print_settings(print));
+    }
+    g_object_unref(print);
   }
+#endif
 }
 
 
@@ -1685,14 +1654,15 @@ on_toolsPen_activate                   (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return;
-  if (ui.toolno[0] == TOOL_PEN) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;
 
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   end_text();
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_PEN;
-  ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
+  ui.toolno[ui.cur_mapping] = TOOL_PEN;
+  ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
   ui.cur_brush->ruler = ui.default_brushes[TOOL_PEN].ruler;
   ui.cur_brush->recognizer = ui.default_brushes[TOOL_PEN].recognizer;
   update_mapping_linkings(TOOL_PEN);
@@ -1715,14 +1685,15 @@ on_toolsEraser_activate                (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return;
-  if (ui.toolno[0] == TOOL_ERASER) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_ERASER) return;
   
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   end_text();
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_ERASER;
-  ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
+  ui.toolno[ui.cur_mapping] = TOOL_ERASER;
+  ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_ERASER]);
   update_mapping_linkings(TOOL_ERASER);
   update_tool_buttons();
   update_tool_menu();
@@ -1743,14 +1714,15 @@ on_toolsHighlighter_activate           (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return; // not user-generated
-  if (ui.toolno[0] == TOOL_HIGHLIGHTER) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) return;
   
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   end_text();
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_HIGHLIGHTER;
-  ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
+  ui.toolno[ui.cur_mapping] = TOOL_HIGHLIGHTER;
+  ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_HIGHLIGHTER]);
   ui.cur_brush->ruler = ui.default_brushes[TOOL_HIGHLIGHTER].ruler;
   ui.cur_brush->recognizer = ui.default_brushes[TOOL_HIGHLIGHTER].recognizer;
   update_mapping_linkings(TOOL_HIGHLIGHTER);
@@ -1773,13 +1745,14 @@ on_toolsText_activate                  (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return; // not user-generated
-  if (ui.toolno[0] == TOOL_TEXT) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) return;
   
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_TEXT;
-  ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
+  ui.toolno[ui.cur_mapping] = TOOL_TEXT;
+  ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
   update_mapping_linkings(-1);
   update_tool_buttons();
   update_tool_menu();
@@ -1808,12 +1781,13 @@ on_toolsSelectRectangle_activate       (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return; // not user-generated
-  if (ui.toolno[0] == TOOL_SELECTRECT) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_SELECTRECT) return;
   
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   end_text();
   reset_focus();
-  ui.toolno[0] = TOOL_SELECTRECT;
+  ui.toolno[ui.cur_mapping] = TOOL_SELECTRECT;
   update_mapping_linkings(-1);
   update_tool_buttons();
   update_tool_menu();
@@ -1834,13 +1808,14 @@ on_toolsVerticalSpace_activate         (GtkMenuItem     *menuitem,
       return;
   }
   
-  if (ui.cur_mapping != 0) return; // not user-generated
-  if (ui.toolno[0] == TOOL_VERTSPACE) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
+  if (ui.toolno[ui.cur_mapping] == TOOL_VERTSPACE) return;
   
+  ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
   end_text();
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_VERTSPACE;
+  ui.toolno[ui.cur_mapping] = TOOL_VERTSPACE;
   update_mapping_linkings(-1);
   update_tool_buttons();
   update_tool_menu();
@@ -1853,7 +1828,7 @@ void
 on_colorBlack_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_BLACK);
+  process_color_activate(menuitem, COLOR_BLACK, predef_colors_rgba[COLOR_BLACK]);
 }
 
 
@@ -1861,8 +1836,7 @@ void
 on_colorBlue_activate                  (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_BLUE);
-
+  process_color_activate(menuitem, COLOR_BLUE, predef_colors_rgba[COLOR_BLUE]);
 }
 
 
@@ -1870,7 +1844,7 @@ void
 on_colorRed_activate                   (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_RED);
+  process_color_activate(menuitem, COLOR_RED, predef_colors_rgba[COLOR_RED]);
 }
 
 
@@ -1878,7 +1852,7 @@ void
 on_colorGreen_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_GREEN);
+  process_color_activate(menuitem, COLOR_GREEN, predef_colors_rgba[COLOR_GREEN]);
 }
 
 
@@ -1886,7 +1860,7 @@ void
 on_colorGray_activate                  (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_GRAY);
+  process_color_activate(menuitem, COLOR_GRAY, predef_colors_rgba[COLOR_GRAY]);
 }
 
 
@@ -1894,7 +1868,7 @@ void
 on_colorLightBlue_activate             (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_LIGHTBLUE);
+  process_color_activate(menuitem, COLOR_LIGHTBLUE, predef_colors_rgba[COLOR_LIGHTBLUE]);
 }
 
 
@@ -1902,7 +1876,7 @@ void
 on_colorLightGreen_activate            (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_LIGHTGREEN);
+  process_color_activate(menuitem, COLOR_LIGHTGREEN, predef_colors_rgba[COLOR_LIGHTGREEN]);
 }
 
 
@@ -1910,7 +1884,7 @@ void
 on_colorMagenta_activate               (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_MAGENTA);
+  process_color_activate(menuitem, COLOR_MAGENTA, predef_colors_rgba[COLOR_MAGENTA]);
 }
 
 
@@ -1918,7 +1892,7 @@ void
 on_colorOrange_activate                (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_ORANGE);
+  process_color_activate(menuitem, COLOR_ORANGE, predef_colors_rgba[COLOR_ORANGE]);
 }
 
 
@@ -1926,7 +1900,7 @@ void
 on_colorYellow_activate                (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_YELLOW);
+  process_color_activate(menuitem, COLOR_YELLOW, predef_colors_rgba[COLOR_YELLOW]);
 }
 
 
@@ -1934,7 +1908,7 @@ void
 on_colorWhite_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-  process_color_activate(menuitem, COLOR_WHITE);
+  process_color_activate(menuitem, COLOR_WHITE, predef_colors_rgba[COLOR_WHITE]);
 }
 
 
@@ -1942,7 +1916,7 @@ void
 on_colorOther_activate                 (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
 {
-
+  gtk_button_clicked(GTK_BUTTON(GET_COMPONENT("buttonColorChooser")));
 }
 
 
@@ -2183,10 +2157,11 @@ on_toolsSetAsDefault_activate          (GtkMenuItem     *menuitem,
 {
   struct Item *it;
   
-  if (ui.cur_mapping!=0) return;
-  if (ui.toolno[0] < NUM_STROKE_TOOLS)
-    g_memmove(ui.default_brushes+ui.toolno[0], &(ui.brushes[0][ui.toolno[0]]), sizeof(struct Brush));
-  if (ui.toolno[0] == TOOL_TEXT) {
+  if (ui.cur_mapping!=0 && !ui.button_switch_mapping) return;
+  if (ui.toolno[ui.cur_mapping] < NUM_STROKE_TOOLS)
+    g_memmove(ui.default_brushes+ui.toolno[ui.cur_mapping], 
+              &(ui.brushes[ui.cur_mapping][ui.toolno[ui.cur_mapping]]), sizeof(struct Brush));
+  if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) {
     if (ui.cur_item_type == ITEM_TEXT) {
       g_free(ui.font_name);
       ui.font_name = g_strdup(ui.cur_item->font_name);
@@ -2219,16 +2194,17 @@ on_toolsRuler_activate                 (GtkMenuItem     *menuitem,
   else
     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
 
-  if (ui.cur_mapping != 0) return;
-  current = (ui.toolno[0] == TOOL_PEN || ui.toolno[0] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
   if (active == current) return;
-  
+
+  ui.cur_mapping = 0;  
   end_text();
   reset_focus();
-  if (ui.toolno[0]!=TOOL_PEN && ui.toolno[0]!=TOOL_HIGHLIGHTER) {
+  if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
     reset_selection();
-    ui.toolno[0] = TOOL_PEN;
-    ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
+    ui.toolno[ui.cur_mapping] = TOOL_PEN;
+    ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
     update_color_menu();
     update_tool_buttons();
     update_tool_menu();
@@ -2237,7 +2213,7 @@ on_toolsRuler_activate                 (GtkMenuItem     *menuitem,
   
   ui.cur_brush->ruler = active;
   if (active) ui.cur_brush->recognizer = FALSE;
-  update_mapping_linkings(ui.toolno[0]);
+  update_mapping_linkings(ui.toolno[ui.cur_mapping]);
   update_ruler_indicator();
 }
 
@@ -2253,16 +2229,17 @@ on_toolsReco_activate                  (GtkMenuItem *menuitem,
   else
     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
 
-  if (ui.cur_mapping != 0) return;
-  current = (ui.toolno[0] == TOOL_PEN || ui.toolno[0] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
   if (active == current) return;
   
+  ui.cur_mapping = 0;
   end_text();
   reset_focus();
-  if (ui.toolno[0]!=TOOL_PEN && ui.toolno[0]!=TOOL_HIGHLIGHTER) {
+  if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
     reset_selection();
-    ui.toolno[0] = TOOL_PEN;
-    ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
+    ui.toolno[ui.cur_mapping] = TOOL_PEN;
+    ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
     update_color_menu();
     update_tool_buttons();
     update_tool_menu();
@@ -2274,7 +2251,7 @@ on_toolsReco_activate                  (GtkMenuItem *menuitem,
     ui.cur_brush->ruler = FALSE;
     reset_recognizer();
   }
-  update_mapping_linkings(ui.toolno[0]);
+  update_mapping_linkings(ui.toolno[ui.cur_mapping]);
   update_ruler_indicator();
 }
 
@@ -2344,8 +2321,8 @@ void
 on_buttonFine_clicked                  (GtkToolButton   *toolbutton,
                                         gpointer         user_data)
 {
-  if (ui.cur_mapping != 0) return;
-  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_FINE);
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_FINE);
 }
 
 
@@ -2353,8 +2330,8 @@ void
 on_buttonMedium_clicked                (GtkToolButton   *toolbutton,
                                         gpointer         user_data)
 {
-  if (ui.cur_mapping != 0) return;
-  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_MEDIUM);
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_MEDIUM);
 }
 
 
@@ -2362,8 +2339,8 @@ void
 on_buttonThick_clicked                 (GtkToolButton   *toolbutton,
                                         gpointer         user_data)
 {
-  if (ui.cur_mapping != 0) return;
-  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_THICK);
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_THICK);
 }
 
 
@@ -2386,6 +2363,8 @@ on_canvas_button_press_event           (GtkWidget       *widget,
   if (event->button > 3) return FALSE; // no painting with the mouse wheel!
   if (event->type != GDK_BUTTON_PRESS) return FALSE; 
     // double-clicks may have broken axes member (free'd) due to a bug in GDK
+  if ((event->state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)) != 0) return FALSE;
+    // no control-clicking or alt-clicking
   if (!is_core)
     fix_xinput_coords((GdkEvent *)event);
 
@@ -2395,8 +2374,10 @@ on_canvas_button_press_event           (GtkWidget       *widget,
 #endif
   if (!finite(event->x) || !finite(event->y)) return FALSE; // Xorg 7.3 bug
 
-  if (ui.cur_item_type == ITEM_TEXT && !is_event_within_textview(event))
-    end_text();
+  if (ui.cur_item_type == ITEM_TEXT) {
+    if (!is_event_within_textview(event)) end_text();
+    else return FALSE;
+  }
   if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
       ui.cur_path.num_points == 1) { 
       // Xorg 7.3+ sent core event before XInput event: fix initial point 
@@ -2405,10 +2386,19 @@ on_canvas_button_press_event           (GtkWidget       *widget,
   }
   if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
 
+  // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
+  if (ui.button_switch_mapping && event->button > 1) {
+    if (is_core == ui.use_xinput) return FALSE; // duplicate event
+    if (ui.cur_mapping == event->button-1) switch_mapping(0);
+    else switch_mapping(event->button-1);
+    return FALSE;
+  }
+
   ui.is_corestroke = is_core;
 
   if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
        mapping = NUM_BUTTONS;
+  else if (ui.button_switch_mapping) mapping = ui.cur_mapping;
   else mapping = event->button-1;
 
   // check whether we're in a page
@@ -2532,7 +2522,8 @@ on_canvas_button_release_event         (GtkWidget       *widget,
     ui.cur_item_type = ITEM_NONE;
   }
 
-  switch_mapping(0);
+  if (!ui.button_switch_mapping || ui.cur_mapping == NUM_BUTTONS) 
+    switch_mapping(0);
   return FALSE;
 }
 
@@ -2546,6 +2537,21 @@ on_canvas_enter_notify_event           (GtkWidget       *widget,
   return FALSE;
 }
 
+gboolean
+on_canvas_leave_notify_event           (GtkWidget       *widget,
+                                        GdkEventCrossing *event,
+                                        gpointer         user_data)
+{
+#ifdef INPUT_DEBUG
+  printf("DEBUG: leave notify\n");
+#endif
+  if (ui.need_emergency_disable_xinput) {
+    gtk_widget_set_extension_events(GTK_WIDGET (canvas), GDK_EXTENSION_EVENTS_NONE);
+    ui.need_emergency_disable_xinput = FALSE;
+  }
+  return FALSE;
+}
+
 
 gboolean
 on_canvas_expose_event                 (GtkWidget       *widget,
@@ -2562,6 +2568,12 @@ on_canvas_key_press_event              (GtkWidget       *widget,
                                         GdkEventKey     *event,
                                         gpointer         user_data)
 {
+  // Esc leaves text edition, or leaves fullscreen mode
+  if (event->keyval == GDK_Escape) {
+    if (ui.cur_item_type == ITEM_TEXT) { end_text(); reset_focus(); }
+    else if (ui.fullscreen) do_fullscreen(FALSE);
+  }
+  
   // If zoomed-out and in single page mode, switch pages with PgUp/PgDn.
   if (!ui.view_continuous && 
       (0.96 * ui.zoom * ui.cur_page->height < 
@@ -2596,6 +2608,7 @@ on_canvas_motion_notify_event          (GtkWidget       *widget,
      or if there's a selection (then we might want to change the mouse
      cursor to indicate the possibility of resizing) */  
   if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
+  if (ui.cur_item_type == ITEM_TEXT) return FALSE;
 
   is_core = (event->device == gdk_device_get_core_pointer());
   if (!ui.use_xinput && !is_core) return FALSE;
@@ -2719,7 +2732,9 @@ on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
   ui.allow_xinput = ui.use_xinput =
     gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
 
-/* Important note: we'd like ONLY the canvas window itself to receive
+/* HOW THINGS USED TO BE:
+
+   We'd like ONLY the canvas window itself to receive
    XInput events, while its child window in the GDK hierarchy (also
    associated to the canvas widget) receives the core events.
    This way on_canvas_... will get both types of events -- otherwise,
@@ -2731,12 +2746,21 @@ on_optionsUseXInput_activate           (GtkMenuItem     *menuitem,
    also traverses GDK child windows that belong to the widget
    and sets their extension events too. We want to avoid that.
    So we use gdk_input_set_extension_events() directly on the canvas.
+
+   As much as possible, we'd like to keep doing this, though GTK+ 2.17
+   is making our life harder (crasher bugs require us to disable XInput
+   while editing text or using the layers combo box, but disabling
+   XInput while in a XInput-aware window causes the interface to become
+   non-responsive). 
 */
-   
-/*  // this causes GTK+ 2.11 bugs
-    gtk_widget_set_extension_events(GTK_WIDGET (canvas), 
+
+  // this causes core events to be discarded... unwanted!
+/*
+   gtk_widget_set_extension_events(GTK_WIDGET (canvas), 
       ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
 */
+
+  // this version only activates extension events on the canvas's parent GdkWindow
   gdk_input_set_extension_events(GTK_WIDGET(canvas)->window, 
     GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
     ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
@@ -2983,18 +3007,7 @@ on_viewFullscreen_activate             (GtkMenuItem     *menuitem,
     active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
 
   if (active == ui.fullscreen) return;
-  end_text();
-  reset_focus();
-  ui.fullscreen = active;
-  gtk_check_menu_item_set_active(
-    GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
-  gtk_toggle_tool_button_set_active(
-    GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
-
-  if (ui.fullscreen) gtk_window_fullscreen(GTK_WINDOW(winMain));
-  else gtk_window_unfullscreen(GTK_WINDOW(winMain));
-  
-  update_vbox_order(ui.vertical_order[ui.fullscreen?1:0]);
+  do_fullscreen(active);
 }
 
 
@@ -3010,21 +3023,6 @@ on_optionsButtonMappings_activate      (GtkMenuItem     *menuitem,
 }
 
 
-void
-on_optionsAntialiasBG_activate         (GtkMenuItem     *menuitem,
-                                        gpointer         user_data)
-{
-  gboolean active;
-  
-  active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
-  if (ui.antialias_bg == active) return;
-  end_text();
-  reset_focus();
-  ui.antialias_bg = active;
-  rescale_bg_pixmaps();
-} 
-
-
 void
 on_optionsProgressiveBG_activate       (GtkMenuItem     *menuitem,
                                         gpointer         user_data)
@@ -3364,13 +3362,14 @@ on_toolsHand_activate                  (GtkMenuItem     *menuitem,
       return;
   }
 
-  if (ui.cur_mapping != 0) return;
-  if (ui.toolno[0] == TOOL_HAND) return;
+  if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
+  if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
 
+  ui.cur_mapping = 0;
   end_text();
   reset_focus();
   reset_selection();
-  ui.toolno[0] = TOOL_HAND;
+  ui.toolno[ui.cur_mapping] = TOOL_HAND;
   update_mapping_linkings(-1);
   update_tool_buttons();
   update_tool_menu();
@@ -3494,3 +3493,27 @@ on_optionsPressureSensitive_activate   (GtkMenuItem     *menuitem,
   update_mappings_menu();
 }
 
+
+void
+on_buttonColorChooser_set              (GtkColorButton  *colorbutton,
+                                        gpointer         user_data)
+{
+  GdkColor gdkcolor;
+  guint16 alpha;
+  
+  gtk_color_button_get_color(colorbutton, &gdkcolor);
+  alpha = gtk_color_button_get_alpha(colorbutton);
+  process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
+}
+
+
+void
+on_optionsButtonsSwitchMappings_activate(GtkMenuItem    *menuitem,
+                                        gpointer         user_data)
+{
+  end_text();
+  reset_focus();
+  switch_mapping(0);
+  ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
+}
+