6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996,1997,1998,1999 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
29 /* This file written by Bill Wilson for the PCB Gtk port */
38 #include <gdk/gdkkeysyms.h>
41 #include "crosshair.h"
47 #ifdef HAVE_LIBDMALLOC
53 static gint x_pan_speed
, y_pan_speed
;
56 ghid_port_ranges_changed (void)
58 GtkAdjustment
*h_adj
, *v_adj
;
60 if (!ghidgui
->combine_adjustments
)
61 HideCrosshair (FALSE
);
62 if (ghidgui
->combine_adjustments
)
64 ghidgui
->combine_adjustments
= FALSE
;
68 ghidgui
->need_restore_crosshair
= TRUE
;
70 h_adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->h_range
));
71 v_adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->v_range
));
72 gport
->view_x0
= h_adj
->value
;
73 gport
->view_y0
= v_adj
->value
;
75 ghid_invalidate_all ();
79 ghid_port_ranges_pan (gdouble x
, gdouble y
, gboolean relative
)
81 GtkAdjustment
*h_adj
, *v_adj
;
82 gdouble x0
, y0
, x1
, y1
;
84 h_adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->h_range
));
85 v_adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->v_range
));
100 if (x1
< h_adj
->lower
)
102 if (x1
> h_adj
->upper
- h_adj
->page_size
)
103 x1
= h_adj
->upper
- h_adj
->page_size
;
105 if (y1
< v_adj
->lower
)
107 if (y1
> v_adj
->upper
- v_adj
->page_size
)
108 y1
= v_adj
->upper
- v_adj
->page_size
;
110 if (x0
!= x1
&& y0
!= y1
)
111 ghidgui
->combine_adjustments
= TRUE
;
113 gtk_range_set_value (GTK_RANGE (ghidgui
->h_range
), x1
);
115 gtk_range_set_value (GTK_RANGE (ghidgui
->v_range
), y1
);
117 ghid_note_event_location (NULL
);
118 return ((x0
!= x1
) || (y0
!= y1
));
121 /* Do scrollbar scaling based on current port drawing area size and
122 | overall PCB board size.
125 ghid_port_ranges_scale (gboolean emit_changed
)
129 /* Update the scrollbars with PCB units. So Scale the current
130 | drawing area size in pixels to PCB units and that will be
131 | the page size for the Gtk adjustment.
133 gport
->view_width
= gport
->width
* gport
->zoom
;
134 gport
->view_height
= gport
->height
* gport
->zoom
;
136 if (gport
->view_width
>= PCB
->MaxWidth
)
137 gport
->view_width
= PCB
->MaxWidth
;
138 if (gport
->view_height
>= PCB
->MaxHeight
)
139 gport
->view_height
= PCB
->MaxHeight
;
141 adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->h_range
));
142 adj
->page_size
= gport
->view_width
;
143 adj
->upper
= PCB
->MaxWidth
;
145 gtk_signal_emit_by_name (GTK_OBJECT (adj
), "changed");
147 adj
= gtk_range_get_adjustment (GTK_RANGE (ghidgui
->v_range
));
148 adj
->page_size
= gport
->view_height
;
149 adj
->upper
= PCB
->MaxHeight
;
151 gtk_signal_emit_by_name (GTK_OBJECT (adj
), "changed");
155 ghid_port_ranges_zoom (gdouble zoom
)
160 /* figure out zoom values in that would just make the width fit and
161 * that would just make the height fit
163 xtmp
= (gdouble
) PCB
->MaxWidth
/ gport
->width
;
164 ytmp
= (gdouble
) PCB
->MaxHeight
/ gport
->height
;
166 /* if we've tried to zoom further out than what would make the
167 * entire board fit or we passed 0, then pick a zoom that just makes
170 if ((zoom
> xtmp
&& zoom
> ytmp
) || zoom
== 0.0)
171 zoom
= (xtmp
> ytmp
) ? xtmp
: ytmp
;
173 xtmp
= (gport
->view_x
- gport
->view_x0
) / (gdouble
) gport
->view_width
;
174 ytmp
= (gport
->view_y
- gport
->view_y0
) / (gdouble
) gport
->view_height
;
178 ghid_port_ranges_scale(FALSE
);
180 x0
= gport
->view_x
- xtmp
* gport
->view_width
;
185 y0
= gport
->view_y
- ytmp
* gport
->view_height
;
190 ghidgui
->adjustment_changed_holdoff
= TRUE
;
191 gtk_range_set_value (GTK_RANGE (ghidgui
->h_range
), gport
->view_x0
);
192 gtk_range_set_value (GTK_RANGE (ghidgui
->v_range
), gport
->view_y0
);
193 ghidgui
->adjustment_changed_holdoff
= FALSE
;
195 ghid_port_ranges_changed();
199 /* ----------------------------------------------------------------------
200 * handles all events from PCB drawing area
203 static gint event_x
, event_y
;
206 ghid_get_coords (const char *msg
, int *x
, int *y
)
208 if (!ghid_port
.has_entered
)
209 ghid_get_user_xy (msg
);
210 *x
= SIDE_X (gport
->view_x
);
211 *y
= SIDE_Y (gport
->view_y
);
215 ghid_note_event_location (GdkEventButton
* ev
)
222 gdk_window_get_pointer (ghid_port
.drawing_area
->window
, &x
, &y
, NULL
);
231 gport
->view_x
= event_x
* gport
->zoom
+ gport
->view_x0
;
232 gport
->view_y
= event_y
* gport
->zoom
+ gport
->view_y0
;
234 moved
= MoveCrosshairAbsolute (SIDE_X (gport
->view_x
),
235 SIDE_Y (gport
->view_y
));
238 AdjustAttachedObjects ();
239 RestoreCrosshair (False
);
241 ghid_set_cursor_position_labels ();
246 have_crosshair_attachments (void)
248 gboolean result
= FALSE
;
250 switch (Settings
.Mode
)
254 case INSERTPOINT_MODE
:
255 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
258 case PASTEBUFFER_MODE
:
263 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
267 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
271 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
275 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
276 || Crosshair
.AttachedBox
.State
== STATE_THIRD
)
288 ghid_show_crosshair (gboolean show
)
291 static gint x_prev
= -1, y_prev
= -1;
292 static GdkGC
*xor_gc
;
293 static GdkColor cross_color
;
295 if (gport
->x_crosshair
< 0 || ghidgui
->creating
|| !gport
->has_entered
)
300 xor_gc
= gdk_gc_new (ghid_port
.drawing_area
->window
);
301 gdk_gc_copy (xor_gc
, ghid_port
.drawing_area
->style
->white_gc
);
302 gdk_gc_set_function (xor_gc
, GDK_XOR
);
303 /* FIXME: when CrossColor changed from config */
304 ghid_map_color_string (Settings
.CrossColor
, &cross_color
);
306 x
= DRAW_X (gport
->x_crosshair
);
307 y
= DRAW_Y (gport
->y_crosshair
);
309 gdk_gc_set_foreground (xor_gc
, &cross_color
);
313 gdk_draw_line (gport
->drawing_area
->window
, xor_gc
,
314 x_prev
, 0, x_prev
, gport
->height
);
315 gdk_draw_line (gport
->drawing_area
->window
, xor_gc
,
316 0, y_prev
, gport
->width
, y_prev
);
317 if (ghidgui
->auto_pan_on
&& have_crosshair_attachments ())
319 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
320 0, y_prev
- VCD
, VCD
, VCW
);
321 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
322 gport
->width
- VCD
, y_prev
- VCD
, VCD
, VCW
);
323 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
324 x_prev
- VCD
, 0, VCW
, VCD
);
325 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
326 x_prev
- VCD
, gport
->height
- VCD
, VCW
, VCD
);
332 gdk_draw_line (gport
->drawing_area
->window
, xor_gc
,
333 x
, 0, x
, gport
->height
);
334 gdk_draw_line (gport
->drawing_area
->window
, xor_gc
,
335 0, y
, gport
->width
, y
);
336 if (ghidgui
->auto_pan_on
&& have_crosshair_attachments ())
338 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
339 0, y
- VCD
, VCD
, VCW
);
340 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
341 gport
->width
- VCD
, y
- VCD
, VCD
, VCW
);
342 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
343 x
- VCD
, 0, VCW
, VCD
);
344 gdk_draw_rectangle (gport
->drawing_area
->window
, xor_gc
, TRUE
,
345 x
- VCD
, gport
->height
- VCD
, VCW
, VCD
);
351 x_prev
= y_prev
= -1;
355 ghid_idle_cb (gpointer data
)
357 if (Settings
.Mode
== NO_MODE
)
358 SetMode (ARROW_MODE
);
359 ghid_mode_cursor (Settings
.Mode
);
360 if (ghidgui
->settings_mode
!= Settings
.Mode
)
362 ghid_mode_buttons_update ();
364 ghidgui
->settings_mode
= Settings
.Mode
;
366 ghid_update_toggle_flags ();
371 ghid_port_key_release_cb (GtkWidget
* drawing_area
, GdkEventKey
* kev
,
374 gint ksym
= kev
->keyval
;
376 if (ghid_is_modifier_key_sym (ksym
))
377 ghid_note_event_location (NULL
);
379 HideCrosshair (TRUE
);
380 AdjustAttachedObjects ();
381 ghid_invalidate_all ();
382 RestoreCrosshair (TRUE
);
383 ghid_screen_update ();
384 g_idle_add (ghid_idle_cb
, NULL
);
388 /* Handle user keys in the output drawing area.
389 * Note that the default is for all hotkeys to be handled by the
392 * Key presses not handled by the menus will show up here.
396 ghid_port_key_press_cb (GtkWidget
* drawing_area
,
397 GdkEventKey
* kev
, GtkUIManager
* ui
)
399 ModifierKeysState mk
;
402 gint tmp
, ksym
= kev
->keyval
;
405 if (ghid_is_modifier_key_sym (ksym
))
406 ghid_note_event_location (NULL
);
408 mk
= ghid_modifier_keys_state ((GdkModifierType
*) &kev
->state
);
410 ghid_show_crosshair (FALSE
);
412 handled
= TRUE
; /* Start off assuming we handle it */
425 gui
->log ("keysym %d (0x%x) has not been defined\n", ksym
, ksym
);
429 /* FIXME -- since we usually don't make it here, does this code need
430 to go somewhere else?
432 HideCrosshair (TRUE
);
433 AdjustAttachedObjects ();
434 ghid_invalidate_all ();
435 RestoreCrosshair (TRUE
);
436 /* ghid_show_crosshair(TRUE); */
437 ghid_screen_update ();
438 ghid_set_status_line_label ();
439 g_idle_add (ghid_idle_cb
, NULL
);
446 if ((Settings
.Mode
== LINE_MODE
447 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
448 || (Settings
.Mode
== ARC_MODE
449 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
450 || (Settings
.Mode
== RECTANGLE_MODE
451 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
452 || (Settings
.Mode
== POLYGON_MODE
453 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
))
458 static gboolean draw_state_reset
;
459 static gint x_press
, y_press
;
462 ghid_port_button_press_cb (GtkWidget
* drawing_area
,
463 GdkEventButton
* ev
, GtkUIManager
* ui
)
465 GtkWidget
*menu
= gtk_ui_manager_get_widget (ui
, "/Popup1");
466 ModifierKeysState mk
;
467 gboolean drag
, start_pan
= FALSE
;
472 ghid_note_event_location (ev
);
473 mk
= ghid_modifier_keys_state ((GdkModifierType
*) &ev
->state
);
474 ghid_show_crosshair (FALSE
);
475 HideCrosshair (TRUE
);
476 drag
= have_crosshair_attachments ();
477 draw_state_reset
= FALSE
;
482 if (mk
== NONE_PRESSED
|| mk
== SHIFT_PRESSED
)
483 hid_actionl ("Mode", "Notify", NULL
);
484 else if (mk
== CONTROL_PRESSED
)
486 hid_actionl ("Mode", "Save", NULL
);
487 hid_actionl ("Mode", "None", NULL
);
488 hid_actionl ("Mode", "Restore", NULL
);
489 hid_actionl ("Mode", "Notify", NULL
);
491 else if (mk
== SHIFT_CONTROL_PRESSED
)
493 hid_actionl ("Mode", "Save", NULL
);
494 hid_actionl ("Mode", "Remove", NULL
);
495 hid_actionl ("Mode", "Notify", NULL
);
496 hid_actionl ("Mode", "Restore", NULL
);
501 if (mk
== NONE_PRESSED
&& in_draw_state ())
503 if (Settings
.Mode
== LINE_MODE
)
504 hid_actionl ("Mode", "Line", NULL
);
505 else if (Settings
.Mode
== ARC_MODE
)
506 hid_actionl ("Mode", "Arc", NULL
);
507 else if (Settings
.Mode
== RECTANGLE_MODE
)
508 hid_actionl ("Mode", "Rectangle", NULL
);
509 else if (Settings
.Mode
== POLYGON_MODE
)
510 hid_actionl ("Mode", "Polygon", NULL
);
512 hid_actionl ("Mode", "Notify", NULL
);
513 draw_state_reset
= TRUE
;
515 else if (mk
== NONE_PRESSED
)
517 hid_actionl ("Mode", "Save", NULL
);
518 hid_actionl ("Mode", "Stroke", NULL
);
520 else if (mk
== CONTROL_PRESSED
)
522 hid_actionl ("Mode", "Save", NULL
);
523 hid_actionl ("Mode", "Copy", NULL
);
524 hid_actionl ("Mode", "Notify", NULL
);
526 else if (mk
== SHIFT_CONTROL_PRESSED
)
528 hid_actionl ("Display", "ToggleRubberbandMode", NULL
);
529 hid_actionl ("Mode", "Save", NULL
);
530 hid_actionl ("Mode", "Move", NULL
);
531 hid_actionl ("Mode", "Notify", NULL
);
536 if (mk
== NONE_PRESSED
)
538 ghid_mode_cursor (PAN_MODE
);
541 else if (mk
== SHIFT_PRESSED
542 && !ghidgui
->command_entry_status_line_active
)
544 ghidgui
->in_popup
= TRUE
;
545 gtk_widget_grab_focus (drawing_area
);
546 if (GTK_IS_MENU (menu
))
547 gtk_menu_popup (GTK_MENU (menu
), NULL
, NULL
, NULL
,
548 drawing_area
, 3, ev
->time
);
553 ghid_invalidate_all ();
554 RestoreCrosshair (TRUE
);
555 ghid_set_status_line_label ();
556 ghid_show_crosshair (TRUE
);
558 g_idle_add (ghid_idle_cb
, NULL
);
564 ghid_port_button_release_cb (GtkWidget
* drawing_area
,
565 GdkEventButton
* ev
, GtkUIManager
* ui
)
567 ModifierKeysState mk
;
570 ghid_note_event_location (ev
);
571 mk
= ghid_modifier_keys_state ((GdkModifierType
*) &ev
->state
);
573 drag
= have_crosshair_attachments ();
575 HideCrosshair (TRUE
);
580 hid_actionl ("Mode", "Release", NULL
); /* For all modifier states */
584 if (mk
== NONE_PRESSED
&& !draw_state_reset
)
586 hid_actionl ("Mode", "Release", NULL
);
587 hid_actionl ("Mode", "Restore", NULL
);
589 else if (mk
== CONTROL_PRESSED
)
591 hid_actionl ("Mode", "Notify", NULL
);
592 hid_actionl ("Mode", "Restore", NULL
);
594 else if (mk
== SHIFT_CONTROL_PRESSED
)
596 hid_actionl ("Mode", "Notify", NULL
);
597 hid_actionl ("Mode", "Restore", NULL
);
598 hid_actionl ("Display", "ToggleRubberbandMode", NULL
);
603 if (mk
== SHIFT_PRESSED
)
605 hid_actionl ("Display", "Center", NULL
);
606 hid_actionl ("Display", "Restore", NULL
);
608 else if (ev
->x
== x_press
&& ev
->y
== y_press
)
610 ghid_show_crosshair (FALSE
);
611 ghidgui
->auto_pan_on
= !ghidgui
->auto_pan_on
;
612 ghid_show_crosshair (TRUE
);
618 AdjustAttachedObjects ();
619 ghid_invalidate_all ();
620 RestoreCrosshair (TRUE
);
621 ghid_screen_update ();
623 ghid_set_status_line_label ();
624 g_idle_add (ghid_idle_cb
, NULL
);
630 ghid_port_drawing_area_configure_event_cb (GtkWidget
* widget
,
631 GdkEventConfigure
* ev
,
634 static gboolean first_time_done
;
636 HideCrosshair (TRUE
);
637 gport
->width
= ev
->width
;
638 gport
->height
= ev
->height
;
641 gdk_pixmap_unref (gport
->pixmap
);
643 gport
->pixmap
= gdk_pixmap_new (widget
->window
,
644 gport
->width
, gport
->height
, -1);
645 gport
->drawable
= gport
->pixmap
;
647 if (!first_time_done
)
649 gport
->colormap
= gtk_widget_get_colormap (gport
->top_window
);
650 gport
->bg_gc
= gdk_gc_new (gport
->drawable
);
651 if (gdk_color_parse (Settings
.BackgroundColor
, &gport
->bg_color
))
652 gdk_color_alloc (gport
->colormap
, &gport
->bg_color
);
654 gdk_color_white (gport
->colormap
, &gport
->bg_color
);
655 gdk_gc_set_foreground (gport
->bg_gc
, &gport
->bg_color
);
657 gport
->offlimits_gc
= gdk_gc_new (gport
->drawable
);
658 if (gdk_color_parse (Settings
.OffLimitColor
, &gport
->offlimits_color
))
659 gdk_color_alloc (gport
->colormap
, &gport
->offlimits_color
);
661 gdk_color_white (gport
->colormap
, &gport
->offlimits_color
);
662 gdk_gc_set_foreground (gport
->offlimits_gc
, &gport
->offlimits_color
);
663 first_time_done
= TRUE
;
664 PCBChanged (0, NULL
, 0, 0);
668 gdk_pixmap_unref (gport
->mask
);
669 gport
->mask
= gdk_pixmap_new (0, gport
->width
, gport
->height
, 1);
671 ghid_port_ranges_scale (FALSE
);
672 ghid_invalidate_all ();
673 RestoreCrosshair (TRUE
);
679 ghid_screen_update (void)
682 ghid_show_crosshair (FALSE
);
683 gdk_draw_drawable (gport
->drawing_area
->window
, gport
->bg_gc
, gport
->pixmap
,
684 0, 0, 0, 0, gport
->width
, gport
->height
);
685 ghid_show_crosshair (TRUE
);
689 ghid_port_drawing_area_expose_event_cb (GtkWidget
* widget
,
690 GdkEventExpose
* ev
, GHidPort
* port
)
692 ghid_show_crosshair (FALSE
);
693 gdk_draw_drawable (widget
->window
, port
->bg_gc
, port
->pixmap
,
694 ev
->area
.x
, ev
->area
.y
, ev
->area
.x
, ev
->area
.y
,
695 ev
->area
.width
, ev
->area
.height
);
696 ghid_show_crosshair (TRUE
);
701 ghid_port_window_motion_cb (GtkWidget
* widget
,
702 GdkEventButton
* ev
, GHidPort
* out
)
704 ModifierKeysState mk
= ghid_modifier_keys_state ((GdkModifierType
*) &ev
->state
);
706 static gint x_prev
, y_prev
;
709 if ((ev
->state
& GDK_BUTTON3_MASK
) == GDK_BUTTON3_MASK
710 && mk
== NONE_PRESSED
)
712 if (gtk_events_pending ())
714 dx
= gport
->zoom
* (x_prev
- ev
->x
);
715 dy
= gport
->zoom
* (y_prev
- ev
->y
);
717 ghid_port_ranges_pan (dx
, dy
, TRUE
);
722 x_prev
= y_prev
= -1;
723 moved
= ghid_note_event_location (ev
);
724 ghid_show_crosshair (TRUE
);
725 if (moved
&& have_crosshair_attachments ())
726 ghid_draw_area_update (gport
, NULL
);
731 ghid_port_window_enter_cb (GtkWidget
* widget
,
732 GdkEventCrossing
* ev
, GHidPort
* out
)
734 /* printf("mode: %d type: %d\n", ev->mode, ev->detail); */
736 /* See comment in ghid_port_window_leave_cb() */
738 if(ev
->mode
!= GDK_CROSSING_NORMAL
&& ev
->detail
!= GDK_NOTIFY_NONLINEAR
)
744 if (!ghidgui
->command_entry_status_line_active
)
746 out
->has_entered
= TRUE
;
747 /* Make sure drawing area has keyboard focus when we are in it.
749 gtk_widget_grab_focus (out
->drawing_area
);
751 ghidgui
->in_popup
= FALSE
;
752 RestoreCrosshair (TRUE
);
754 /* Following expression is true if a you open a menu from the menu bar,
755 * move the mouse to the viewport and click on it. This closes the menu
756 * and moves the pointer to the viewport without the pointer going over
757 * the edge of the viewport */
758 if(ev
->mode
== GDK_CROSSING_UNGRAB
&& GDK_NOTIFY_NONLINEAR
)
760 ghid_screen_update ();
767 ghid_pan_idle_cb (gpointer data
)
769 gdouble dx
= 0, dy
= 0;
771 if (gport
->has_entered
)
773 dy
= gport
->zoom
* y_pan_speed
;
774 dx
= gport
->zoom
* x_pan_speed
;
775 return (ghid_port_ranges_pan (dx
, dy
, TRUE
));
779 ghid_port_window_leave_cb (GtkWidget
* widget
,
780 GdkEventCrossing
* ev
, GHidPort
* out
)
782 gint x0
, y0
, x
, y
, dx
, dy
, w
, h
;
784 /* printf("mode: %d type: %d\n", ev->mode, ev->detail); */
786 /* Window leave events can also be triggered because of focus grabs. Some
787 * X applications occasionally grab the focus and so trigger this function.
788 * At least GNOME's window manager is known to do this on every mouse click.
790 * See http://bugzilla.gnome.org/show_bug.cgi?id=102209
793 if(ev
->mode
!= GDK_CROSSING_NORMAL
)
798 if (out
->has_entered
&& !ghidgui
->in_popup
)
800 /* if actively drawing, start scrolling */
802 if (have_crosshair_attachments () && ghidgui
->auto_pan_on
)
804 /* GdkEvent coords are set to 0,0 at leave events, so must figure
805 | out edge the cursor left.
807 w
= ghid_port
.width
* gport
->zoom
;
808 h
= ghid_port
.height
* gport
->zoom
;
812 ghid_get_coords (NULL
, &x
, &y
);
819 x_pan_speed
= y_pan_speed
= 2 * ghidgui
->auto_pan_speed
;
823 x_pan_speed
= -x_pan_speed
;
828 y_pan_speed
= -y_pan_speed
;
834 y_pan_speed
= y_pan_speed
- (3 * dy
* y_pan_speed
) / h
;
841 x_pan_speed
= x_pan_speed
- (3 * dx
* x_pan_speed
) / w
;
845 g_idle_add (ghid_pan_idle_cb
, NULL
);
849 ghid_show_crosshair (FALSE
);
850 out
->has_entered
= FALSE
;
852 ghid_screen_update ();
858 /* Mouse scroll wheel events
861 ghid_port_window_mouse_scroll_cb (GtkWidget
* widget
,
862 GdkEventScroll
* ev
, GHidPort
* out
)
864 ModifierKeysState mk
= ghid_modifier_keys_state ((GdkModifierType
*) &ev
->state
);
865 gdouble dx
= 0.0, dy
= 0.0, zoom_factor
;
867 if (mk
== NONE_PRESSED
)
869 zoom_factor
= (ev
->direction
== GDK_SCROLL_UP
) ? 0.8 : 1.25;
870 ghid_port_ranges_zoom (gport
->zoom
* zoom_factor
);
874 if (mk
== SHIFT_PRESSED
)
875 dy
= ghid_port
.height
* gport
->zoom
/ 40;
877 dx
= ghid_port
.width
* gport
->zoom
/ 40;
879 if (ev
->direction
== GDK_SCROLL_UP
)
885 HideCrosshair (FALSE
);
886 ghid_port_ranges_pan (dx
, dy
, TRUE
);
887 MoveCrosshairRelative (dx
, dy
);
888 AdjustAttachedObjects ();
889 RestoreCrosshair (FALSE
);