diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 30 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 30 | ||||
-rw-r--r-- | gdk/gdkregion-generic.c | 36 | ||||
-rw-r--r-- | gdk/gdkregion.h | 7 | ||||
-rw-r--r-- | gdk/gdkwindow.h | 13 | ||||
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 4 | ||||
-rw-r--r-- | gdk/x11/gdkgc-x11.c | 26 | ||||
-rw-r--r-- | gdk/x11/gdkmain-x11.c | 24 | ||||
-rw-r--r-- | gdk/x11/gdkprivate-x11.h | 6 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 65 | ||||
-rw-r--r-- | gdk/x11/gdkx.h | 2 | ||||
-rw-r--r-- | gtk/gtkentry.c | 321 | ||||
-rw-r--r-- | gtk/gtkentry.h | 5 | ||||
-rw-r--r-- | gtk/testgtk.c | 67 | ||||
-rw-r--r-- | tests/testgtk.c | 67 |
20 files changed, 767 insertions, 86 deletions
@@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index fc0b1c765a..a6251c3040 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,33 @@ +2001-03-02 Havoc Pennington <hp@redhat.com> + + * gdk/x11/gdkgc-x11.c (_gdk_x11_gc_flush): use + _gdk_region_get_xrectangles() + + * gdk/x11/gdkmain-x11.c (_gdk_region_get_xrectangles): new function + + * gtk/testgtk.c (create_shapes): add test for shape_combine_region + + * gdk/x11/gdkwindow-x11.c (gdk_window_shape_combine_region): new + function, contributed by Ron Steinke + + * gdk/x11/gdkevents-x11.c (gdk_wmspec_supported): rename + gdk_net_wm_supports + + * gdk/gdkregion-generic.c (gdk_region_get_rectangles): + New function, contributed by Ron Steinke + + * gtk/gtkentry.c (gtk_entry_get_layout_offsets): New function, + used to line up the text in the entry when using the entry for + editable sheet cell hacks + + * gtk/testgtk.c (create_entry): test the activate_default setting + on GtkEntry + + * gtk/gtkentry.c (gtk_entry_set_activates_default): New function to + cause the entry to activate the default button for a dialog when + activated + (gtk_entry_get_activates_default): new function + Wed Feb 28 19:10:43 2001 Owen Taylor <otaylor@redhat.com> * gtk/gtkclist.c (real_remove_row): Patch from ChiDeok diff --git a/gdk/gdkregion-generic.c b/gdk/gdkregion-generic.c index b049fc0358..524657a529 100644 --- a/gdk/gdkregion-generic.c +++ b/gdk/gdkregion-generic.c @@ -186,6 +186,42 @@ gdk_region_get_clipbox (GdkRegion *r, GdkRectangle *rect) rect->height = r->extents.y2 - r->extents.y1; } + +/** + * gdk_region_get_rectangles: + * @region: a #GdkRegion + * @rectangles: return location for an array of rectangles + * @n_rectangles: length of returned array + * + * Obtains the area covered by the region as a list of rectangles. + * The array returned in @rectangles must be freed with g_free(). + * + **/ +void +gdk_region_get_rectangles (GdkRegion *region, + GdkRectangle **rectangles, + gint *n_rectangles) +{ + gint i; + + g_return_if_fail (region != NULL); + g_return_if_fail (rectangles != NULL); + g_return_if_fail (n_rectangles != NULL); + + *n_rectangles = region->numRects; + *rectangles = g_new (GdkRectangle, region->numRects); + + for (i = 0; i < region->numRects; i++) + { + GdkRegionBox rect; + rect = region->rects[i]; + (*rectangles)[i].x = rect.x1; + (*rectangles)[i].y = rect.y1; + (*rectangles)[i].width = rect.x2 - rect.x1; + (*rectangles)[i].height = rect.y2 - rect.y1; + } +} + void gdk_region_union_with_rect (GdkRegion *region, GdkRectangle *rect) diff --git a/gdk/gdkregion.h b/gdk/gdkregion.h index ad20a65817..f4f4b47803 100644 --- a/gdk/gdkregion.h +++ b/gdk/gdkregion.h @@ -40,8 +40,11 @@ GdkRegion *gdk_region_copy (GdkRegion *region); GdkRegion *gdk_region_rectangle (GdkRectangle *rectangle); void gdk_region_destroy (GdkRegion *region); -void gdk_region_get_clipbox (GdkRegion *region, - GdkRectangle *rectangle); +void gdk_region_get_clipbox (GdkRegion *region, + GdkRectangle *rectangle); +void gdk_region_get_rectangles (GdkRegion *region, + GdkRectangle **rectangles, + gint *n_rectangles); gboolean gdk_region_empty (GdkRegion *region); gboolean gdk_region_equal (GdkRegion *region1, diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 9976265edc..13d1aac253 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -278,10 +278,15 @@ void gdk_window_scroll (GdkWindow *window, * The shape_mask can be the mask * from gdk_pixmap_create_from_xpm. Stefan Wille */ -void gdk_window_shape_combine_mask (GdkWindow *window, - GdkBitmap *shape_mask, - gint offset_x, - gint offset_y); +void gdk_window_shape_combine_mask (GdkWindow *window, + GdkBitmap *shape_mask, + gint offset_x, + gint offset_y); +void gdk_window_shape_combine_region (GdkWindow *window, + GdkRegion *shape_region, + gint offset_x, + gint offset_y); + /* * This routine allows you to quickly take the shapes of all the child windows * of a window and use their shapes as the shape mask for this window - useful diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 7056d9bc75..94153d7f64 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1756,7 +1756,7 @@ gdk_x11_get_server_time (GdkWindow *window) gboolean -gdk_wmspec_supported (GdkAtom property) +gdk_net_wm_supports (GdkAtom property) { static GdkAtom wmspec_check_atom = 0; static GdkAtom wmspec_supported_atom = 0; @@ -1840,7 +1840,7 @@ gdk_wmspec_supported (GdkAtom property) XFree (xwindow); /* since wmspec_check_window != None this isn't infinite. ;-) */ - return gdk_wmspec_supported (property); + return gdk_net_wm_supports (property); } diff --git a/gdk/x11/gdkgc-x11.c b/gdk/x11/gdkgc-x11.c index 8d3dcdae49..34f90a0d28 100644 --- a/gdk/x11/gdkgc-x11.c +++ b/gdk/x11/gdkgc-x11.c @@ -190,21 +190,19 @@ _gdk_x11_gc_flush (GdkGC *gc) gc->clip_x_origin, gc->clip_y_origin); else { - XRectangle *rectangles = g_new (XRectangle, private->clip_region->numRects); - GdkRegionBox *boxes = private->clip_region->rects; - int i; - - for (i=0; i<private->clip_region->numRects; i++) - { - rectangles[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); - rectangles[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); - rectangles[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].x; - rectangles[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].y; - } + XRectangle *rectangles; + gint n_rects; + + _gdk_region_get_xrectangles (private->clip_region, + gc->clip_x_origin, + gc->clip_y_origin, + &rectangles, + &n_rects); - XSetClipRectangles(GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0, rectangles, - private->clip_region->numRects, YXBanded); - + XSetClipRectangles (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0, + rectangles, + n_rects, YXBanded); + g_free (rectangles); } } diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index 1f395e390d..ff6fa309cc 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -53,6 +53,7 @@ #include "gdkprivate-x11.h" #include "gdkinternals.h" +#include "gdkregion-generic.h" #include "gdkinputprivate.h" #include <pango/pangox.h> @@ -737,3 +738,26 @@ gdk_send_xevent (Window window, gboolean propagate, glong event_mask, return result && !gdk_error_code; } + +void +_gdk_region_get_xrectangles (GdkRegion *region, + gint x_offset, + gint y_offset, + XRectangle **rects, + gint *n_rects) +{ + XRectangle *rectangles = g_new (XRectangle, region->numRects); + GdkRegionBox *boxes = region->rects; + gint i; + + for (i = 0; i < region->numRects; i++) + { + rectangles[i].x = CLAMP (boxes[i].x1 + x_offset, G_MINSHORT, G_MAXSHORT); + rectangles[i].y = CLAMP (boxes[i].y1 + y_offset, G_MINSHORT, G_MAXSHORT); + rectangles[i].width = CLAMP (boxes[i].x2 + x_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].x; + rectangles[i].height = CLAMP (boxes[i].y2 + y_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].y; + } + + *rects = rectangles; + *n_rects = region->numRects; +} diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 70aa809b66..0d03177fd3 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -86,6 +86,12 @@ void _gdk_window_process_expose (GdkWindow *window, void _gdk_selection_window_destroyed (GdkWindow *window); gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event); +void _gdk_region_get_xrectangles (GdkRegion *region, + gint x_offset, + gint y_offset, + XRectangle **rects, + gint *n_rects); + extern GdkDrawableClass _gdk_x11_drawable_class; extern gboolean gdk_use_xshm; extern Atom gdk_wm_delete_window; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 548bb587c4..077880fc17 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1066,7 +1066,7 @@ gdk_window_focus (GdkWindow *window, if (GDK_WINDOW_DESTROYED (window)) return; - if (gdk_wmspec_supported (gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE))) + if (gdk_net_wm_supports (gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE))) { XEvent xev; @@ -1831,6 +1831,8 @@ gdk_window_have_shape_ext (void) return (have_shape == YES); } +#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.") + /* * This needs the X11 shape extension. * If not available, shaped windows will look @@ -1842,6 +1844,7 @@ gdk_window_shape_combine_mask (GdkWindow *window, gint x, gint y) { Pixmap pixmap; + gint xoffset, yoffset; g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); @@ -1849,6 +1852,14 @@ gdk_window_shape_combine_mask (GdkWindow *window, #ifdef HAVE_SHAPE_EXT if (GDK_WINDOW_DESTROYED (window)) return; + + _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); + + if (xoffset != 0 || yoffset != 0) + { + WARN_SHAPE_TOO_BIG (); + return; + } if (gdk_window_have_shape_ext ()) { @@ -1874,6 +1885,58 @@ gdk_window_shape_combine_mask (GdkWindow *window, } void +gdk_window_shape_combine_region (GdkWindow *window, + GdkRegion *shape_region, + gint offset_x, + gint offset_y) +{ + gint xoffset, yoffset; + + g_return_if_fail (GDK_IS_WINDOW (window)); + +#ifdef HAVE_SHAPE_EXT + if (GDK_WINDOW_DESTROYED (window)) + return; + + _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); + + if (xoffset != 0 || yoffset != 0) + { + WARN_SHAPE_TOO_BIG (); + return; + } + + if (shape_region == NULL) + { + /* Use NULL mask to unset the shape */ + gdk_window_shape_combine_mask (window, NULL, 0, 0); + return; + } + + if (gdk_window_have_shape_ext ()) + { + gint n_rects = 0; + XRectangle *xrects = NULL; + + _gdk_region_get_xrectangles (shape_region, + 0, 0, + &xrects, &n_rects); + + XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + ShapeBounding, + offset_x, offset_y, + xrects, n_rects, + ShapeSet, + YXBanded); + + g_free (xrects); + } +#endif /* HAVE_SHAPE_EXT */ +} + + +void gdk_window_set_override_redirect (GdkWindow *window, gboolean override_redirect) { diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h index 628d32206f..acb6202675 100644 --- a/gdk/x11/gdkx.h +++ b/gdk/x11/gdkx.h @@ -186,7 +186,7 @@ gpointer gdk_xid_table_lookup (XID xid); guint32 gdk_x11_get_server_time (GdkWindow *window); /* returns TRUE if we support the given WM spec feature */ -gboolean gdk_wmspec_supported (GdkAtom property); +gboolean gdk_net_wm_supports (GdkAtom property); #define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid)) #define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid)) diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 3a087e8992..83ae8285cc 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -41,6 +41,7 @@ #include "gtkseparatormenuitem.h" #include "gtkselection.h" #include "gtksignal.h" +#include "gtkwindow.h" #define MIN_ENTRY_WIDTH 150 #define DRAW_TIMEOUT 20 @@ -73,7 +74,8 @@ enum { PROP_EDITABLE, PROP_MAX_LENGTH, PROP_VISIBILITY, - PROP_INVISIBLE_CHAR + PROP_INVISIBLE_CHAR, + PROP_ACTIVATES_DEFAULT }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -205,6 +207,7 @@ static void gtk_entry_cut_clipboard (GtkEntry *entry); static void gtk_entry_copy_clipboard (GtkEntry *entry); static void gtk_entry_paste_clipboard (GtkEntry *entry); static void gtk_entry_toggle_overwrite (GtkEntry *entry); +static void gtk_entry_real_activate (GtkEntry *entry); /* IM Context Callbacks */ @@ -355,7 +358,8 @@ gtk_entry_class_init (GtkEntryClass *class) class->copy_clipboard = gtk_entry_copy_clipboard; class->paste_clipboard = gtk_entry_paste_clipboard; class->toggle_overwrite = gtk_entry_toggle_overwrite; - + class->activate = gtk_entry_real_activate; + g_object_class_install_property (gobject_class, PROP_TEXT_POSITION, g_param_spec_int ("text_position", @@ -401,6 +405,14 @@ gtk_entry_class_init (GtkEntryClass *class) '*', G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_ACTIVATES_DEFAULT, + g_param_spec_boolean ("activates_default", + _("Activates default"), + _("Whether to activate the default widget (such as the default button in a dialog) when Enter is pressed."), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + signals[INSERT_TEXT] = gtk_signal_new ("insert_text", GTK_RUN_LAST, @@ -675,6 +687,10 @@ static void gtk_entry_set_property (GObject *object, gtk_entry_set_invisible_char (entry, g_value_get_int (value)); break; + case PROP_ACTIVATES_DEFAULT: + gtk_entry_set_activates_default (entry, g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -708,6 +724,9 @@ static void gtk_entry_get_property (GObject *object, case PROP_INVISIBLE_CHAR: g_value_set_int (value, entry->invisible_char); break; + case PROP_ACTIVATES_DEFAULT: + g_value_set_boolean (value, entry->activates_default); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -923,12 +942,94 @@ gtk_entry_size_request (GtkWidget *widget, } static void +get_borders (GtkEntry *entry, + gint *xborder, + gint *yborder) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (entry); + + if (entry->has_frame) + { + if (xborder) + *xborder = widget->style->xthickness; + if (yborder) + *yborder = widget->style->ythickness; + } + else + { + /* 1 pixel for focus rect */ + if (xborder) + *xborder = 1; + if (yborder) + *yborder = 1; + } +} + +static void +get_text_area_size (GtkEntry *entry, + gint *x, + gint *y, + gint *width, + gint *height) +{ + gint xborder, yborder; + GtkRequisition requisition; + GtkWidget *widget; + + widget = GTK_WIDGET (entry); + + gtk_widget_get_child_requisition (widget, &requisition); + + get_borders (entry, &xborder, &yborder); + + if (x) + *x = xborder; + + if (y) + *y = yborder; + + if (width) + *width = GTK_WIDGET (entry)->allocation.width - xborder * 2; + + if (height) + *height = requisition.height - yborder * 2; +} + +static void +get_widget_window_size (GtkEntry *entry, + gint *x, + gint *y, + gint *width, + gint *height) +{ + GtkRequisition requisition; + GtkWidget *widget; + + widget = GTK_WIDGET (entry); + + gtk_widget_get_child_requisition (widget, &requisition); + + if (x) + *x = widget->allocation.x; + + if (y) + *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2; + + if (width) + *width = widget->allocation.width; + + if (height) + *height = requisition.height; +} + +static void gtk_entry_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkEntry *entry; GtkEditable *editable; - gint xborder, yborder; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_ENTRY (widget)); @@ -937,18 +1038,6 @@ gtk_entry_size_allocate (GtkWidget *widget, widget->allocation = *allocation; entry = GTK_ENTRY (widget); editable = GTK_EDITABLE (widget); - - if (entry->has_frame) - { - xborder = widget->style->xthickness; - yborder = widget->style->ythickness; - } - else - { - /* 1 pixel for focus rect */ - xborder = 1; - yborder = 1; - } if (GTK_WIDGET_REALIZED (widget)) { @@ -956,18 +1045,17 @@ gtk_entry_size_allocate (GtkWidget *widget, * backwards compatibility reasons) the realization here to * be affected by the usize of the entry, if set */ - GtkRequisition requisition; - gtk_widget_get_child_requisition (widget, &requisition); - + gint x, y, width, height; + + get_widget_window_size (entry, &x, &y, &width, &height); + gdk_window_move_resize (widget->window, - allocation->x, - allocation->y + (allocation->height - requisition.height) / 2, - allocation->width, requisition.height); + x, y, width, height); + + get_text_area_size (entry, &x, &y, &width, &height); + gdk_window_move_resize (entry->text_area, - xborder, - yborder, - allocation->width - xborder * 2, - requisition.height - yborder * 2); + x, y, width, height); gtk_entry_recompute (entry); } @@ -1777,6 +1865,24 @@ gtk_entry_toggle_overwrite (GtkEntry *entry) entry->overwrite_mode = !entry->overwrite_mode; } +static void +gtk_entry_real_activate (GtkEntry *entry) +{ + GtkWindow *window; + GtkWidget *widget; + + widget = GTK_WIDGET (entry); + + if (entry->activates_default) + { + window = (GtkWindow *) gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + + if (window && + window->default_widget != widget) + gtk_window_activate_default (window); + } +} + /* IM Context Callbacks */ @@ -1987,6 +2093,47 @@ gtk_entry_get_layout (GtkEntry *entry, } static void +get_layout_position (GtkEntry *entry, + gint *x, + gint *y) +{ + PangoLayout *layout; + PangoRectangle logical_rect; + gint area_width, area_height; + gint y_pos; + PangoLayoutLine *line; + + layout = gtk_entry_get_layout (entry, TRUE); + + get_text_area_size (entry, NULL, NULL, &area_width, &area_height); + + area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER); + + line = pango_layout_get_lines (layout)->data; + pango_layout_line_get_extents (line, NULL, &logical_rect); + + /* Align primarily for locale's ascent/descent */ + y_pos = ((area_height - entry->ascent - entry->descent) / 2 + + entry->ascent + logical_rect.y); + + /* Now see if we need to adjust to fit in actual drawn string */ + if (logical_rect.height > area_height) + y_pos = (area_height - logical_rect.height) / 2; + else if (y_pos < 0) + y_pos = 0; + else if (y_pos + logical_rect.height > area_height) + y_pos = area_height - logical_rect.height; + + y_pos = INNER_BORDER + y_pos / PANGO_SCALE; + + if (x) + *x = INNER_BORDER - entry->scroll_offset; + + if (y) + *y = y_pos; +} + +static void gtk_entry_draw_text (GtkEntry *entry) { GtkWidget *widget; @@ -2001,59 +2148,46 @@ gtk_entry_draw_text (GtkEntry *entry) if (GTK_WIDGET_DRAWABLE (entry)) { PangoLayout *layout = gtk_entry_get_layout (entry, TRUE); - PangoRectangle logical_rect; gint area_width, area_height; + gint x, y; gint start_pos, end_pos; - gint y_pos; - - gdk_window_get_size (entry->text_area, &area_width, &area_height); widget = GTK_WIDGET (entry); + + get_layout_position (entry, &x, &y); + + get_text_area_size (entry, NULL, NULL, &area_width, &area_height); gtk_paint_flat_box (widget->style, entry->text_area, GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, NULL, widget, "entry_bg", 0, 0, area_width, area_height); - - area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER); - - line = pango_layout_get_lines (layout)->data; - pango_layout_line_get_extents (line, NULL, &logical_rect); - - /* Align primarily for locale's ascent/descent */ - y_pos = ((area_height - entry->ascent - entry->descent) / 2 + - entry->ascent + logical_rect.y); - - /* Now see if we need to adjust to fit in actual drawn string */ - if (logical_rect.height > area_height) - y_pos = (area_height - logical_rect.height) / 2; - else if (y_pos < 0) - y_pos = 0; - else if (y_pos + logical_rect.height > area_height) - y_pos = area_height - logical_rect.height; - - y_pos = INNER_BORDER + y_pos / PANGO_SCALE; - gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], - INNER_BORDER - entry->scroll_offset, y_pos, + gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state], + x, y, layout); - + if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) { gint *ranges; gint n_ranges, i; + PangoRectangle logical_rect; gint start_index = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text; gint end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text; GdkRegion *clip_region = gdk_region_new (); + line = pango_layout_get_lines (layout)->data; + pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges); + pango_layout_get_extents (layout, NULL, &logical_rect); + for (i=0; i < n_ranges; i++) { GdkRectangle rect; rect.x = INNER_BORDER - entry->scroll_offset + ranges[2*i] / PANGO_SCALE; - rect.y = y_pos; + rect.y = y; rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE; rect.height = logical_rect.height / PANGO_SCALE; @@ -2065,7 +2199,7 @@ gtk_entry_draw_text (GtkEntry *entry) gdk_gc_set_clip_region (widget->style->fg_gc [GTK_STATE_SELECTED], clip_region); gdk_draw_layout (entry->text_area, widget->style->fg_gc [GTK_STATE_SELECTED], - INNER_BORDER - entry->scroll_offset, y_pos, + x, y, layout); gdk_gc_set_clip_region (widget->style->fg_gc [GTK_STATE_SELECTED], NULL); @@ -2705,6 +2839,51 @@ gtk_entry_set_max_length (GtkEntry *entry, } /** + * gtk_entry_set_activates_default: + * @entry: a #GtkEntry + * @setting: %TRUE to activate window's default widget on Enter keypress + * + * If @setting is %TRUE, pressing Enter in the @entry will activate the default + * widget for the window containing the entry. This usually means that + * the dialog box containing the entry will be closed, since the default + * widget is usually one of the dialog buttons. + * + * (For experts: if @setting is %TRUE, the entry calls + * gtk_window_activate_default() on the window containing the entry, in + * the default handler for the "activate" signal.) + * + **/ +void +gtk_entry_set_activates_default (GtkEntry *entry, + gboolean setting) +{ + g_return_if_fail (GTK_IS_ENTRY (entry)); + setting = setting != FALSE; + + if (setting != entry->activates_default) + { + entry->activates_default = setting; + g_object_notify (G_OBJECT (entry), "activates_default"); + } +} + +/** + * gtk_entry_get_activates_default: + * @entry: a #GtkEntry + * + * Retrieves the value set by gtk_entry_set_activates_default(). + * + * Return value: %TRUE if the entry will activate the default widget + **/ +gboolean +gtk_entry_get_activates_default (GtkEntry *entry) +{ + g_return_val_if_fail (GTK_IS_ENTRY (entry), FALSE); + + return entry->activates_default; +} + +/** * gtk_entry_set_has_frame: * @entry: a #GtkEntry * @setting: new value @@ -2729,7 +2908,7 @@ gtk_entry_set_has_frame (GtkEntry *entry, * gtk_entry_get_has_frame: * @entry: a #GtkEntry * - * + * Gets the value set by gtk_entry_set_has_frame(). * * Return value: whether the entry has a beveled frame **/ @@ -2741,6 +2920,40 @@ gtk_entry_get_has_frame (GtkEntry *entry) return entry->has_frame; } +/** + * gtk_entry_get_layout_offsets: + * @entry: a #GtkEntry + * @x: location to store X coordinate of layout + * @y: location to store Y coordinate of layout + * + * Obtains the position of the #PangoLayout used to render text + * in the entry, in widget coordinates. Useful if you want to line + * up the text in an entry with some other text, e.g. when using the + * entry to implement editable cells in a sheet widget. + * + **/ +void +gtk_entry_get_layout_offsets (GtkEntry *entry, + gint *x, + gint *y) +{ + gint text_area_x, text_area_y; + + g_return_if_fail (GTK_IS_ENTRY (entry)); + + /* this gets coords relative to text area */ + get_layout_position (entry, x, y); + + /* convert to widget coords */ + get_text_area_size (entry, &text_area_x, &text_area_y, NULL, NULL); + + if (x) + *x += text_area_x; + + if (y) + *y += text_area_y; +} + /* Quick hack of a popup menu */ static void diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h index eeb6c2bf30..45a5db38a2 100644 --- a/gtk/gtkentry.h +++ b/gtk/gtkentry.h @@ -77,6 +77,8 @@ struct _GtkEntry guint need_im_reset : 1; guint has_frame : 1; + + guint activates_default : 1; guint button; guint timer; @@ -146,6 +148,9 @@ gboolean gtk_entry_get_has_frame (GtkEntry *entry); /* text is truncated if needed */ void gtk_entry_set_max_length (GtkEntry *entry, gint max); +void gtk_entry_set_activates_default (GtkEntry *entry, + gboolean setting); +gboolean gtk_entry_get_activates_default (GtkEntry *entry); /* Somewhat more convenient than the GtkEditable generic functions */ diff --git a/gtk/testgtk.c b/gtk/testgtk.c index 00704342e7..553f606ec0 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -3429,8 +3429,8 @@ static void entry_toggle_visibility (GtkWidget *checkbutton, GtkWidget *entry) { - gtk_entry_set_visibility(GTK_ENTRY(entry), - GTK_TOGGLE_BUTTON(checkbutton)->active); + gtk_entry_set_visibility (GTK_ENTRY (entry), + GTK_TOGGLE_BUTTON (checkbutton)->active); } static void @@ -3443,6 +3443,15 @@ entry_toggle_invisible_char (GtkWidget *checkbutton, gtk_entry_set_invisible_char (GTK_ENTRY (entry), '*'); } + +static void +entry_toggle_activate_default (GtkWidget *checkbutton, + GtkWidget *entry) +{ + gtk_entry_set_activates_default (GTK_ENTRY (entry), + GTK_TOGGLE_BUTTON (checkbutton)->active); +} + static void create_entry (void) { @@ -3452,6 +3461,7 @@ create_entry (void) GtkWidget *editable_check; GtkWidget *sensitive_check; GtkWidget *invisible_char_check; + GtkWidget *activate_check; GtkWidget *entry, *cb; GtkWidget *button; GtkWidget *separator; @@ -3525,6 +3535,13 @@ create_entry (void) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sensitive_check), TRUE); gtk_widget_show (sensitive_check); + activate_check = gtk_check_button_new_with_label ("Activates default"); + gtk_box_pack_start (GTK_BOX (box2), activate_check, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (activate_check), "toggled", + GTK_SIGNAL_FUNC (entry_toggle_activate_default), entry); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (activate_check), FALSE); + gtk_widget_show (activate_check); + invisible_char_check = gtk_check_button_new_with_label("invisible_char = 0"); gtk_box_pack_start (GTK_BOX (box2), invisible_char_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(invisible_char_check), "toggled", @@ -3542,7 +3559,6 @@ create_entry (void) gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); gtk_widget_show (separator); - box2 = gtk_vbox_new (FALSE, 10); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); @@ -7538,7 +7554,8 @@ create_shapes (void) static GtkWidget *modeller = NULL; static GtkWidget *sheets = NULL; static GtkWidget *rings = NULL; - + static GtkWidget *with_region = NULL; + if (!(file_exists ("Modeller.xpm") && file_exists ("FilesQueue.xpm") && file_exists ("3DRings.xpm"))) @@ -7581,6 +7598,48 @@ create_shapes (void) } else gtk_widget_destroy (rings); + + if (!with_region) + { + GdkRegion *region; + gint x, y; + + with_region = shape_create_icon ("3DRings.xpm", + 460, 270, 25,25, GTK_WINDOW_TOPLEVEL); + + gtk_signal_connect (GTK_OBJECT (with_region), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &with_region); + + /* reset shape from mask to a region */ + x = 0; + y = 0; + region = gdk_region_new (); + + while (x < 460) + { + while (y < 270) + { + GdkRectangle rect; + rect.x = x; + rect.y = y; + rect.width = 10; + rect.height = 10; + + gdk_region_union_with_rect (region, &rect); + + y += 20; + } + y = 0; + x += 20; + } + + gdk_window_shape_combine_region (with_region->window, + region, + 0, 0); + } + else + gtk_widget_destroy (with_region); } /* diff --git a/tests/testgtk.c b/tests/testgtk.c index 00704342e7..553f606ec0 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -3429,8 +3429,8 @@ static void entry_toggle_visibility (GtkWidget *checkbutton, GtkWidget *entry) { - gtk_entry_set_visibility(GTK_ENTRY(entry), - GTK_TOGGLE_BUTTON(checkbutton)->active); + gtk_entry_set_visibility (GTK_ENTRY (entry), + GTK_TOGGLE_BUTTON (checkbutton)->active); } static void @@ -3443,6 +3443,15 @@ entry_toggle_invisible_char (GtkWidget *checkbutton, gtk_entry_set_invisible_char (GTK_ENTRY (entry), '*'); } + +static void +entry_toggle_activate_default (GtkWidget *checkbutton, + GtkWidget *entry) +{ + gtk_entry_set_activates_default (GTK_ENTRY (entry), + GTK_TOGGLE_BUTTON (checkbutton)->active); +} + static void create_entry (void) { @@ -3452,6 +3461,7 @@ create_entry (void) GtkWidget *editable_check; GtkWidget *sensitive_check; GtkWidget *invisible_char_check; + GtkWidget *activate_check; GtkWidget *entry, *cb; GtkWidget *button; GtkWidget *separator; @@ -3525,6 +3535,13 @@ create_entry (void) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sensitive_check), TRUE); gtk_widget_show (sensitive_check); + activate_check = gtk_check_button_new_with_label ("Activates default"); + gtk_box_pack_start (GTK_BOX (box2), activate_check, FALSE, TRUE, 0); + gtk_signal_connect (GTK_OBJECT (activate_check), "toggled", + GTK_SIGNAL_FUNC (entry_toggle_activate_default), entry); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (activate_check), FALSE); + gtk_widget_show (activate_check); + invisible_char_check = gtk_check_button_new_with_label("invisible_char = 0"); gtk_box_pack_start (GTK_BOX (box2), invisible_char_check, FALSE, TRUE, 0); gtk_signal_connect (GTK_OBJECT(invisible_char_check), "toggled", @@ -3542,7 +3559,6 @@ create_entry (void) gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0); gtk_widget_show (separator); - box2 = gtk_vbox_new (FALSE, 10); gtk_container_set_border_width (GTK_CONTAINER (box2), 10); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0); @@ -7538,7 +7554,8 @@ create_shapes (void) static GtkWidget *modeller = NULL; static GtkWidget *sheets = NULL; static GtkWidget *rings = NULL; - + static GtkWidget *with_region = NULL; + if (!(file_exists ("Modeller.xpm") && file_exists ("FilesQueue.xpm") && file_exists ("3DRings.xpm"))) @@ -7581,6 +7598,48 @@ create_shapes (void) } else gtk_widget_destroy (rings); + + if (!with_region) + { + GdkRegion *region; + gint x, y; + + with_region = shape_create_icon ("3DRings.xpm", + 460, 270, 25,25, GTK_WINDOW_TOPLEVEL); + + gtk_signal_connect (GTK_OBJECT (with_region), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), + &with_region); + + /* reset shape from mask to a region */ + x = 0; + y = 0; + region = gdk_region_new (); + + while (x < 460) + { + while (y < 270) + { + GdkRectangle rect; + rect.x = x; + rect.y = y; + rect.width = 10; + rect.height = 10; + + gdk_region_union_with_rect (region, &rect); + + y += 20; + } + y = 0; + x += 20; + } + + gdk_window_shape_combine_region (with_region->window, + region, + 0, 0); + } + else + gtk_widget_destroy (with_region); } /* |