home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / disp_callbacks.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  26.6 KB  |  1,005 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18. #include "config.h"
  19.  
  20. #include <stdlib.h>
  21.  
  22. #include <glib.h>
  23. #include <gdk/gdkkeysyms.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "bucket_fill.h"
  29. #include "cursorutil.h"
  30. #include "devices.h"
  31. #include "disp_callbacks.h"
  32. #include "gdisplay.h"
  33. #include "gimpcontext.h"
  34. #include "gimprc.h"
  35. #include "info_window.h"
  36. #include "layer_select.h"
  37. #include "move.h"
  38. #include "patterns.h"
  39. #include "scale.h"
  40. #include "scroll.h"
  41. #include "tools.h"
  42. #include "undo.h"
  43. #include "gimage.h"
  44. #include "dialog_handler.h"
  45.  
  46. #include "libgimp/gimpintl.h"
  47.  
  48. /* Function declarations */
  49.  
  50. static void gdisplay_check_device_cursor (GDisplay *gdisp);
  51.  
  52. static void
  53. redraw (GDisplay *gdisp,
  54.     gint      x,
  55.     gint      y,
  56.     gint      w,
  57.     gint      h)
  58. {
  59.   glong x1, y1, x2, y2;    /*  coordinate of rectangle corners  */
  60.  
  61.   x1 = x;
  62.   y1 = y;
  63.   x2 = (x+w);
  64.   y2 = (y+h);
  65.   x1 = CLAMP (x1, 0, gdisp->disp_width);
  66.   y1 = CLAMP (y1, 0, gdisp->disp_height);
  67.   x2 = CLAMP (x2, 0, gdisp->disp_width);
  68.   y2 = CLAMP (y2, 0, gdisp->disp_height);
  69.   if ((x2 - x1) && (y2 - y1))
  70.     {
  71.       gdisplay_expose_area (gdisp, x1, y1, (x2 - x1), (y2 - y1));
  72.       gdisplay_flush_displays_only (gdisp);
  73.     }
  74. }
  75.  
  76. static void
  77. gdisplay_check_device_cursor (GDisplay *gdisp)
  78. {
  79.   GList *list;
  80.  
  81.   /*  gdk_input_list_devices returns an internal list, so we shouldn't
  82.    *  free it afterwards
  83.    */
  84.   for (list = gdk_input_list_devices(); list; list = g_list_next (list))
  85.     {
  86.       GdkDeviceInfo *info = (GdkDeviceInfo *) list->data;
  87.  
  88.       if (info->deviceid == current_device)
  89.     {
  90.       gdisp->draw_cursor = !info->has_cursor;
  91.       break;
  92.     }
  93.     }
  94. }
  95.  
  96. static int
  97. key_to_state (gint key)
  98. {
  99.   switch (key)
  100.     {
  101.     case GDK_Alt_L:
  102.     case GDK_Alt_R:
  103.       return GDK_MOD1_MASK;
  104.     case GDK_Shift_L:
  105.     case GDK_Shift_R:
  106.       return GDK_SHIFT_MASK;
  107.     case GDK_Control_L:
  108.     case GDK_Control_R:
  109.       return GDK_CONTROL_MASK;
  110.     default:
  111.       return 0;
  112.     }
  113. }
  114.  
  115. gint
  116. gdisplay_shell_events (GtkWidget *widget,
  117.                GdkEvent  *event,
  118.                GDisplay  *gdisp)
  119. {
  120.   switch (event->type)
  121.     {
  122.     case GDK_BUTTON_PRESS:
  123.     case GDK_KEY_PRESS:
  124.       /*  Setting the context's display automatically sets the image, too  */
  125.       gimp_context_set_display (gimp_context_get_user (), gdisp);
  126.       break;
  127.     default:
  128.       break;
  129.     }
  130.  
  131.   return FALSE;
  132. }
  133.  
  134. gint
  135. gdisplay_canvas_events (GtkWidget *canvas,
  136.             GdkEvent  *event)
  137. {
  138.   GDisplay        *gdisp;
  139.   GdkEventExpose  *eevent;
  140.   GdkEventMotion  *mevent;
  141.   GdkEventButton  *bevent;
  142.   GdkEventKey     *kevent;
  143.   gdouble          tx            = 0;
  144.   gdouble          ty            = 0;
  145.   guint            state         = 0;
  146.   gint             return_val    = FALSE;
  147.   static gboolean  scrolled      = FALSE;
  148.   static guint     key_signal_id = 0;
  149.   gboolean         update_cursor = FALSE;
  150.  
  151.   gdisp = (GDisplay *) gtk_object_get_user_data (GTK_OBJECT (canvas));
  152.  
  153.   if (!canvas->window) 
  154.     return FALSE;
  155.  
  156.   /*  If this is the first event...  */
  157.   if (!gdisp->select)
  158.     {
  159.       /*  create the selection object  */
  160.       gdisp->select = selection_create (gdisp->canvas->window, gdisp,
  161.                     gdisp->gimage->height,
  162.                     gdisp->gimage->width, marching_speed);
  163.  
  164.       gdisp->disp_width = gdisp->canvas->allocation.width;
  165.       gdisp->disp_height = gdisp->canvas->allocation.height;
  166.  
  167.       /*  create GC for scrolling  */
  168.       gdisp->scroll_gc = gdk_gc_new (gdisp->canvas->window);
  169.       gdk_gc_set_exposures (gdisp->scroll_gc, TRUE);
  170.  
  171.       /*  set up the scrollbar observers  */
  172.       gtk_signal_connect (GTK_OBJECT (gdisp->hsbdata), "value_changed",
  173.               (GtkSignalFunc) scrollbar_horz_update,
  174.               gdisp);
  175.       gtk_signal_connect (GTK_OBJECT (gdisp->vsbdata), "value_changed",
  176.               (GtkSignalFunc) scrollbar_vert_update,
  177.               gdisp);
  178.  
  179.       /*  setup scale properly  */
  180.       setup_scale (gdisp);
  181.     }
  182.  
  183.   /*  Find out what device the event occurred upon  */
  184.   if (!gimp_busy && devices_check_change (event))
  185.     gdisplay_check_device_cursor (gdisp);
  186.  
  187.   switch (event->type)
  188.     {
  189.     case GDK_EXPOSE:
  190.       eevent = (GdkEventExpose *) event;
  191.       /*printf(" EXP:%d,%d(%dx%d) ",eevent->area.x, eevent->area.y,
  192.     eevent->area.width, eevent->area.height);fflush(stdout);*/
  193.       redraw (gdisp, eevent->area.x, eevent->area.y,
  194.           eevent->area.width, eevent->area.height);
  195.       break;
  196.  
  197.     case GDK_CONFIGURE:
  198.       /*printf(" CNF ");fflush(stdout);*/
  199.       if ((gdisp->disp_width != gdisp->canvas->allocation.width) ||
  200.       (gdisp->disp_height != gdisp->canvas->allocation.height))
  201.     {
  202.       gdisp->disp_width = gdisp->canvas->allocation.width;
  203.       gdisp->disp_height = gdisp->canvas->allocation.height;
  204.       resize_display (gdisp, FALSE, FALSE);
  205.     }
  206.       break;
  207.  
  208.     case GDK_LEAVE_NOTIFY:
  209.       if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL)
  210.     return TRUE;
  211.       gdisplay_update_cursor (gdisp, 0, 0);
  212.       gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), "");
  213.       info_window_update_RGB (gdisp, -1, -1);
  214.  
  215.     case GDK_PROXIMITY_OUT:
  216.       gdisp->proximity = FALSE;
  217.       break;
  218.  
  219.     case GDK_ENTER_NOTIFY:
  220.       if (((GdkEventCrossing*) event)->mode != GDK_CROSSING_NORMAL)
  221.     return TRUE;
  222.       /* Actually, should figure out tx,ty here */
  223.       break;
  224.  
  225.     case GDK_BUTTON_PRESS:
  226.       bevent = (GdkEventButton *) event;
  227.       state = bevent->state;
  228.  
  229.       /*  ignore new mouse events  */
  230.       if (gimp_busy)
  231.     return TRUE;
  232.  
  233.       switch (bevent->button)
  234.     {
  235.     case 1:
  236.       state |= GDK_BUTTON1_MASK;
  237.       gtk_grab_add (canvas);
  238.  
  239.       /* This is a hack to prevent other stuff being run in the middle of
  240.          a tool operation (like changing image types.... brrrr). We just
  241.          block all the keypress event. A better solution is to implement
  242.          some sort of locking for images.
  243.          Note that this is dependent on specific GTK behavior, and isn't
  244.          guaranteed to work in future versions of GTK.
  245.          -Yosh
  246.        */
  247.       if (key_signal_id == 0)
  248.         key_signal_id = gtk_signal_connect (GTK_OBJECT (canvas),
  249.                         "key_press_event",
  250.                         GTK_SIGNAL_FUNC (gtk_true),
  251.                         NULL);
  252.  
  253.       if (active_tool && ((active_tool->type == MOVE) ||
  254.                   !gimage_is_empty (gdisp->gimage)))
  255.         {
  256.           if (active_tool->auto_snap_to)
  257.         {
  258.           gdisplay_snap_point (gdisp, bevent->x, bevent->y, &tx, &ty);
  259.           bevent->x = tx;
  260.           bevent->y = ty;
  261.           update_cursor = TRUE;
  262.         }
  263.  
  264.           /* reset the current tool if ... */
  265.           if ((/* it has no drawable */
  266.            ! active_tool->drawable ||
  267.  
  268.            /* or a drawable different from the current one */
  269.            (gimage_active_drawable (gdisp->gimage) !=
  270.             active_tool->drawable)) &&
  271.  
  272.           /* and doesn't want to be preserved across drawable changes */
  273.           ! active_tool->preserve)
  274.         {
  275.           tools_initialize (active_tool->type, gdisp);
  276.         }
  277.  
  278.           /* otherwise set it's drawable if it has none */
  279.           else if (! active_tool->drawable)
  280.         {
  281.           active_tool->drawable = gimage_active_drawable (gdisp->gimage);
  282.         }
  283.  
  284.           (* active_tool->button_press_func) (active_tool, bevent, gdisp);
  285.         }
  286.       break;
  287.  
  288.     case 2:
  289.       state |= GDK_BUTTON2_MASK;
  290.       scrolled = TRUE;
  291.       gtk_grab_add (canvas);
  292.       start_grab_and_scroll (gdisp, bevent);
  293.       break;
  294.  
  295.     case 3:
  296.       state |= GDK_BUTTON3_MASK;
  297.       gtk_menu_popup (GTK_MENU (gdisp->popup),
  298.               NULL, NULL, NULL, NULL, 3, bevent->time);
  299.       return_val = TRUE;
  300.       break;
  301.  
  302.       /*  wheelmouse support  */
  303.     case 4:
  304.       state |= GDK_BUTTON4_MASK;
  305.       if (state & GDK_SHIFT_MASK)
  306.         {
  307.           change_scale (gdisp, ZOOMIN);
  308.         }
  309.       else
  310.         {
  311.           GtkAdjustment *adj =
  312.         (state & GDK_CONTROL_MASK) ? gdisp->hsbdata : gdisp->vsbdata;
  313.           gfloat new_value = adj->value - adj->page_increment / 2;
  314.           new_value =
  315.         CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
  316.           gtk_adjustment_set_value (adj, new_value);
  317.         }
  318.       return_val = TRUE;
  319.       break;
  320.  
  321.     case 5:
  322.       state |= GDK_BUTTON5_MASK;
  323.       if (state & GDK_SHIFT_MASK)
  324.         {
  325.           change_scale (gdisp, ZOOMOUT);
  326.         }
  327.       else
  328.         {
  329.           GtkAdjustment *adj =
  330.         (state & GDK_CONTROL_MASK) ? gdisp->hsbdata : gdisp->vsbdata;
  331.           gfloat new_value = adj->value + adj->page_increment / 2;
  332.           new_value = CLAMP (new_value,
  333.                  adj->lower, adj->upper - adj->page_size);
  334.           gtk_adjustment_set_value (adj, new_value);
  335.         }
  336.       return_val = TRUE;
  337.       break;
  338.  
  339.     default:
  340.       break;
  341.     }
  342.       break;
  343.  
  344.     case GDK_BUTTON_RELEASE:
  345.       bevent = (GdkEventButton *) event;
  346.       state = bevent->state;
  347.  
  348.       /*  ugly side condition: all operations which set busy cursors are
  349.        *  invoked on BUTTON_RELEASE, thus no new BUTTON_PRESS events are
  350.        *  accepted while Gimp is busy, thus it should be safe to block
  351.        *  BUTTON_RELEASE.  --Mitch
  352.        *
  353.        *  ugly: fuzzy_select sets busy cursors while ACTIVE.
  354.        */
  355.       if (gimp_busy &&
  356.       !(active_tool->type == FUZZY_SELECT &&
  357.         active_tool->state == ACTIVE))
  358.     return TRUE;
  359.  
  360.       switch (bevent->button)
  361.     {
  362.     case 1:
  363.       state &= ~GDK_BUTTON1_MASK;
  364.  
  365.       /* Lame hack. See above */
  366.       if (key_signal_id)
  367.         {
  368.           gtk_signal_disconnect (GTK_OBJECT (canvas), key_signal_id);
  369.           key_signal_id = 0;
  370.         }
  371.  
  372.       gtk_grab_remove (canvas);
  373.       gdk_pointer_ungrab (bevent->time);  /* fixes pointer grab bug */
  374.       if (active_tool && ((active_tool->type == MOVE) ||
  375.                   !gimage_is_empty (gdisp->gimage)))
  376.         {
  377.           if (active_tool->state == ACTIVE)
  378.         {
  379.           if (active_tool->auto_snap_to)
  380.             {
  381.               gdisplay_snap_point (gdisp, bevent->x, bevent->y, &tx, &ty);
  382.               bevent->x = tx;
  383.               bevent->y = ty;
  384.               update_cursor = TRUE;
  385.             }
  386.           
  387.           (* active_tool->button_release_func) (active_tool, bevent,
  388.                             gdisp);
  389.         }
  390.         }
  391.       break;
  392.  
  393.     case 2:
  394.       state &= ~GDK_BUTTON2_MASK;
  395.       scrolled = FALSE;
  396.       gtk_grab_remove (canvas);
  397.       end_grab_and_scroll (gdisp, bevent);
  398.       break;
  399.  
  400.     case 3:
  401.       state &= ~GDK_BUTTON3_MASK;
  402.       break;
  403.  
  404.       /*  wheelmouse support  */
  405.     case 4:
  406.       state &= ~GDK_BUTTON4_MASK;
  407.       return_val = TRUE;
  408.       break;
  409.  
  410.     case 5:
  411.       state &= ~GDK_BUTTON5_MASK;
  412.       return_val = TRUE;
  413.       break;
  414.  
  415.     default:
  416.       break;
  417.     }
  418.       break;
  419.  
  420.     case GDK_MOTION_NOTIFY:
  421.       mevent = (GdkEventMotion *) event;
  422.       state = mevent->state;
  423.  
  424.       /*  for the same reason we block BUTTON_RELEASE,
  425.        *  we block MOTION_NOTIFY.  --Mitch
  426.        *
  427.        *  ugly: fuzzy_select sets busy cursors while ACTIVE.
  428.        */
  429.       if (gimp_busy &&
  430.       !(active_tool->type == FUZZY_SELECT &&
  431.         active_tool->state == ACTIVE))
  432.     return TRUE;
  433.  
  434.      /* Ask for the pointer position, but ignore it except for cursor
  435.       * handling, so motion events sync with the button press/release events */
  436.  
  437.       if (mevent->is_hint)
  438.     {
  439.       gdk_input_window_get_pointer (canvas->window, current_device, &tx, &ty,
  440. #ifdef GTK_HAVE_SIX_VALUATORS
  441.                     NULL, NULL, NULL, NULL, NULL
  442. #else /* !GTK_HAVE_SIX_VALUATORS */    
  443.                     NULL, NULL, NULL, NULL
  444. #endif /* GTK_HAVE_SIX_VALUATORS */
  445.                     );
  446.     }
  447.       else
  448.     {
  449.       tx = mevent->x;
  450.       ty = mevent->y;
  451.     }
  452.       update_cursor = TRUE;
  453.  
  454.       if (!gdisp->proximity)
  455.     {
  456.       gdisp->proximity = TRUE;
  457.       gdisplay_check_device_cursor (gdisp);
  458.     }
  459.  
  460.       if (active_tool && ((active_tool->type == MOVE) ||
  461.               !gimage_is_empty (gdisp->gimage)) &&
  462.       (mevent->state & GDK_BUTTON1_MASK))
  463.     {
  464.       if (active_tool->state == ACTIVE)
  465.         {
  466.           /*  if the first mouse button is down, check for automatic
  467.            *  scrolling...
  468.            */
  469.           if ((mevent->state & GDK_BUTTON1_MASK) &&
  470.           !active_tool->scroll_lock)
  471.         {
  472.           if (mevent->x < 0 || mevent->y < 0 ||
  473.               mevent->x > gdisp->disp_width ||
  474.               mevent->y > gdisp->disp_height)
  475.             scroll_to_pointer_position (gdisp, mevent);
  476.         }
  477.  
  478.           if (active_tool->auto_snap_to)
  479.         {
  480.           gdisplay_snap_point (gdisp, mevent->x, mevent->y, &tx, &ty);
  481.           mevent->x = tx;
  482.           mevent->y = ty;
  483.           update_cursor = TRUE;
  484.         }
  485.  
  486.           (* active_tool->motion_func) (active_tool, mevent, gdisp);
  487.         }
  488.     }
  489.       else if ((mevent->state & GDK_BUTTON2_MASK) && scrolled)
  490.     {
  491.       grab_and_scroll (gdisp, mevent);
  492.     }
  493.  
  494.       /* Operator update support: Bug #XXXX */
  495.  
  496.       if (/* Should we have a tool...      */
  497.       active_tool && 
  498.       /* and this event is NOT driving */
  499.       /* button press handlers ...     */
  500.       !(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
  501.         {
  502.           /* ...then preconditions to modify a tool */ 
  503.           /* operator state have been met.          */
  504.           (* active_tool->oper_update_func) (active_tool, mevent, gdisp);
  505.         }
  506.  
  507.       break;
  508.  
  509.     case GDK_KEY_PRESS:
  510.       kevent = (GdkEventKey *) event;
  511.       state = kevent->state;
  512.  
  513.       /*  ignore any key presses  */
  514.       if (gimp_busy)
  515.     return TRUE;
  516.  
  517.       switch (kevent->keyval)
  518.     {
  519.     case GDK_Left: case GDK_Right:
  520.     case GDK_Up: case GDK_Down:
  521.       if (active_tool && !gimage_is_empty (gdisp->gimage))
  522.         (* active_tool->arrow_keys_func) (active_tool, kevent, gdisp);
  523.       return_val = TRUE;
  524.       break;
  525.  
  526.     case GDK_Tab:
  527.       if (kevent->state & GDK_MOD1_MASK && !gimage_is_empty (gdisp->gimage))
  528.         layer_select_init (gdisp->gimage, 1, kevent->time);
  529.  
  530.       if (kevent->state & GDK_CONTROL_MASK &&
  531.           !gimage_is_empty (gdisp->gimage))
  532.         layer_select_init (gdisp->gimage, -1, kevent->time);
  533.  
  534.       /* Hide or show all dialogs */
  535.       if (!kevent->state)
  536.         dialog_toggle();
  537.  
  538.       return_val = TRUE;
  539.       break;
  540.  
  541.       /*  Update the state based on modifiers being pressed  */
  542.     case GDK_Alt_L: case GDK_Alt_R:
  543.     case GDK_Shift_L: case GDK_Shift_R:
  544.     case GDK_Control_L: case GDK_Control_R:
  545.       state |= key_to_state (kevent->keyval);
  546.       /* For all modifier keys: call the tools modifier_key_func */
  547.       if (active_tool && !gimage_is_empty (gdisp->gimage))
  548.         {
  549.           gdk_input_window_get_pointer (canvas->window, current_device,
  550. #ifdef GTK_HAVE_SIX_VALUATORS 
  551.                         &tx, &ty, NULL, NULL, NULL, NULL, NULL
  552. #else /* !GTK_HAVE_SIX_VALUATORS */
  553.                         &tx, &ty, NULL, NULL, NULL, NULL
  554. #endif /* GTK_HAVE_SIX_VALUATORS */
  555.                         );
  556.           (* active_tool->modifier_key_func) (active_tool, kevent, gdisp);
  557.           return_val = TRUE;
  558.         }
  559.       break;
  560.     }
  561.       break;
  562.  
  563.     case GDK_KEY_RELEASE:
  564.       kevent = (GdkEventKey *) event;
  565.       state = kevent->state;
  566.  
  567.       /*  ignore any key releases  */
  568.       if (gimp_busy)
  569.     return TRUE;
  570.  
  571.       switch (kevent->keyval)
  572.     {
  573.     case GDK_Alt_L: case GDK_Alt_R:
  574.     case GDK_Shift_L: case GDK_Shift_R:
  575.     case GDK_Control_L: case GDK_Control_R:
  576.       state &= ~key_to_state (kevent->keyval);
  577.       /* For all modifier keys: call the tools modifier_key_func */
  578.       if (active_tool && !gimage_is_empty (gdisp->gimage))
  579.         {
  580.           gdk_input_window_get_pointer (canvas->window, current_device,
  581. #ifdef GTK_HAVE_SIX_VALUATORS
  582.                                             &tx, &ty, NULL, NULL, NULL, NULL, NULL
  583. #else /* !GTK_HAVE_SIX_VALUATORS */
  584.                                         &tx, &ty, NULL, NULL, NULL, NULL
  585. #endif /* GTK_HAVE_SIX_VALUATORS */ 
  586.                         );
  587.           (* active_tool->modifier_key_func) (active_tool, kevent, gdisp);
  588.           return_val = TRUE;
  589.         }
  590.       break;
  591.     }
  592.  
  593.       return_val = TRUE;
  594.       break;
  595.  
  596.     default:
  597.       break;
  598.     }
  599.  
  600.   /*  if we reached this point in gimp_busy mode, return now  */
  601.   if (gimp_busy)
  602.     return TRUE;
  603.  
  604.   /* Cursor update support                               */
  605.   /* no_cursor_updating is TRUE (=1) when                */
  606.   /* <Toolbox>/File/Preferences.../Interface/...         */
  607.   /* Image Windows/Disable Cursor Updating is TOGGLED ON */
  608.  
  609.   if (no_cursor_updating == 0)
  610.     {
  611.       if (active_tool && !gimage_is_empty (gdisp->gimage) &&
  612.       !(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)))
  613.     {
  614.       GdkEventMotion me;
  615.       me.x = tx;  me.y = ty;
  616.       me.state = state;
  617.       (* active_tool->cursor_update_func) (active_tool, &me, gdisp);
  618.     }
  619.       else if (gimage_is_empty (gdisp->gimage))
  620.     {
  621.       gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
  622.                     TOOL_TYPE_NONE,
  623.                     CURSOR_MODIFIER_NONE,
  624.                     FALSE);
  625.     }
  626.     }
  627.  
  628.   if (update_cursor)
  629.     gdisplay_update_cursor (gdisp, tx, ty);
  630.  
  631.   return return_val;
  632. }
  633.  
  634. gint
  635. gdisplay_hruler_button_press (GtkWidget      *widget,
  636.                   GdkEventButton *event,
  637.                   gpointer        data)
  638. {
  639.   GDisplay *gdisp;
  640.  
  641.   if (gimp_busy)
  642.     return TRUE;
  643.  
  644.   if (event->button == 1)
  645.     {
  646.       gdisp = data;
  647.  
  648.       gimp_context_set_tool (gimp_context_get_user (), MOVE);
  649.       move_tool_start_hguide (active_tool, gdisp);
  650.       gtk_grab_add (gdisp->canvas);
  651.     }
  652.  
  653.   return FALSE;
  654. }
  655.  
  656. gint
  657. gdisplay_vruler_button_press (GtkWidget      *widget,
  658.                   GdkEventButton *event,
  659.                   gpointer        data)
  660. {
  661.   GDisplay *gdisp;
  662.  
  663.   if (gimp_busy)
  664.     return TRUE;
  665.  
  666.   if (event->button == 1)
  667.     {
  668.       gdisp = data;
  669.  
  670.       gimp_context_set_tool (gimp_context_get_user (), MOVE);
  671.       move_tool_start_vguide (active_tool, gdisp);
  672.       gtk_grab_add (gdisp->canvas);
  673.     }
  674.  
  675.   return FALSE;
  676. }
  677.  
  678. static void
  679. gdisplay_origin_menu_position (GtkMenu  *menu,
  680.                    gint     *x,
  681.                    gint     *y,
  682.                    gpointer  data)
  683. {
  684.   GtkWidget *origin;
  685.   gint origin_x;
  686.   gint origin_y;
  687.  
  688.   origin = (GtkWidget *) data;
  689.  
  690.   gdk_window_get_origin (origin->window, &origin_x, &origin_y);
  691.  
  692.   *x = origin_x + origin->allocation.x + origin->allocation.width - 1;
  693.   *y = origin_y + origin->allocation.y + (origin->allocation.height - 1) / 2;
  694.  
  695.   if (*x + GTK_WIDGET (menu)->allocation.width > gdk_screen_width ())
  696.     *x -= (GTK_WIDGET (menu)->allocation.width + origin->allocation.width);
  697.  
  698.   if (*y + GTK_WIDGET (menu)->allocation.height > gdk_screen_height ())
  699.     *y -= (GTK_WIDGET (menu)->allocation.height);
  700. }
  701.  
  702. gint
  703. gdisplay_origin_button_press (GtkWidget      *widget,
  704.                   GdkEventButton *event,
  705.                   gpointer        data)
  706. {
  707.   GDisplay *gdisp;
  708.  
  709.   if (!gimp_busy && event->button == 1)
  710.     {
  711.       gdisp = data;
  712.       gtk_menu_popup (GTK_MENU (gdisp->popup),
  713.               NULL, NULL,
  714.               gdisplay_origin_menu_position, widget,
  715.               1, event->time);
  716.     }
  717.  
  718.   /*  Stop the signal emission so the button doesn't grab the
  719.    *  pointer away from us
  720.    */
  721.   gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "button_press_event");
  722.  
  723.   return FALSE;
  724. }
  725.  
  726. gboolean
  727. gdisplay_drag_drop (GtkWidget      *widget,
  728.             GdkDragContext *context,
  729.             gint            x,
  730.             gint            y,
  731.             guint           time,
  732.             gpointer        data)
  733. {
  734.   GDisplay  *gdisp;
  735.   GtkWidget *src_widget;
  736.   gboolean   return_val = FALSE;
  737.  
  738.   gdisp = (GDisplay *) data;
  739.  
  740.   if (!gimp_busy && (src_widget = gtk_drag_get_source_widget (context)))
  741.     {
  742.       GimpDrawable *drawable       = NULL;
  743.       Layer        *layer          = NULL;
  744.       Channel      *channel        = NULL;
  745.       LayerMask    *layer_mask     = NULL;
  746.       GImage       *component      = NULL;
  747.       ChannelType   component_type = -1;
  748.  
  749.       layer = (Layer *) gtk_object_get_data (GTK_OBJECT (src_widget),
  750.                          "gimp_layer");
  751.       channel = (Channel *) gtk_object_get_data (GTK_OBJECT (src_widget),
  752.                          "gimp_channel");
  753.       layer_mask = (LayerMask *) gtk_object_get_data (GTK_OBJECT (src_widget),
  754.                               "gimp_layer_mask");
  755.       component = (GImage *) gtk_object_get_data (GTK_OBJECT (src_widget),
  756.                           "gimp_component");
  757.  
  758.       if (layer)
  759.     {
  760.       drawable = GIMP_DRAWABLE (layer);
  761.     }
  762.       else if (channel)
  763.     {
  764.       drawable = GIMP_DRAWABLE (channel);
  765.     }
  766.       else if (layer_mask)
  767.     {
  768.       drawable = GIMP_DRAWABLE (layer_mask);
  769.     }
  770.       else if (component)
  771.     {
  772.       component_type =
  773.         (ChannelType) gtk_object_get_data (GTK_OBJECT (src_widget),
  774.                            "gimp_component_type");
  775.     }
  776.  
  777.       /*  FIXME: implement special treatment of channel etc.
  778.        */
  779.       if (drawable)
  780.     {
  781.           GImage           *src_gimage;
  782.       Layer            *new_layer;
  783.       GImage           *dest_gimage;
  784.       gint              src_width, src_height;
  785.       gint              dest_width, dest_height;
  786.       gint              off_x, off_y;
  787.       TileManager      *tiles;
  788.       PixelRegion       srcPR, destPR;
  789.       guchar            bg[MAX_CHANNELS];
  790.       gint              bytes; 
  791.           GimpImageBaseType type;
  792.  
  793.       src_gimage = gimp_drawable_gimage (drawable);
  794.           src_width  = gimp_drawable_width  (drawable);
  795.           src_height = gimp_drawable_height (drawable);
  796.  
  797.       /*  How many bytes in the temp buffer?  */
  798.       switch (drawable_type (drawable))
  799.         {
  800.         case RGB_GIMAGE: case RGBA_GIMAGE:
  801.           bytes = 4; type = RGB;
  802.           break;
  803.         case GRAY_GIMAGE: case GRAYA_GIMAGE:
  804.           bytes = 2; type = GRAY;
  805.           break;
  806.         case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
  807.           bytes = 4; type = INDEXED;
  808.           break;
  809.         default:
  810.           bytes = 3; type = RGB;
  811.           break;
  812.         }
  813.  
  814.       gimage_get_background (src_gimage, drawable, bg);
  815.  
  816.       tiles = tile_manager_new (src_width, src_height, bytes);
  817.  
  818.       pixel_region_init (&srcPR, drawable_data (drawable),
  819.                  0, 0, src_width, src_height, FALSE);
  820.       pixel_region_init (&destPR, tiles,
  821.                  0, 0, src_width, src_height, TRUE);
  822.  
  823.       if (type == INDEXED)
  824.         /*  If the layer is indexed...we need to extract pixels  */
  825.         extract_from_region (&srcPR, &destPR, NULL,
  826.                  drawable_cmap (drawable), bg, type,
  827.                  drawable_has_alpha (drawable), FALSE);
  828.       else if (bytes > srcPR.bytes)
  829.         /*  If the layer doesn't have an alpha channel, add one  */
  830.         add_alpha_region (&srcPR, &destPR);
  831.       else
  832.         /*  Otherwise, do a straight copy  */
  833.         copy_region (&srcPR, &destPR);
  834.  
  835.       dest_gimage = gdisp->gimage;
  836.       dest_width  = dest_gimage->width;
  837.       dest_height = dest_gimage->height;
  838.  
  839.       undo_push_group_start (dest_gimage, EDIT_PASTE_UNDO);
  840.  
  841.       new_layer =
  842.         layer_new_from_tiles (dest_gimage,
  843.                   gimp_image_base_type_with_alpha (dest_gimage),
  844.                   tiles, 
  845.                   _("Pasted Layer"),
  846.                   OPAQUE_OPACITY, NORMAL_MODE);
  847.  
  848.       tile_manager_destroy (tiles);
  849.  
  850.       if (new_layer)
  851.         {
  852.           gimp_drawable_set_gimage (GIMP_DRAWABLE (new_layer), dest_gimage);
  853.  
  854.           off_x = (dest_gimage->width - src_width) / 2;
  855.           off_y = (dest_gimage->height - src_height) / 2;
  856.  
  857.           layer_translate (new_layer, off_x, off_y);
  858.  
  859.           gimage_add_layer (dest_gimage, new_layer, -1);
  860.  
  861.           undo_push_group_end (dest_gimage);
  862.  
  863.           gdisplays_flush ();
  864.  
  865.           return_val = TRUE;
  866.         }
  867.     }
  868.     }
  869.  
  870.   gtk_drag_finish (context, return_val, FALSE, time);
  871.  
  872.   if (return_val)
  873.     gimp_context_set_display (gimp_context_get_user (), gdisp);
  874.  
  875.   return return_val;
  876. }
  877.  
  878. static void
  879. gdisplay_bucket_fill (GtkWidget      *widget,
  880.               BucketFillMode  fill_mode,
  881.               guchar          orig_color[],
  882.               TempBuf        *orig_pat_buf,
  883.               gpointer        data)
  884. {
  885.   GimpImage    *gimage;
  886.   GimpDrawable *drawable;
  887.   TileManager  *buf_tiles;
  888.   PixelRegion   bufPR;
  889.   GimpContext  *context;
  890.   gint     x1, x2, y1, y2;
  891.   gint     bytes;
  892.   gboolean has_alpha;
  893.  
  894.   guchar    color[3];
  895.   TempBuf  *pat_buf = NULL;
  896.   gboolean  new_buf = FALSE;
  897.  
  898.   if (gimp_busy)
  899.     return;
  900.  
  901.   gimage = ((GDisplay *) data)->gimage;
  902.   drawable = gimage_active_drawable (gimage);
  903.   if (!drawable)
  904.     return;
  905.  
  906.   gimp_add_busy_cursors ();
  907.  
  908.   /*  Get the bucket fill context  */
  909.   if (! global_paint_options)
  910.     context = tool_info[BUCKET_FILL].tool_context;
  911.   else
  912.     context = gimp_context_get_user ();
  913.  
  914.   /*  Transform the passed data for the dest image  */
  915.   if (fill_mode == FG_BUCKET_FILL)
  916.     {
  917.       gimp_image_transform_color (gimage, drawable, orig_color, color, RGB);
  918.     }
  919.   else
  920.     {
  921.       if (((orig_pat_buf->bytes == 3) && !drawable_color (drawable)) ||
  922.       ((orig_pat_buf->bytes == 1) && !drawable_gray (drawable)))
  923.     {
  924.       guchar *d1, *d2;
  925.       gint size;
  926.  
  927.       if ((orig_pat_buf->bytes == 1) && drawable_color (drawable))
  928.         pat_buf = temp_buf_new (orig_pat_buf->width, orig_pat_buf->height,
  929.                     3, 0, 0, NULL);
  930.       else
  931.         pat_buf = temp_buf_new (orig_pat_buf->width, orig_pat_buf->height,
  932.                     1, 0, 0, NULL);
  933.  
  934.           d1 = temp_buf_data (orig_pat_buf);
  935.           d2 = temp_buf_data (pat_buf);
  936.  
  937.           size = orig_pat_buf->width * orig_pat_buf->height;
  938.           while (size--)
  939.             {
  940.               gimage_transform_color (gimage, drawable, d1, d2,
  941.                       (orig_pat_buf->bytes == 3) ? RGB : GRAY);
  942.               d1 += orig_pat_buf->bytes;
  943.               d2 += pat_buf->bytes;
  944.             }
  945.  
  946.           new_buf = TRUE;
  947.     }
  948.       else
  949.     {
  950.       pat_buf = orig_pat_buf;
  951.     }
  952.     }
  953.  
  954.   drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
  955.   bytes = drawable_bytes (drawable);
  956.   has_alpha = drawable_has_alpha (drawable);
  957.  
  958.   /*  Fill the region  */
  959.   buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
  960.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
  961.   bucket_fill_region (fill_mode, &bufPR, NULL,
  962.               color, pat_buf, x1, y1, has_alpha);
  963.  
  964.   /*  Apply it to the image  */
  965.   pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
  966.   gimage_apply_image (gimage, drawable, &bufPR, TRUE,
  967.               gimp_context_get_opacity (context) * 255,
  968.               gimp_context_get_paint_mode (context),
  969.               NULL, x1, y1);
  970.   tile_manager_destroy (buf_tiles);
  971.  
  972.   /*  Update the displays  */
  973.   drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
  974.   gdisplays_flush ();
  975.  
  976.   if (new_buf)
  977.     temp_buf_free (pat_buf);
  978.  
  979.   gimp_remove_busy_cursors (NULL);
  980. }
  981.  
  982. void
  983. gdisplay_drop_color (GtkWidget *widget,
  984.              guchar     r,
  985.              guchar     g,
  986.              guchar     b,
  987.              gpointer   data)
  988. {
  989.   guchar color[3];
  990.  
  991.   color[0] = r;
  992.   color[1] = g;
  993.   color[2] = b;
  994.  
  995.   gdisplay_bucket_fill (widget, FG_BUCKET_FILL, color, NULL, data);
  996. }
  997.  
  998. void
  999. gdisplay_drop_pattern (GtkWidget *widget,
  1000.                GPattern  *pattern,
  1001.                gpointer   data)
  1002. {
  1003.   gdisplay_bucket_fill (widget, PATTERN_BUCKET_FILL, NULL, pattern->mask, data);
  1004. }
  1005.