Merge no-flicker branch into HEAD

This commit is contained in:
Owen Taylor 2000-03-28 01:24:44 +00:00
parent 4238d406e9
commit 8098546227
68 changed files with 9281 additions and 1896 deletions

176
ChangeLog
View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -1,3 +1,179 @@
Thu Feb 24 23:58:21 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkgeometry-x11.c: Don't worry about clipping of
toplevel windows and their immediate children by their parents,
since the size of toplevel windows is out of our immediate
control and we don't get any real benefit from trying to track
this size for clipping.
* gdk/gdkprivate.h (struct _GdkWindowPrivate) gdk/x11/gdkwindow-x11.c : Add a flag
for input_only windows.
* gdk/gdkwindow.c gdk/x11/gdkgeometry-x11.c: Use the above flag
to fix some hacks and make sure that we don't try to set the
background of input only windows.
Thu Feb 24 18:11:46 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkinternals.h gdk/gdkprivate.h gdk/Makefile.am: Add a header file for
the _really_ internal stuff, and leave gdkprivate.h for the fake private
stuff that we've traditionally exposed.
* gdk/**.c: Use gdkinternals.h where appropriate.
* gdk/x11/gdkx.h gdk/x11/gdkprivate-x11.h gdk/x11/*.c: Make gdkx.h
not include gdkprivate-x11.h, move all stuff of conceivable public
interest into gdkx.h; keep all really private stuff in
uninstalled header gdkprivate-x11.h.
* gdk/gdkdraw.c gdk/gdkwindow.c gdk/gdkinternals: Redirect all calls to
image->image_put on windows through a new function _gdk_window_draw_image()
to allow us to do backing store for images. (Sort of ugly)
* gdk/gdkgc.c gdk/gdkprivate.h: Cache the ts and clip origins for graphics
contexts locally so that we can offset them properly when drawing
onto backing pixmaps.
* gdk/gdkinput.h: Reindented
* gdk/gdkprivate.h gdk/x11/gdkwindow-x11.c: Store the background
pixmap or color for the window, so we can properly initialize
our double-buffer pixmaps, and also so that we temporarily set
a background of None while scrolling.
* gdk/gdkregion.h: Revise region boolean operators to have an
interface that is actually convenient - switch from creating new
regions on every op, to "methods" that modify existing regions
(A = A OP B). 3 argument forms which allow dest == src, would also
be possible, but the current interfaces seem to map nicely
onto what needs to be done. (There is quite a lot of region
code in GDK now.)
* gdk/gdkregion.h: Add constructor from rectangle and a copy
operator.
* gdk/x11/{gdkregion-generic.[ch],gdkpolyreg-generic.c,
gdkpoly-generic.h: Copy region code from Xlib, switch it over
to 32 bit coordinates, modify it to be mostly GTK+ style
and to have interfaces that match gdkregion.h.
* gdk/gdkwindow.c gdk/gdkprivate.h: Add facility for
double-buffered drawing. gdk_window_begin_paint_{rect,region}()
create a backing pixmap and redirect all drawing to
that backing pixmap until a matching gdk_window_end_paint().
* gdk/gdkwindow.[ch] gdk/gdkinternals.h gdk/x11/gdkdrawable-x11.c:
Create a special drawable class for GtkWindow's that
redirects the drawing to the backing pixmap as necessary
and then calls the real operations in _gdk_windowing_window_class.
* gdk/gdkprivate.h gdk/gdkwindow.[ch] gdk/x11/gdkevents-x11.c:
Store invalid region for each window. Generate expose events for invalid
region in an idle. This replaces both the expose compression
and the redrawing queuing in GTK+. It is both more efficient and
simpler than either one individually and far more so then the
combination.
* gdk/x11/gdkgeometry.c gdk/x11/gdkwindow.c gdk/x11/gdkprivate-x11.h:
Emulate 32 bit coordinates for windows with 16 bit coordinates
by offsetting drawing, guffaw scrolling techniques and
mapping/unmapping child windows as necessary.
* gdk/gdkwindow.[ch] gdk/x11/gdkgeometry.c: Add anti-exposes,
where, when invalid regions are processed, the region is stored,
and if expose events come in that are detectably duplicate
the processed exposes (by comparison of event serial numbers),
the stored region is subtracted out of those exposes.
* gdk/x11/gdkgeometry.c: Temporarily unset backing pixmaps of
regions newly exposed when scrolling or resizing windows.
This, combined with forcing processesing of queued invalidated
regions, gives nice flicker-free scrolling.
* gtk/gtklayout.c gtk/gtkviewport.c: Force processing of
invalidated regions after every scroll.
* gtk/gtklayout.c: Vastly simplify using the new 32 bit coordinate
emulation in GDK. Its, for all practical purposes just a
GtkViewport/GtkFixed hybrid now.
* gdk/gdkdrawable-x11.c: Convert from GDK (32 bit) to X11
(16-bit) structures as necessary instead of just casting.
* gdk/x11/gdkgc-x11.c gdk/x11/gdkx.h: Replace XSetRegion with code
in terms of the structures from gdkregion-generic.c, using appropriate
offsets from GDK to X11 coordinates. Cache clip mask and
origin and ts origin locally and only flush to the server
when drawing, to avoid constantly setting and resetting these
values when offsetting GC's for scrolling and backing pixmaps.
* gdk/x11/gdkinput-x11.c: Fix leak of axes structures.
* gtk/gtkcontainer.c: Call process_all_updates at end
of resizing to reduce flicker. (Avoids having redraw
lag arbitrarily behind resize under some circumstances)
* gtk/gtkentry.c: Remove old backing store code, and simply take
advantage of the new backing store capabilities of GDK.
* gtk/gtkmain.c: Simple implementation of widget backing
store - simply push a paint while handling each expose.
(Should really be configurable widget for widget.)
* gtk/gtkwidget.c: Remove all the old complicated redraw
code, and simply invalidate the GDK windows from
gdk_window_queue_clear(), etc. (Sigh, so much carefully
debugged complexity ... gone to the winds.)
Remove all the code for suppressing expose events while
resizes are pending; this isn't needed since the invalid
areas won't be processed until after the resizes are
processed, since they are in a lower priority idle.
Thu Feb 24 15:37:41 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdkrectangle.c (gdk_rectangle_intersect): Set width
and height of dest rectangle for non-intersecting rectangles.
Sun Feb 20 16:47:31 2000 Owen Taylor <otaylor@redhat.com>
* gtk/gtkwidget.h: Make GtkAllocation just a typedef
for GdkRectangle.
Sun Feb 20 11:27:00 2000 Owen Taylor <otaylor@redhat.com>
* gdk/gdk{events,image,private,types,window}.h
gdk/x11/gdkinputprivate.h: Change all coordinates
from int16 to int. Also, Change width and height from
unsigned to signed to avoid all the stupid C
signedness bugs.
Sat Feb 19 12:01:53 2000 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkdrawable-x11.c (gdk_x11_draw_drawable):
Use gdk_drawable_get_depth instead of gdk_drawable_get_visual.
Add some more detailed checking.
* gdk/gdkdraw.c gdk/gdkdrawable.h (gdk_drawable_get_depth):
New function to retrieve the depth of a drawable.
* gdk/gdkprivate.h (struct _GdkDrawablePrivate): Add a depth
field, reorder fields to save memory.
Mon Dec 13 14:06:03 1999 Owen Taylor <otaylor@redhat.com>
* gtk/gtkentry.c (gtk_entry_draw_cursor_on_drawable): Draw a small portion
of the background image instead of scaling the background down to
a line.
* gtk/gtk[hv]scrollbar.c (gtk_hscrollbar_size_allocate): Removed mysterious
which temporarily set slider to wrong size.
* gtk/gtkaspectframe.c gtkbin.c: Remove unecessary calls to
queue_clear().
Wed Nov 17 18:36:05 1999 Owen Taylor <otaylor@redhat.com>
2000-03-23 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkpaned.c (gtk_paned_get_position): add getter.

View File

@ -18,4 +18,6 @@ Incompatible Changes from GTK+-1.2 to GTK+-1.4:
that the automatic grab that occurs when the user presses a button
will have owner_events = FALSE, so all events are redirected to the
grab window, even events that would normally go to other windows of the
window's owner.
window's owner.
- The detail arguments in the GtkStyleClass structure are now 'const gchar *'.

View File

@ -83,6 +83,7 @@ gdk_c_sources = @STRIP_BEGIN@ \
gdkgc.c \
gdkglobals.c \
gdkimage.c \
gdkinternals.h \
gdkrgb.c \
gdkrectangle.c \
gdkwindow.c \

View File

@ -30,7 +30,7 @@
#include <stdlib.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinternals.h"
#ifndef HAVE_XCONVERTCASE
#include "gdkkeysyms.h"

View File

@ -47,6 +47,8 @@ gdk_drawable_alloc (void)
private->width = 1;
private->height = 1;
private->depth = 0;
private->colormap = NULL;
return drawable;
@ -104,6 +106,15 @@ gdk_drawable_get_visual (GdkDrawable *drawable)
return colormap ? gdk_colormap_get_visual (colormap) : NULL;
}
gint
gdk_drawable_get_depth (GdkDrawable *drawable)
{
GdkDrawablePrivate *private = (GdkDrawablePrivate *)drawable;
g_return_val_if_fail (drawable != NULL, 0);
return private->depth;
}
GdkDrawable*
gdk_drawable_ref (GdkDrawable *drawable)
{
@ -365,8 +376,12 @@ gdk_draw_image (GdkDrawable *drawable,
height = image->height;
image_private->klass->image_put (image, drawable, gc, xsrc, ysrc,
xdest, ydest, width, height);
if (GDK_IS_WINDOW (drawable))
_gdk_window_draw_image (drawable, gc, image, xsrc, ysrc,
xdest, ydest, width, height);
else
image_private->klass->image_put (image, drawable, gc, xsrc, ysrc,
xdest, ydest, width, height);
}
void

View File

@ -130,6 +130,7 @@ void gdk_drawable_set_colormap (GdkDrawable *drawable,
GdkColormap *colormap);
GdkColormap* gdk_drawable_get_colormap (GdkDrawable *drawable);
GdkVisual* gdk_drawable_get_visual (GdkDrawable *drawable);
gint gdk_drawable_get_depth (GdkDrawable *drawable);
GdkDrawable* gdk_drawable_ref (GdkDrawable *drawable);
void gdk_drawable_unref (GdkDrawable *drawable);

View File

@ -25,7 +25,7 @@
*/
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinternals.h"
typedef struct _GdkIOClosure GdkIOClosure;
typedef struct _GdkEventPrivate GdkEventPrivate;

View File

@ -317,9 +317,9 @@ struct _GdkEventConfigure
GdkEventType type;
GdkWindow *window;
gint8 send_event;
gint16 x, y;
gint16 width;
gint16 height;
gint x, y;
gint width;
gint height;
};
struct _GdkEventProperty

View File

@ -38,6 +38,10 @@ gdk_gc_alloc (void)
private->ref_count = 1;
private->klass = NULL;
private->klass_data = NULL;
private->clip_x_origin = 0;
private->clip_y_origin = 0;
private->ts_x_origin = 0;
private->ts_y_origin = 0;
return (GdkGC *)private;
}
@ -58,14 +62,29 @@ gdk_gc_new_with_values (GdkDrawable *drawable,
GdkGCValues *values,
GdkGCValuesMask values_mask)
{
GdkGC *gc;
GdkGCPrivate *private;
g_return_val_if_fail (drawable != NULL, NULL);
if (GDK_DRAWABLE_DESTROYED (drawable))
return NULL;
return ((GdkDrawablePrivate *)drawable)->klass->create_gc (drawable,
values,
values_mask);
gc = ((GdkDrawablePrivate *)drawable)->klass->create_gc (drawable,
values,
values_mask);
private = (GdkGCPrivate *)gc;
if (values_mask & GDK_GC_CLIP_X_ORIGIN)
private->clip_x_origin = values->clip_x_origin;
if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
private->clip_y_origin = values->clip_y_origin;
if (values_mask & GDK_GC_TS_X_ORIGIN)
private->ts_x_origin = values->ts_x_origin;
if (values_mask & GDK_GC_TS_Y_ORIGIN)
private->ts_y_origin = values->ts_y_origin;
return gc;
}
GdkGC *
@ -90,7 +109,10 @@ gdk_gc_unref (GdkGC *gc)
private->ref_count--;
if (private->ref_count == 0)
private->klass->destroy (gc);
{
private->klass->destroy (gc);
g_free (private);
}
}
void
@ -108,10 +130,21 @@ gdk_gc_set_values (GdkGC *gc,
GdkGCValues *values,
GdkGCValuesMask values_mask)
{
GdkGCPrivate *private = (GdkGCPrivate *)gc;
g_return_if_fail (gc != NULL);
g_return_if_fail (values != NULL);
((GdkGCPrivate *)gc)->klass->set_values (gc, values, values_mask);
if (values_mask & GDK_GC_CLIP_X_ORIGIN)
private->clip_x_origin = values->clip_x_origin;
if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
private->clip_y_origin = values->clip_y_origin;
if (values_mask & GDK_GC_TS_X_ORIGIN)
private->ts_x_origin = values->ts_x_origin;
if (values_mask & GDK_GC_TS_Y_ORIGIN)
private->ts_y_origin = values->ts_y_origin;
private->klass->set_values (gc, values, values_mask);
}
void

View File

@ -34,8 +34,8 @@ struct _GdkImage
GdkImageType type;
GdkVisual *visual; /* visual used to create the image */
GdkByteOrder byte_order;
guint16 width;
guint16 height;
gint width;
gint height;
guint16 depth;
guint16 bpp; /* bytes per pixel */
guint16 bpl; /* bytes per line */

View File

@ -99,7 +99,6 @@ GdkTimeCoord *gdk_input_motion_events (GdkWindow *window,
guint32 deviceid,
guint32 start,
guint32 stop,
gint *nevents_return);
#ifdef __cplusplus
}

210
gdk/gdkinternals.h Normal file
View File

@ -0,0 +1,210 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
/* Uninstalled header defining types and functions internal to GDK */
#include <gdk/gdktypes.h>
#include <gdk/gdkprivate.h>
#ifndef __GDK_INTERNALS_H__
#define __GDK_INTERNALS_H__
/**********************
* General Facilities *
**********************/
/* Debugging support */
typedef enum {
GDK_DEBUG_MISC = 1 << 0,
GDK_DEBUG_EVENTS = 1 << 1,
GDK_DEBUG_DND = 1 << 2,
GDK_DEBUG_COLOR_CONTEXT = 1 << 3,
GDK_DEBUG_XIM = 1 << 4
} GdkDebugFlag;
extern gint gdk_debug_level;
extern gboolean gdk_show_events;
extern GList *gdk_default_filters;
GDKVAR guint gdk_debug_flags;
#ifdef G_ENABLE_DEBUG
#define GDK_NOTE(type,action) G_STMT_START { \
if (gdk_debug_flags & GDK_DEBUG_##type) \
{ action; }; } G_STMT_END
#else /* !G_ENABLE_DEBUG */
#define GDK_NOTE(type,action)
#endif /* G_ENABLE_DEBUG */
/* Arg parsing */
typedef enum
{
GDK_ARG_STRING,
GDK_ARG_INT,
GDK_ARG_BOOL,
GDK_ARG_NOBOOL,
GDK_ARG_CALLBACK
} GdkArgType;
typedef struct _GdkArgContext GdkArgContext;
typedef struct _GdkArgDesc GdkArgDesc;
typedef void (*GdkArgFunc) (const char *name, const char *arg, gpointer data);
struct _GdkArgContext
{
GPtrArray *tables;
gpointer cb_data;
};
struct _GdkArgDesc
{
const char *name;
GdkArgType type;
gpointer location;
GdkArgFunc callback;
};
/* Event handling */
extern GdkEventFunc gdk_event_func; /* Callback for events */
extern gpointer gdk_event_data;
extern GDestroyNotify gdk_event_notify;
/* FIFO's for event queue, and for events put back using
* gdk_event_put().
*/
extern GList *gdk_queued_events;
extern GList *gdk_queued_tail;
GdkEvent* gdk_event_new (void);
void gdk_events_init (void);
void gdk_events_queue (void);
GdkEvent* gdk_event_unqueue (void);
GList* gdk_event_queue_find_first (void);
void gdk_event_queue_remove_link (GList *node);
void gdk_event_queue_append (GdkEvent *event);
void gdk_event_button_generate (GdkEvent *event);
/*************************************
* Interfaces used by windowing code *
*************************************/
#ifdef USE_XIM
/* XIM support */
gint gdk_im_open (void);
void gdk_im_close (void);
void gdk_ic_cleanup (void);
#endif /* USE_XIM */
GdkWindow* _gdk_window_alloc (void);
void _gdk_window_draw_image (GdkDrawable *drawable,
GdkGC *gc,
GdkImage *image,
gint xsrc,
gint ysrc,
gint xdest,
gint ydest,
gint width,
gint height);
/*****************************************
* Interfaces provided by windowing code *
*****************************************/
/* Font/string functions implemented in module-specific code */
gint _gdk_font_strlen (GdkFont *font, const char *str);
void _gdk_font_destroy (GdkFont *font);
void _gdk_colormap_real_destroy (GdkColormap *colormap);
void _gdk_cursor_destroy (GdkCursor *cursor);
/* Class supplied by windowing-system-dependent code for GdkWindow.
*/
extern GdkDrawableClass _gdk_windowing_window_class;
/* Class for covering over windowing-system-dependent and backing-store
* code for GdkWindow
*/
extern GdkDrawableClass _gdk_window_class;
extern GdkArgDesc _gdk_windowing_args[];
gboolean _gdk_windowing_init_check (int argc,
char **argv);
void _gdk_windowing_window_get_offsets (GdkWindow *window,
gint *x_offset,
gint *y_offset);
void _gdk_windowing_window_clear_area (GdkWindow *window,
gint x,
gint y,
gint width,
gint height);
void _gdk_windowing_window_clear_area_e (GdkWindow *window,
gint x,
gint y,
gint width,
gint height);
/* Called before processing updates for a window. This gives the windowing
* layer a chance to save the region for later use in avoiding duplicate
* exposes. The return value indicates whether the function has a saved
* the region; if the result is TRUE, then the windowing layer is responsible
* for destroying the region later.
*/
gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
GdkRegion *area);
/************************************
* Initialization and exit routines *
************************************/
void gdk_window_init (void);
void gdk_visual_init (void);
void gdk_dnd_init (void);
void gdk_image_init (void);
void gdk_image_exit (void);
void gdk_input_init (void);
void gdk_input_exit (void);
void gdk_windowing_exit (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GDK_INTERNALS_H__ */

291
gdk/gdkpoly-generic.h Normal file
View File

@ -0,0 +1,291 @@
/* $TOG: poly.h /main/5 1998/02/06 17:47:27 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
/*
* This file contains a few macros to help track
* the edge of a filled object. The object is assumed
* to be filled in scanline order, and thus the
* algorithm used is an extension of Bresenham's line
* drawing algorithm which assumes that y is always the
* major axis.
* Since these pieces of code are the same for any filled shape,
* it is more convenient to gather the library in one
* place, but since these pieces of code are also in
* the inner loops of output primitives, procedure call
* overhead is out of the question.
* See the author for a derivation if needed.
*/
/*
* In scan converting polygons, we want to choose those pixels
* which are inside the polygon. Thus, we add .5 to the starting
* x coordinate for both left and right edges. Now we choose the
* first pixel which is inside the pgon for the left edge and the
* first pixel which is outside the pgon for the right edge.
* Draw the left pixel, but not the right.
*
* How to add .5 to the starting x coordinate:
* If the edge is moving to the right, then subtract dy from the
* error term from the general form of the algorithm.
* If the edge is moving to the left, then add dy to the error term.
*
* The reason for the difference between edges moving to the left
* and edges moving to the right is simple: If an edge is moving
* to the right, then we want the algorithm to flip immediately.
* If it is moving to the left, then we don't want it to flip until
* we traverse an entire pixel.
*/
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
int dx; /* local storage */ \
\
/* \
* if the edge is horizontal, then it is ignored \
* and assumed not to be processed. Otherwise, do this stuff. \
*/ \
if ((dy) != 0) { \
xStart = (x1); \
dx = (x2) - xStart; \
if (dx < 0) { \
m = dx / (dy); \
m1 = m - 1; \
incr1 = -2 * dx + 2 * (dy) * m1; \
incr2 = -2 * dx + 2 * (dy) * m; \
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
} else { \
m = dx / (dy); \
m1 = m + 1; \
incr1 = 2 * dx - 2 * (dy) * m1; \
incr2 = 2 * dx - 2 * (dy) * m; \
d = -2 * m * (dy) + 2 * dx; \
} \
} \
}
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
if (m1 > 0) { \
if (d > 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} else {\
if (d >= 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} \
}
/*
* This structure contains all of the information needed
* to run the bresenham algorithm.
* The variables may be hardcoded into the declarations
* instead of using this structure to make use of
* register declarations.
*/
typedef struct {
int minor_axis; /* minor axis */
int d; /* decision variable */
int m, m1; /* slope and slope+1 */
int incr1, incr2; /* error increments */
} BRESINFO;
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
bres.m, bres.m1, bres.incr1, bres.incr2)
#define BRESINCRPGONSTRUCT(bres) \
BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
/*
* These are the data structures needed to scan
* convert regions. Two different scan conversion
* methods are available -- the even-odd method, and
* the winding number method.
* The even-odd rule states that a point is inside
* the polygon if a ray drawn from that point in any
* direction will pass through an odd number of
* path segments.
* By the winding number rule, a point is decided
* to be inside the polygon if a ray drawn from that
* point in any direction passes through a different
* number of clockwise and counter-clockwise path
* segments.
*
* These data structures are adapted somewhat from
* the algorithm in (Foley/Van Dam) for scan converting
* polygons.
* The basic algorithm is to start at the top (smallest y)
* of the polygon, stepping down to the bottom of
* the polygon by incrementing the y coordinate. We
* keep a list of edges which the current scanline crosses,
* sorted by x. This list is called the Active Edge Table (AET)
* As we change the y-coordinate, we update each entry in
* in the active edge table to reflect the edges new xcoord.
* This list must be sorted at each scanline in case
* two edges intersect.
* We also keep a data structure known as the Edge Table (ET),
* which keeps track of all the edges which the current
* scanline has not yet reached. The ET is basically a
* list of ScanLineList structures containing a list of
* edges which are entered at a given scanline. There is one
* ScanLineList per scanline at which an edge is entered.
* When we enter a new edge, we move it from the ET to the AET.
*
* From the AET, we can implement the even-odd rule as in
* (Foley/Van Dam).
* The winding number rule is a little trickier. We also
* keep the EdgeTableEntries in the AET linked by the
* nextWETE (winding EdgeTableEntry) link. This allows
* the edges to be linked just as before for updating
* purposes, but only uses the edges linked by the nextWETE
* link as edges representing spans of the polygon to
* drawn (as with the even-odd rule).
*/
/*
* for the winding number rule
*/
#define CLOCKWISE 1
#define COUNTERCLOCKWISE -1
typedef struct _EdgeTableEntry {
int ymax; /* ycoord at which we exit this edge. */
BRESINFO bres; /* Bresenham info to run the edge */
struct _EdgeTableEntry *next; /* next in the list */
struct _EdgeTableEntry *back; /* for insertion sort */
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
int ClockWise; /* flag for winding number rule */
} EdgeTableEntry;
typedef struct _ScanLineList{
int scanline; /* the scanline represented */
EdgeTableEntry *edgelist; /* header node */
struct _ScanLineList *next; /* next in the list */
} ScanLineList;
typedef struct {
int ymax; /* ymax for the polygon */
int ymin; /* ymin for the polygon */
ScanLineList scanlines; /* header node */
} EdgeTable;
/*
* Here is a struct to help with storage allocation
* so we can allocate a big chunk at a time, and then take
* pieces from this heap when we need to.
*/
#define SLLSPERBLOCK 25
typedef struct _ScanLineListBlock {
ScanLineList SLLs[SLLSPERBLOCK];
struct _ScanLineListBlock *next;
} ScanLineListBlock;
/*
*
* a few macros for the inner loops of the fill code where
* performance considerations don't allow a procedure call.
*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The winding number rule is in effect, so we must notify
* the caller when the edge has been removed so he
* can reorder the Winding Active Edge Table.
*/
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
fixWAET = 1; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}
/*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The even-odd rule is in effect.
*/
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}

616
gdk/gdkpolyreg-generic.c Normal file
View File

@ -0,0 +1,616 @@
/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */
#define LARGE_COORDINATE 1000000
#define SMALL_COORDINATE -LARGE_COORDINATE
#include <gdkregion.h>
#include "gdkregion-generic.h"
#include "gdkpoly-generic.h"
/*
* InsertEdgeInET
*
* Insert the given edge into the edge table.
* First we must find the correct bucket in the
* Edge table, then find the right slot in the
* bucket. Finally, we can insert it.
*
*/
static void
InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
EdgeTable *ET;
EdgeTableEntry *ETE;
int scanline;
ScanLineListBlock **SLLBlock;
int *iSLLBlock;
{
EdgeTableEntry *start, *prev;
ScanLineList *pSLL, *pPrevSLL;
ScanLineListBlock *tmpSLLBlock;
/*
* find the right bucket to put the edge into
*/
pPrevSLL = &ET->scanlines;
pSLL = pPrevSLL->next;
while (pSLL && (pSLL->scanline < scanline))
{
pPrevSLL = pSLL;
pSLL = pSLL->next;
}
/*
* reassign pSLL (pointer to ScanLineList) if necessary
*/
if ((!pSLL) || (pSLL->scanline > scanline))
{
if (*iSLLBlock > SLLSPERBLOCK-1)
{
tmpSLLBlock =
(ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock));
(*SLLBlock)->next = tmpSLLBlock;
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
*SLLBlock = tmpSLLBlock;
*iSLLBlock = 0;
}
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
pSLL->next = pPrevSLL->next;
pSLL->edgelist = (EdgeTableEntry *)NULL;
pPrevSLL->next = pSLL;
}
pSLL->scanline = scanline;
/*
* now insert the edge in the right bucket
*/
prev = (EdgeTableEntry *)NULL;
start = pSLL->edgelist;
while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
{
prev = start;
start = start->next;
}
ETE->next = start;
if (prev)
prev->next = ETE;
else
pSLL->edgelist = ETE;
}
/*
* CreateEdgeTable
*
* This routine creates the edge table for
* scan converting polygons.
* The Edge Table (ET) looks like:
*
* EdgeTable
* --------
* | ymax | ScanLineLists
* |scanline|-->------------>-------------->...
* -------- |scanline| |scanline|
* |edgelist| |edgelist|
* --------- ---------
* | |
* | |
* V V
* list of ETEs list of ETEs
*
* where ETE is an EdgeTableEntry data structure,
* and there is one ScanLineList per scanline at
* which an edge is initially entered.
*
*/
static void
CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
int count;
GdkPoint *pts;
EdgeTable *ET;
EdgeTableEntry *AET;
EdgeTableEntry *pETEs;
ScanLineListBlock *pSLLBlock;
{
GdkPoint *top, *bottom;
GdkPoint *PrevPt, *CurrPt;
int iSLLBlock = 0;
int dy;
if (count < 2) return;
/*
* initialize the Active Edge Table
*/
AET->next = (EdgeTableEntry *)NULL;
AET->back = (EdgeTableEntry *)NULL;
AET->nextWETE = (EdgeTableEntry *)NULL;
AET->bres.minor_axis = SMALL_COORDINATE;
/*
* initialize the Edge Table.
*/
ET->scanlines.next = (ScanLineList *)NULL;
ET->ymax = SMALL_COORDINATE;
ET->ymin = LARGE_COORDINATE;
pSLLBlock->next = (ScanLineListBlock *)NULL;
PrevPt = &pts[count-1];
/*
* for each vertex in the array of points.
* In this loop we are dealing with two vertices at
* a time -- these make up one edge of the polygon.
*/
while (count--)
{
CurrPt = pts++;
/*
* find out which point is above and which is below.
*/
if (PrevPt->y > CurrPt->y)
{
bottom = PrevPt, top = CurrPt;
pETEs->ClockWise = 0;
}
else
{
bottom = CurrPt, top = PrevPt;
pETEs->ClockWise = 1;
}
/*
* don't add horizontal edges to the Edge table.
*/
if (bottom->y != top->y)
{
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
/*
* initialize integer edge algorithm
*/
dy = bottom->y - top->y;
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
if (PrevPt->y > ET->ymax)
ET->ymax = PrevPt->y;
if (PrevPt->y < ET->ymin)
ET->ymin = PrevPt->y;
pETEs++;
}
PrevPt = CurrPt;
}
}
/*
* loadAET
*
* This routine moves EdgeTableEntries from the
* EdgeTable into the Active Edge Table,
* leaving them sorted by smaller x coordinate.
*
*/
static void
loadAET(AET, ETEs)
EdgeTableEntry *AET, *ETEs;
{
EdgeTableEntry *pPrevAET;
EdgeTableEntry *tmp;
pPrevAET = AET;
AET = AET->next;
while (ETEs)
{
while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
{
pPrevAET = AET;
AET = AET->next;
}
tmp = ETEs->next;
ETEs->next = AET;
if (AET)
AET->back = ETEs;
ETEs->back = pPrevAET;
pPrevAET->next = ETEs;
pPrevAET = ETEs;
ETEs = tmp;
}
}
/*
* computeWAET
*
* This routine links the AET by the
* nextWETE (winding EdgeTableEntry) link for
* use by the winding number rule. The final
* Active Edge Table (AET) might look something
* like:
*
* AET
* ---------- --------- ---------
* |ymax | |ymax | |ymax |
* | ... | |... | |... |
* |next |->|next |->|next |->...
* |nextWETE| |nextWETE| |nextWETE|
* --------- --------- ^--------
* | | |
* V-------------------> V---> ...
*
*/
static void
computeWAET(AET)
EdgeTableEntry *AET;
{
EdgeTableEntry *pWETE;
int inside = 1;
int isInside = 0;
AET->nextWETE = (EdgeTableEntry *)NULL;
pWETE = AET;
AET = AET->next;
while (AET)
{
if (AET->ClockWise)
isInside++;
else
isInside--;
if ((!inside && !isInside) ||
( inside && isInside))
{
pWETE->nextWETE = AET;
pWETE = AET;
inside = !inside;
}
AET = AET->next;
}
pWETE->nextWETE = (EdgeTableEntry *)NULL;
}
/*
* InsertionSort
*
* Just a simple insertion sort using
* pointers and back pointers to sort the Active
* Edge Table.
*
*/
static int
InsertionSort(AET)
EdgeTableEntry *AET;
{
EdgeTableEntry *pETEchase;
EdgeTableEntry *pETEinsert;
EdgeTableEntry *pETEchaseBackTMP;
int changed = 0;
AET = AET->next;
while (AET)
{
pETEinsert = AET;
pETEchase = AET;
while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
pETEchase = pETEchase->back;
AET = AET->next;
if (pETEchase != pETEinsert)
{
pETEchaseBackTMP = pETEchase->back;
pETEinsert->back->next = AET;
if (AET)
AET->back = pETEinsert->back;
pETEinsert->next = pETEchase;
pETEchase->back->next = pETEinsert;
pETEchase->back = pETEinsert;
pETEinsert->back = pETEchaseBackTMP;
changed = 1;
}
}
return(changed);
}
/*
* Clean up our act.
*/
static void
FreeStorage(pSLLBlock)
ScanLineListBlock *pSLLBlock;
{
ScanLineListBlock *tmpSLLBlock;
while (pSLLBlock)
{
tmpSLLBlock = pSLLBlock->next;
g_free (pSLLBlock);
pSLLBlock = tmpSLLBlock;
}
}
/*
* Create an array of rectangles from a list of points.
* If indeed these things (POINTS, RECTS) are the same,
* then this proc is still needed, because it allocates
* storage for the array, which was allocated on the
* stack by the calling procedure.
*
*/
static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg)
int numFullPtBlocks, iCurPtBlock;
POINTBLOCK *FirstPtBlock;
GdkRegion *reg;
{
GdkRegionBox *rects;
GdkPoint *pts;
POINTBLOCK *CurPtBlock;
int i;
GdkRegionBox *extents;
int numRects;
extents = &reg->extents;
numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
reg->rects = g_renew (GdkRegionBox, reg->rects, numRects);
reg->size = numRects;
CurPtBlock = FirstPtBlock;
rects = reg->rects - 1;
numRects = 0;
extents->x1 = G_MAXSHORT, extents->x2 = G_MINSHORT;
for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
/* the loop uses 2 points per iteration */
i = NUMPTSTOBUFFER >> 1;
if (!numFullPtBlocks)
i = iCurPtBlock >> 1;
for (pts = CurPtBlock->pts; i--; pts += 2) {
if (pts->x == pts[1].x)
continue;
if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
pts[1].x == rects->x2 &&
(numRects == 1 || rects[-1].y1 != rects->y1) &&
(i && pts[2].y > pts[1].y)) {
rects->y2 = pts[1].y + 1;
continue;
}
numRects++;
rects++;
rects->x1 = pts->x; rects->y1 = pts->y;
rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1;
if (rects->x1 < extents->x1)
extents->x1 = rects->x1;
if (rects->x2 > extents->x2)
extents->x2 = rects->x2;
}
CurPtBlock = CurPtBlock->next;
}
if (numRects) {
extents->y1 = reg->rects->y1;
extents->y2 = rects->y2;
} else {
extents->x1 = 0;
extents->y1 = 0;
extents->x2 = 0;
extents->y2 = 0;
}
reg->numRects = numRects;
return(TRUE);
}
/*
* polytoregion
*
* Scan converts a polygon by returning a run-length
* encoding of the resultant bitmap -- the run-length
* encoding is in the form of an array of rectangles.
*/
GdkRegion *
gdk_region_polygon(GdkPoint *Pts, gint Count, GdkFillRule rule)
{
GdkRegion *region;
EdgeTableEntry *pAET; /* Active Edge Table */
int y; /* current scanline */
int iPts = 0; /* number of pts in buffer */
EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
ScanLineList *pSLL; /* current scanLineList */
GdkPoint *pts; /* output buffer */
EdgeTableEntry *pPrevAET; /* ptr to previous AET */
EdgeTable ET; /* header node for ET */
EdgeTableEntry AET; /* header node for AET */
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
ScanLineListBlock SLLBlock; /* header for scanlinelist */
int fixWAET = FALSE;
POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
region = gdk_region_new ();
/* special case a rectangle */
pts = Pts;
if (((Count == 4) ||
((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) &&
(((pts[0].y == pts[1].y) &&
(pts[1].x == pts[2].x) &&
(pts[2].y == pts[3].y) &&
(pts[3].x == pts[0].x)) ||
((pts[0].x == pts[1].x) &&
(pts[1].y == pts[2].y) &&
(pts[2].x == pts[3].x) &&
(pts[3].y == pts[0].y)))) {
region->extents.x1 = MIN(pts[0].x, pts[2].x);
region->extents.y1 = MIN(pts[0].y, pts[2].y);
region->extents.x2 = MAX(pts[0].x, pts[2].x);
region->extents.y2 = MAX(pts[0].y, pts[2].y);
if ((region->extents.x1 != region->extents.x2) &&
(region->extents.y1 != region->extents.y2)) {
region->numRects = 1;
*(region->rects) = region->extents;
}
return(region);
}
pETEs = g_new (EdgeTableEntry, Count);
pts = FirstPtBlock.pts;
CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
pSLL = ET.scanlines.next;
curPtBlock = &FirstPtBlock;
if (rule == GDK_EVEN_ODD_RULE) {
/*
* for each scanline
*/
for (y = ET.ymin; y < ET.ymax; y++) {
/*
* Add a new edge to the active edge table when we
* get to the next edge.
*/
if (pSLL != NULL && y == pSLL->scanline) {
loadAET(&AET, pSLL->edgelist);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
/*
* for each active edge
*/
while (pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y;
pts++, iPts++;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++;
iPts = 0;
}
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
}
(void) InsertionSort(&AET);
}
}
else {
/*
* for each scanline
*/
for (y = ET.ymin; y < ET.ymax; y++) {
/*
* Add a new edge to the active edge table when we
* get to the next edge.
*/
if (pSLL != NULL && y == pSLL->scanline) {
loadAET(&AET, pSLL->edgelist);
computeWAET(&AET);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
pWETE = pAET;
/*
* for each active edge
*/
while (pAET) {
/*
* add to the buffer only those edges that
* are in the Winding active edge table.
*/
if (pWETE == pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y;
pts++, iPts++;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++; iPts = 0;
}
pWETE = pWETE->nextWETE;
}
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
}
/*
* recompute the winding active edge table if
* we just resorted or have exited an edge.
*/
if (InsertionSort(&AET) || fixWAET) {
computeWAET(&AET);
fixWAET = FALSE;
}
}
}
FreeStorage(SLLBlock.next);
(void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
tmpPtBlock = curPtBlock->next;
g_free (curPtBlock);
curPtBlock = tmpPtBlock;
}
g_free (pETEs);
return(region);
}

View File

@ -41,6 +41,9 @@
extern "C" {
#endif /* __cplusplus */
#define GDK_PARENT_RELATIVE_BG ((GdkPixmap *)1L)
#define GDK_NO_BG ((GdkPixmap *)2L)
#define GDK_DRAWABLE_TYPE(d) (((GdkDrawablePrivate *)d)->window_type)
#define GDK_IS_WINDOW(d) (GDK_DRAWABLE_TYPE(d) <= GDK_WINDOW_TEMP || \
GDK_DRAWABLE_TYPE(d) == GDK_WINDOW_FOREIGN)
@ -52,7 +55,6 @@ extern "C" {
#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))
typedef struct _GdkDrawablePrivate GdkDrawablePrivate;
/* typedef struct _GdkDrawablePrivate GdkPixmapPrivate; */
typedef struct _GdkWindowPrivate GdkWindowPrivate;
typedef struct _GdkImageClass GdkImageClass;
typedef struct _GdkImagePrivate GdkImagePrivate;
@ -69,14 +71,16 @@ struct _GdkDrawablePrivate
GdkDrawableClass *klass;
gpointer klass_data;
guint8 window_type;
guint ref_count;
guint16 width;
guint16 height;
gint width;
gint height;
GdkColormap *colormap;
guint8 window_type;
guint8 depth;
guint destroyed : 2;
};
@ -85,16 +89,25 @@ struct _GdkWindowPrivate
GdkDrawablePrivate drawable;
GdkWindow *parent;
gint16 x;
gint16 y;
gint x;
gint y;
guint8 resize_count;
guint mapped : 1;
guint guffaw_gravity : 1;
guint input_only : 1;
gint extension_events;
GList *filters;
GList *children;
GdkColor bg_color;
GdkPixmap *bg_pixmap;
GSList *paint_stack;
GdkRegion *update_area;
guint update_freeze_count;
};
struct _GdkImageClass
@ -130,6 +143,11 @@ struct _GdkGCPrivate
guint ref_count;
GdkGCClass *klass;
gpointer klass_data;
gint clip_x_origin;
gint clip_y_origin;
gint ts_x_origin;
gint ts_y_origin;
};
typedef enum {
@ -161,137 +179,11 @@ struct _GdkClientFilter {
gpointer data;
};
typedef enum
{
GDK_ARG_STRING,
GDK_ARG_INT,
GDK_ARG_BOOL,
GDK_ARG_NOBOOL,
GDK_ARG_CALLBACK
} GdkArgType;
typedef struct _GdkArgContext GdkArgContext;
typedef struct _GdkArgDesc GdkArgDesc;
typedef void (*GdkArgFunc) (const char *name, const char *arg, gpointer data);
struct _GdkArgContext
{
GPtrArray *tables;
gpointer cb_data;
};
struct _GdkArgDesc
{
const char *name;
GdkArgType type;
gpointer location;
GdkArgFunc callback;
};
typedef enum {
GDK_DEBUG_MISC = 1 << 0,
GDK_DEBUG_EVENTS = 1 << 1,
GDK_DEBUG_DND = 1 << 2,
GDK_DEBUG_COLOR_CONTEXT = 1 << 3,
GDK_DEBUG_XIM = 1 << 4
} GdkDebugFlag;
void gdk_event_button_generate (GdkEvent *event);
/* FIFO's for event queue, and for events put back using
* gdk_event_put().
*/
extern GList *gdk_queued_events;
extern GList *gdk_queued_tail;
extern GdkEventFunc gdk_event_func; /* Callback for events */
extern gpointer gdk_event_data;
extern GDestroyNotify gdk_event_notify;
GdkEvent* gdk_event_new (void);
void gdk_events_init (void);
void gdk_events_queue (void);
GdkEvent* gdk_event_unqueue (void);
GList* gdk_event_queue_find_first (void);
void gdk_event_queue_remove_link (GList *node);
void gdk_event_queue_append (GdkEvent *event);
void gdk_window_init (void);
void gdk_visual_init (void);
void gdk_dnd_init (void);
void gdk_image_init (void);
void gdk_image_exit (void);
void gdk_input_init (void);
void gdk_input_exit (void);
void gdk_windowing_exit (void);
void gdk_window_add_colormap_windows (GdkWindow *window);
void gdk_window_destroy_notify (GdkWindow *window);
/* If you pass x = y = -1, it queries the pointer
to find out where it currently is.
If you pass x = y = -2, it does anything necessary
to know that the drag is ending.
*/
void gdk_dnd_display_drag_cursor(gint x,
gint y,
gboolean drag_ok,
gboolean change_made);
extern gint gdk_debug_level;
extern gboolean gdk_show_events;
extern gint gdk_screen;
GDKVAR GdkWindow *gdk_parent_root;
GDKVAR gint gdk_error_code;
GDKVAR gint gdk_error_warnings;
extern GList *gdk_default_filters;
GdkWindow* _gdk_window_alloc (void);
/* Font/string functions implemented in module-specific code */
gint _gdk_font_strlen (GdkFont *font, const char *str);
void _gdk_font_destroy (GdkFont *font);
void _gdk_colormap_real_destroy (GdkColormap *colormap);
void _gdk_cursor_destroy (GdkCursor *cursor);
/* Initialization */
extern GdkArgDesc _gdk_windowing_args[];
gboolean _gdk_windowing_init_check (int argc, char **argv);
#ifdef USE_XIM
/* XIM support */
gint gdk_im_open (void);
void gdk_im_close (void);
void gdk_ic_cleanup (void);
#endif /* USE_XIM */
/* Debugging support */
#ifdef G_ENABLE_DEBUG
#define GDK_NOTE(type,action) G_STMT_START { \
if (gdk_debug_flags & GDK_DEBUG_##type) \
{ action; }; } G_STMT_END
#else /* !G_ENABLE_DEBUG */
#define GDK_NOTE(type,action)
#endif /* G_ENABLE_DEBUG */
GDKVAR guint gdk_debug_flags;
#ifdef __cplusplus
}
@ -299,3 +191,8 @@ GDKVAR guint gdk_debug_flags;
#endif /* __GDK_PRIVATE_H__ */

View File

@ -31,14 +31,18 @@ gdk_rectangle_union (GdkRectangle *src1,
GdkRectangle *src2,
GdkRectangle *dest)
{
gint dest_x, dest_y;
g_return_if_fail (src1 != NULL);
g_return_if_fail (src2 != NULL);
g_return_if_fail (dest != NULL);
dest->x = MIN (src1->x, src2->x);
dest->y = MIN (src1->y, src2->y);
dest->width = MAX (src1->x + src1->width, src2->x + src2->width) - dest->x;
dest->height = MAX (src1->y + src1->height, src2->y + src2->height) - dest->y;
dest_x = MIN (src1->x, src2->x);
dest_y = MIN (src1->y, src2->y);
dest->width = MAX (src1->x + src1->width, src2->x + src2->width) - dest_x;
dest->height = MAX (src1->y + src1->height, src2->y + src2->height) - dest_y;
dest->x = dest_x;
dest->y = dest_y;
}
gboolean
@ -63,13 +67,13 @@ gdk_rectangle_intersect (GdkRectangle *src1,
src1 = src2;
src2 = temp;
}
dest->x = src2->x;
src1_x2 = src1->x + src1->width;
src2_x2 = src2->x + src2->width;
if (src2->x < src1_x2)
{
dest->x = src2->x;
if (src1_x2 < src2_x2)
dest->width = src1_x2 - dest->x;
else
@ -81,8 +85,6 @@ gdk_rectangle_intersect (GdkRectangle *src1,
src1 = src2;
src2 = temp;
}
dest->y = src2->y;
src1_y2 = src1->y + src1->height;
src2_y2 = src2->y + src2->height;
@ -90,6 +92,8 @@ gdk_rectangle_intersect (GdkRectangle *src1,
{
return_val = TRUE;
dest->y = src2->y;
if (src1_y2 < src2_y2)
dest->height = src1_y2 - dest->y;
else
@ -102,5 +106,11 @@ gdk_rectangle_intersect (GdkRectangle *src1,
}
}
if (!return_val)
{
dest->width = 0;
dest->height = 0;
}
return return_val;
}

1505
gdk/gdkregion-generic.c Normal file

File diff suppressed because it is too large Load Diff

167
gdk/gdkregion-generic.h Normal file
View File

@ -0,0 +1,167 @@
/* $TOG: region.h /main/9 1998/02/06 17:50:30 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
#ifndef __GDK_REGION_GENERIC_H__
#define __GDK_REGION_GENERIC_H__
typedef struct _GdkRegionBox GdkRegionBox;
struct _GdkRegionBox
{
int x1, x2, y1, y2;
};
/*
* clip region
*/
struct _GdkRegion
{
long size;
long numRects;
GdkRegionBox *rects;
GdkRegionBox extents;
};
/* 1 if two BOXs overlap.
* 0 if two BOXs do not overlap.
* Remember, x2 and y2 are not in the region
*/
#define EXTENTCHECK(r1, r2) \
((r1)->x2 > (r2)->x1 && \
(r1)->x1 < (r2)->x2 && \
(r1)->y2 > (r2)->y1 && \
(r1)->y1 < (r2)->y2)
/*
* update region extents
*/
#define EXTENTS(r,idRect){\
if((r)->x1 < (idRect)->extents.x1)\
(idRect)->extents.x1 = (r)->x1;\
if((r)->y1 < (idRect)->extents.y1)\
(idRect)->extents.y1 = (r)->y1;\
if((r)->x2 > (idRect)->extents.x2)\
(idRect)->extents.x2 = (r)->x2;\
if((r)->y2 > (idRect)->extents.y2)\
(idRect)->extents.y2 = (r)->y2;\
}
/*
* Check to see if there is enough memory in the present region.
*/
#define MEMCHECK(reg, rect, firstrect){ \
if ((reg)->numRects >= ((reg)->size - 1)) { \
(firstrect) = g_renew (GdkRegionBox, (firstrect), 2 * (reg)->size); \
(reg)->size *= 2; \
(rect) = &(firstrect)[(reg)->numRects]; \
} \
}
/* this routine checks to see if the previous rectangle is the same
* or subsumes the new rectangle to add.
*/
#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\
(!(((Reg)->numRects > 0)&&\
((R-1)->y1 == (Ry1)) &&\
((R-1)->y2 == (Ry2)) &&\
((R-1)->x1 <= (Rx1)) &&\
((R-1)->x2 >= (Rx2))))
/* add a rectangle to the given Region */
#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\
if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
(r)->x1 = (rx1);\
(r)->y1 = (ry1);\
(r)->x2 = (rx2);\
(r)->y2 = (ry2);\
EXTENTS((r), (reg));\
(reg)->numRects++;\
(r)++;\
}\
}
/* add a rectangle to the given Region */
#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\
if ((rx1 < rx2) && (ry1 < ry2) &&\
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
(r)->x1 = (rx1);\
(r)->y1 = (ry1);\
(r)->x2 = (rx2);\
(r)->y2 = (ry2);\
(reg)->numRects++;\
(r)++;\
}\
}
#define EMPTY_REGION(pReg) pReg->numRects = 0
#define REGION_NOT_EMPTY(pReg) pReg->numRects
#define INBOX(r, x, y) \
( ( ((r).x2 > x)) && \
( ((r).x1 <= x)) && \
( ((r).y2 > y)) && \
( ((r).y1 <= y)) )
/*
* number of points to buffer before sending them off
* to scanlines() : Must be an even number
*/
#define NUMPTSTOBUFFER 200
/*
* used to allocate buffers for points and link
* the buffers together
*/
typedef struct _POINTBLOCK {
GdkPoint pts[NUMPTSTOBUFFER];
struct _POINTBLOCK *next;
} POINTBLOCK;
#endif /* __GDK_REGION_GENERIC_H__ */

View File

@ -29,48 +29,42 @@ typedef enum
GDK_OVERLAP_RECTANGLE_PART
} GdkOverlapType;
struct _GdkRegion
{
gpointer user_data;
};
GdkRegion *gdk_region_new (void);
GdkRegion *gdk_region_polygon (GdkPoint *points,
gint npoints,
GdkFillRule fill_rule);
GdkRegion *gdk_region_copy (GdkRegion *region);
GdkRegion *gdk_region_rectangle (GdkRectangle *rectangle);
void gdk_region_destroy (GdkRegion *region);
GdkRegion* gdk_region_new (void);
void gdk_region_destroy (GdkRegion *region);
void gdk_region_get_clipbox (GdkRegion *region,
GdkRectangle *rectangle);
void gdk_region_get_clipbox(GdkRegion *region,
GdkRectangle *rectangle);
gboolean gdk_region_empty (GdkRegion *region);
gboolean gdk_region_equal (GdkRegion *region1,
GdkRegion *region2);
gboolean gdk_region_point_in (GdkRegion *region,
int x,
int y);
GdkOverlapType gdk_region_rect_in (GdkRegion *region,
GdkRectangle *rect);
GdkRegion* gdk_region_polygon (GdkPoint *points,
gint npoints,
GdkFillRule fill_rule);
void gdk_region_offset (GdkRegion *region,
gint dx,
gint dy);
void gdk_region_shrink (GdkRegion *region,
gint dx,
gint dy);
GdkRegion* gdk_region_union_with_rect (GdkRegion *region,
GdkRectangle *rect);
GdkRegion* gdk_regions_intersect (GdkRegion *source1,
GdkRegion *source2);
GdkRegion* gdk_regions_union (GdkRegion *source1,
GdkRegion *source2);
GdkRegion* gdk_regions_subtract (GdkRegion *source1,
GdkRegion *source2);
GdkRegion* gdk_regions_xor (GdkRegion *source1,
GdkRegion *source2);
gboolean gdk_region_empty (GdkRegion *region);
gboolean gdk_region_equal (GdkRegion *region1,
GdkRegion *region2);
gboolean gdk_region_point_in (GdkRegion *region,
int x,
int y);
GdkOverlapType gdk_region_rect_in (GdkRegion *region,
GdkRectangle *rect);
void gdk_region_offset (GdkRegion *region,
gint dx,
gint dy);
void gdk_region_shrink (GdkRegion *region,
gint dx,
gint dy);
void gdk_region_union_with_rect (GdkRegion *region,
GdkRectangle *rect);
void gdk_region_intersect (GdkRegion *source1,
GdkRegion *source2);
void gdk_region_union (GdkRegion *source1,
GdkRegion *source2);
void gdk_region_subtract (GdkRegion *source1,
GdkRegion *source2);
void gdk_region_xor (GdkRegion *source1,
GdkRegion *source2);
#ifdef __cplusplus
}

View File

@ -143,24 +143,24 @@ typedef void (*GdkDestroyNotify) (gpointer data);
struct _GdkPoint
{
gint16 x;
gint16 y;
gint x;
gint y;
};
struct _GdkRectangle
{
gint16 x;
gint16 y;
guint16 width;
guint16 height;
gint x;
gint y;
gint width;
gint height;
};
struct _GdkSegment
{
gint16 x1;
gint16 y1;
gint16 x2;
gint16 y2;
gint x1;
gint y1;
gint x2;
gint y2;
};

File diff suppressed because it is too large Load Diff

View File

@ -91,9 +91,9 @@ struct _GdkWindowAttr
{
gchar *title;
gint event_mask;
gint16 x, y;
gint16 width;
gint16 height;
gint x, y;
gint width;
gint height;
GdkWindowClass wclass;
GdkVisual *visual;
GdkColormap *colormap;
@ -230,6 +230,11 @@ void gdk_window_set_geometry_hints (GdkWindow *window,
GdkWindowHints flags);
void gdk_set_sm_client_id (const gchar *sm_client_id);
void gdk_window_begin_paint_rect (GdkWindow *window,
GdkRectangle *rectangle);
void gdk_window_begin_paint_region (GdkWindow *window,
GdkRegion *region);
void gdk_window_end_paint (GdkWindow *window);
void gdk_window_set_title (GdkWindow *window,
const gchar *title);
@ -268,9 +273,10 @@ GdkWindow* gdk_window_get_pointer (GdkWindow *window,
gint *x,
gint *y,
GdkModifierType *mask);
GdkWindow* gdk_window_get_parent (GdkWindow *window);
GdkWindow* gdk_window_get_toplevel (GdkWindow *window);
GList* gdk_window_get_children (GdkWindow *window);
GdkWindow * gdk_window_get_parent (GdkWindow *window);
GdkWindow * gdk_window_get_toplevel (GdkWindow *window);
GList * gdk_window_get_children (GdkWindow *window);
GdkEventMask gdk_window_get_events (GdkWindow *window);
void gdk_window_set_events (GdkWindow *window,
GdkEventMask event_mask);
@ -291,6 +297,24 @@ GList * gdk_window_get_toplevels (void);
void gdk_window_register_dnd (GdkWindow *window);
/* Interface for dirty-region queueing */
void gdk_window_invalidate_rect (GdkWindow *window,
GdkRectangle *rect,
gboolean invalidate_children);
void gdk_window_invalidate_region (GdkWindow *window,
GdkRegion *region,
gboolean invalidate_children);
GdkRegion *gdk_window_get_update_area (GdkWindow *window);
void gdk_window_freeze_updates (GdkWindow *window);
void gdk_window_thaw_updates (GdkWindow *window);
void gdk_window_process_all_updates (void);
void gdk_window_process_updates (GdkWindow *window,
gboolean update_children);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -35,40 +35,49 @@ xinput_sources = \
endif
endif
libgdk_x11_la_SOURCES = \
MwmUtil.h \
gdkcc-x11.c \
gdkcolor-x11.c \
gdkcursor-x11.c \
gdkdnd-x11.c \
gdkdrawable-x11.c \
gdkevents-x11.c \
gdkfont-x11.c \
gdkgc-x11.c \
gdkglobals-x11.c \
gdkim-x11.c \
gdkimage-x11.c \
gdkinput.c \
gdkmain-x11.c \
gdkpixmap-x11.c \
gdkproperty-x11.c \
gdkregion-x11.c \
gdkselection-x11.c \
gdkvisual-x11.c \
gdkwindow-x11.c \
gdkxid.c \
gxid_lib.c \
gxid_lib.h \
gxid_proto.h \
gdkx.h \
gdkprivate-x11.h \
gdkinputprivate.h \
libgdk_x11_la_SOURCES = \
MwmUtil.h \
gdkcc-x11.c \
gdkcolor-x11.c \
gdkcursor-x11.c \
gdkdnd-x11.c \
gdkdrawable-x11.c \
gdkevents-x11.c \
gdkfont-x11.c \
gdkgc-x11.c \
gdkgeometry-x11.c \
gdkglobals-x11.c \
gdkim-x11.c \
gdkimage-x11.c \
gdkinput.c \
gdkmain-x11.c \
gdkpixmap-x11.c \
gdkproperty-x11.c \
gdkpolyreg-generic.c \
gdkregion-generic.c \
gdkselection-x11.c \
gdkvisual-x11.c \
gdkwindow-x11.c \
gdkxid.c \
gxid_lib.c \
gxid_lib.h \
gxid_proto.h \
gdkx.h \
gdkprivate-x11.h \
gdkinputprivate.h \
$(xinput_sources)
INCLUDE_HEADERS = \
gdkx.h
EXTRA_PROGRAMS = gxid
bin_PROGRAMS = @xinput_progs@
gxid_SOURCES = gxid.c
gxid_LDADD = $(LDADDS)
install-data-local:
../../$(MKINSTALLDIRS) $(includedir)/gdk
$(INSTALL_DATA) $(srcdir)/gdkx.h $(includedir)/gdk
../../$(MKINSTALLDIRS) $(includedir)/gdk/x11
$(INSTALL_DATA) $(srcdir)/gdkprivate-x11.h $(includedir)/gdk/x11

View File

@ -68,6 +68,7 @@
#include "gdkcc.h"
#include "gdkcolor.h"
#include "gdkx.h"
#include "gdkinternals.h"
#define MAX_IMAGE_COLORS 256

View File

@ -27,7 +27,7 @@
#include <time.h>
#include "gdkcolor.h"
#include "gdkx.h"
#include "gdkprivate-x11.h"
static gint gdk_colormap_match_color (GdkColormap *cmap,
GdkColor *color,

View File

@ -31,8 +31,8 @@
#include "gdk.h" /* For gdk_flush() */
#include "gdkdnd.h"
#include "gdkproperty.h"
#include "gdkprivate.h"
#include "gdkx.h"
#include "gdkinternals.h"
#include "gdkprivate-x11.h"
typedef struct _GdkDragContextPrivate GdkDragContextPrivate;

View File

@ -1,4 +1,30 @@
#include "gdkx.h"
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "gdkprivate-x11.h"
static void gdk_x11_drawable_destroy (GdkDrawable *drawable);
@ -159,10 +185,10 @@ gdk_x11_draw_rectangle (GdkDrawable *drawable,
{
if (filled)
XFillRectangle (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, width, height);
GDK_GC_GET_XGC (gc), x, y, width, height);
else
XDrawRectangle (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, width, height);
GDK_GC_GET_XGC (gc), x, y, width, height);
}
static void
@ -178,10 +204,10 @@ gdk_x11_draw_arc (GdkDrawable *drawable,
{
if (filled)
XFillArc (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, width, height, angle1, angle2);
GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
else
XDrawArc (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, width, height, angle1, angle2);
GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
}
static void
@ -191,36 +217,37 @@ gdk_x11_draw_polygon (GdkDrawable *drawable,
GdkPoint *points,
gint npoints)
{
if (filled)
XPoint *tmp_points;
gint tmp_npoints, i;
if (!filled &&
(points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
{
XFillPolygon (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), (XPoint*) points, npoints, Complex, CoordModeOrigin);
tmp_npoints = npoints + 1;
tmp_points = g_new (XPoint, tmp_npoints);
tmp_points[npoints].x = points[0].x;
tmp_points[npoints].y = points[0].y;
}
else
{
GdkPoint *local_points = points;
gint local_npoints = npoints;
gint local_alloc = 0;
if ((points[0].x != points[npoints-1].x) ||
(points[0].y != points[npoints-1].y))
{
local_alloc = 1;
++local_npoints;
local_points = (GdkPoint*) g_malloc (local_npoints * sizeof(GdkPoint));
memcpy (local_points, points, npoints * sizeof(GdkPoint));
local_points[npoints].x = points[0].x;
local_points[npoints].y = points[0].y;
}
XDrawLines (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
(XPoint*) local_points, local_npoints,
CoordModeOrigin);
if (local_alloc)
g_free (local_points);
tmp_npoints = npoints;
tmp_points = g_new (XPoint, tmp_npoints);
}
for (i=0; i<npoints; i++)
{
tmp_points[i].x = points[i].x;
tmp_points[i].y = points[i].y;
}
if (filled)
XFillPolygon (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
else
XDrawLines (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
g_free (tmp_points);
}
/* gdk_x11_draw_text
@ -241,23 +268,23 @@ gdk_x11_draw_text (GdkDrawable *drawable,
if (font->type == GDK_FONT_FONT)
{
XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_XGC (gc), xfont->fid);
XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_GET_XGC (gc), xfont->fid);
if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
{
XDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, text, text_length);
GDK_GC_GET_XGC (gc), x, y, text, text_length);
}
else
{
XDrawString16 (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
}
}
else if (font->type == GDK_FONT_FONTSET)
{
XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
XmbDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
fontset, GDK_GC_XGC (gc), x, y, text, text_length);
fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
}
else
g_error("undefined font type\n");
@ -277,11 +304,11 @@ gdk_x11_draw_text_wc (GdkDrawable *drawable,
XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
gchar *text_8bit;
gint i;
XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_XGC (gc), xfont->fid);
XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_GET_XGC (gc), xfont->fid);
text_8bit = g_new (gchar, text_length);
for (i=0; i<text_length; i++) text_8bit[i] = text[i];
XDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), x, y, text_8bit, text_length);
GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
g_free (text_8bit);
}
else if (font->type == GDK_FONT_FONTSET)
@ -290,7 +317,7 @@ gdk_x11_draw_text_wc (GdkDrawable *drawable,
{
XwcDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
(XFontSet) GDK_FONT_XFONT (font),
GDK_GC_XGC (gc), x, y, (wchar_t *)text, text_length);
GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
}
else
{
@ -300,7 +327,7 @@ gdk_x11_draw_text_wc (GdkDrawable *drawable,
for (i=0; i<text_length; i++) text_wchar[i] = text[i];
XwcDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
(XFontSet) GDK_FONT_XFONT (font),
GDK_GC_XGC (gc), x, y, text_wchar, text_length);
GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
g_free (text_wchar);
}
}
@ -319,27 +346,31 @@ gdk_x11_draw_drawable (GdkDrawable *drawable,
gint width,
gint height)
{
/* FIXME: this doesn't work because bitmaps don't have visuals */
if (gdk_drawable_get_visual (src)->depth == 1)
int src_depth = gdk_drawable_get_depth (src);
int dest_depth = gdk_drawable_get_depth (drawable);
if (src_depth == 1)
{
XCopyArea (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (src),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
GDK_GC_GET_XGC (gc),
xsrc, ysrc,
width, height,
xdest, ydest);
}
else if (dest_depth != 0 && src_depth == dest_depth)
{
XCopyArea (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (src),
GDK_DRAWABLE_XID (drawable),
GDK_GC_GET_XGC (gc),
xsrc, ysrc,
width, height,
xdest, ydest);
}
else
{
XCopyArea (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (src),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
xsrc, ysrc,
width, height,
xdest, ydest);
}
g_warning ("Attempt to copy between drawables of mismatched depths!\n");
}
static void
@ -355,17 +386,28 @@ gdk_x11_draw_points (GdkDrawable *drawable,
{
XDrawPoint (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
GDK_GC_GET_XGC (gc),
points[0].x, points[0].y);
}
else
{
gint i;
XPoint *tmp_points = g_new (XPoint, npoints);
for (i=0; i<npoints; i++)
{
tmp_points[i].x = points[i].x;
tmp_points[i].y = points[i].y;
}
XDrawPoints (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
(XPoint *) points,
GDK_GC_GET_XGC (gc),
tmp_points,
npoints,
CoordModeOrigin);
g_free (tmp_points);
}
}
@ -381,16 +423,28 @@ gdk_x11_draw_segments (GdkDrawable *drawable,
if (nsegs == 1)
{
XDrawLine (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), segs[0].x1, segs[0].y1,
GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
segs[0].x2, segs[0].y2);
}
else
{
gint i;
XSegment *tmp_segs = g_new (XSegment, nsegs);
for (i=0; i<nsegs; i++)
{
tmp_segs[i].x1 = segs[i].x1;
tmp_segs[i].x2 = segs[i].x2;
tmp_segs[i].y1 = segs[i].y1;
tmp_segs[i].y2 = segs[i].y2;
}
XDrawSegments (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
(XSegment *) segs,
nsegs);
GDK_GC_GET_XGC (gc),
tmp_segs, nsegs);
g_free (tmp_segs);
}
}
@ -400,10 +454,20 @@ gdk_x11_draw_lines (GdkDrawable *drawable,
GdkPoint *points,
gint npoints)
{
gint i;
XPoint *tmp_points = g_new (XPoint, npoints);
for (i=0; i<npoints; i++)
{
tmp_points[i].x = points[i].x;
tmp_points[i].y = points[i].y;
}
XDrawLines (GDK_DRAWABLE_XDISPLAY (drawable),
GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc),
(XPoint *) points,
npoints,
GDK_GC_GET_XGC (gc),
tmp_points, npoints,
CoordModeOrigin);
g_free (tmp_points);
}

View File

@ -25,7 +25,8 @@
*/
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkprivate-x11.h"
#include "gdkinternals.h"
#include "gdkx.h"
#include "gdkkeysyms.h"
@ -215,214 +216,6 @@ gdk_event_get_graphics_expose (GdkWindow *window)
return NULL;
}
/************************
* Exposure compression *
************************/
/*
* The following implements simple exposure compression. It is
* modelled after the way Xt does exposure compression - in
* particular compress_expose = XtExposeCompressMultiple.
* It compress consecutive sequences of exposure events,
* but not sequences that cross other events. (This is because
* if it crosses a ConfigureNotify, we could screw up and
* mistakenly compress the exposures generated for the new
* size - could we just check for ConfigureNotify?)
*
* Xt compresses to a region / bounding rectangle, we compress
* to two rectangles, and try find the two rectangles of minimal
* area for this - this is supposed to handle the typical
* L-shaped regions generated by OpaqueMove.
*/
/* Given three rectangles, find the two rectangles that cover
* them with the smallest area.
*/
static void
gdk_add_rect_to_rects (GdkRectangle *rect1,
GdkRectangle *rect2,
GdkRectangle *new_rect)
{
GdkRectangle t1, t2, t3;
gint size1, size2, size3;
gdk_rectangle_union (rect1, rect2, &t1);
gdk_rectangle_union (rect1, new_rect, &t2);
gdk_rectangle_union (rect2, new_rect, &t3);
size1 = t1.width * t1.height + new_rect->width * new_rect->height;
size2 = t2.width * t2.height + rect2->width * rect2->height;
size3 = t1.width * t1.height + rect1->width * rect1->height;
if (size1 < size2)
{
if (size1 < size3)
{
*rect1 = t1;
*rect2 = *new_rect;
}
else
*rect2 = t3;
}
else
{
if (size2 < size3)
*rect1 = t2;
else
*rect2 = t3;
}
}
typedef struct _GdkExposeInfo GdkExposeInfo;
struct _GdkExposeInfo
{
Window window;
gboolean seen_nonmatching;
};
static Bool
expose_predicate (Display *display,
XEvent *xevent,
XPointer arg)
{
GdkExposeInfo *info = (GdkExposeInfo*) arg;
/* Compressing across GravityNotify events is safe, because
* we completely ignore them, so they can't change what
* we are going to draw. Compressing across GravityNotify
* events is necessay because during window-unshading animation
* we'll get a whole bunch of them interspersed with
* expose events.
*/
if (xevent->xany.type != Expose &&
xevent->xany.type != GravityNotify)
{
info->seen_nonmatching = TRUE;
}
if (info->seen_nonmatching ||
xevent->xany.type != Expose ||
xevent->xany.window != info->window)
return FALSE;
else
return TRUE;
}
void
gdk_compress_exposures (XEvent *xevent,
GdkWindow *window)
{
gint nrects = 1;
gint count = 0;
GdkRectangle rect1;
GdkRectangle rect2;
GdkRectangle tmp_rect;
XEvent tmp_event;
GdkFilterReturn result;
GdkExposeInfo info;
GdkEvent event;
info.window = xevent->xany.window;
info.seen_nonmatching = FALSE;
rect1.x = xevent->xexpose.x;
rect1.y = xevent->xexpose.y;
rect1.width = xevent->xexpose.width;
rect1.height = xevent->xexpose.height;
event.any.type = GDK_EXPOSE;
event.any.window = None;
event.any.send_event = FALSE;
while (1)
{
if (count == 0)
{
if (!XCheckIfEvent (gdk_display,
&tmp_event,
expose_predicate,
(XPointer)&info))
break;
}
else
XIfEvent (gdk_display,
&tmp_event,
expose_predicate,
(XPointer)&info);
event.any.window = window;
/* We apply filters here, and if it was filtered, completely
* ignore the return
*/
result = gdk_event_apply_filters (xevent, &event,
window ?
((GdkWindowPrivate *)window)->filters
: gdk_default_filters);
if (result != GDK_FILTER_CONTINUE)
{
if (result == GDK_FILTER_TRANSLATE)
gdk_event_put (&event);
continue;
}
if (nrects == 1)
{
rect2.x = tmp_event.xexpose.x;
rect2.y = tmp_event.xexpose.y;
rect2.width = tmp_event.xexpose.width;
rect2.height = tmp_event.xexpose.height;
nrects++;
}
else
{
tmp_rect.x = tmp_event.xexpose.x;
tmp_rect.y = tmp_event.xexpose.y;
tmp_rect.width = tmp_event.xexpose.width;
tmp_rect.height = tmp_event.xexpose.height;
gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);
}
count = tmp_event.xexpose.count;
}
if (nrects == 2)
{
gdk_rectangle_union (&rect1, &rect2, &tmp_rect);
if ((tmp_rect.width * tmp_rect.height) <
2 * (rect1.height * rect1.width +
rect2.height * rect2.width))
{
rect1 = tmp_rect;
nrects = 1;
}
}
if (nrects == 2)
{
event.expose.type = GDK_EXPOSE;
event.expose.window = window;
event.expose.area.x = rect2.x;
event.expose.area.y = rect2.y;
event.expose.area.width = rect2.width;
event.expose.area.height = rect2.height;
event.expose.count = 0;
gdk_event_put (&event);
}
xevent->xexpose.count = nrects - 1;
xevent->xexpose.x = rect1.x;
xevent->xexpose.y = rect1.y;
xevent->xexpose.width = rect1.width;
xevent->xexpose.height = rect1.height;
}
static gint
gdk_event_apply_filters (XEvent *xevent,
GdkEvent *event,
@ -477,6 +270,7 @@ gdk_event_translate (GdkEvent *event,
char buf[16];
#endif
gint return_val;
gint xoffset, yoffset;
return_val = FALSE;
@ -571,6 +365,16 @@ gdk_event_translate (GdkEvent *event,
return_val = TRUE;
if (window)
{
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
}
else
{
xoffset = 0;
yoffset = 0;
}
switch (xevent->type)
{
case KeyPress:
@ -709,8 +513,8 @@ gdk_event_translate (GdkEvent *event,
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
event->scroll.window = window;
event->scroll.time = xevent->xbutton.x;
event->scroll.x = xevent->xbutton.x;
event->scroll.y = xevent->xbutton.y;
event->scroll.x = xevent->xbutton.x + xoffset;
event->scroll.y = xevent->xbutton.y + yoffset;
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.pressure = 0.5;
@ -725,8 +529,8 @@ gdk_event_translate (GdkEvent *event,
event->button.type = GDK_BUTTON_PRESS;
event->button.window = window;
event->button.time = xevent->xbutton.time;
event->button.x = xevent->xbutton.x;
event->button.y = xevent->xbutton.y;
event->button.x = xevent->xbutton.x + xoffset;
event->button.y = xevent->xbutton.y + yoffset;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.pressure = 0.5;
@ -769,8 +573,8 @@ gdk_event_translate (GdkEvent *event,
event->button.type = GDK_BUTTON_RELEASE;
event->button.window = window;
event->button.time = xevent->xbutton.time;
event->button.x = xevent->xbutton.x;
event->button.y = xevent->xbutton.y;
event->button.x = xevent->xbutton.x + xoffset;
event->button.y = xevent->xbutton.y + yoffset;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.pressure = 0.5;
@ -803,8 +607,8 @@ gdk_event_translate (GdkEvent *event,
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xevent->xmotion.time;
event->motion.x = xevent->xmotion.x;
event->motion.y = xevent->xmotion.y;
event->motion.x = xevent->xmotion.x + xoffset;
event->motion.y = xevent->xmotion.y + yoffset;
event->motion.x_root = (gfloat)xevent->xmotion.x_root;
event->motion.y_root = (gfloat)xevent->xmotion.y_root;
event->motion.pressure = 0.5;
@ -845,8 +649,8 @@ gdk_event_translate (GdkEvent *event,
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = xevent->xcrossing.x;
event->crossing.y = xevent->xcrossing.y;
event->crossing.x = xevent->xcrossing.x + xoffset;
event->crossing.y = xevent->xcrossing.y + yoffset;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
@ -914,8 +718,8 @@ gdk_event_translate (GdkEvent *event,
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
event->crossing.x = xevent->xcrossing.x;
event->crossing.y = xevent->xcrossing.y;
event->crossing.x = xevent->xcrossing.x + xoffset;
event->crossing.y = xevent->xcrossing.y + yoffset;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
@ -1016,33 +820,41 @@ gdk_event_translate (GdkEvent *event,
xevent->xexpose.x, xevent->xexpose.y,
xevent->xexpose.width, xevent->xexpose.height,
event->any.send_event ? " (send)" : ""));
gdk_compress_exposures (xevent, window);
event->expose.type = GDK_EXPOSE;
event->expose.window = window;
event->expose.area.x = xevent->xexpose.x;
event->expose.area.y = xevent->xexpose.y;
event->expose.area.width = xevent->xexpose.width;
event->expose.area.height = xevent->xexpose.height;
event->expose.count = xevent->xexpose.count;
{
GdkRectangle expose_rect;
expose_rect.x = xevent->xexpose.x + xoffset;
expose_rect.y = xevent->xexpose.y + yoffset;
expose_rect.width = xevent->xexpose.width;
expose_rect.height = xevent->xexpose.height;
_gdk_window_process_expose (window, xevent->xexpose.serial, &expose_rect);
return_val = FALSE;
}
break;
case GraphicsExpose:
/* Print debugging info.
*/
GDK_NOTE (EVENTS,
g_message ("graphics expose:\tdrawable: %ld",
xevent->xgraphicsexpose.drawable));
event->expose.type = GDK_EXPOSE;
event->expose.window = window;
event->expose.area.x = xevent->xgraphicsexpose.x;
event->expose.area.y = xevent->xgraphicsexpose.y;
event->expose.area.width = xevent->xgraphicsexpose.width;
event->expose.area.height = xevent->xgraphicsexpose.height;
event->expose.count = xevent->xexpose.count;
{
GdkRectangle expose_rect;
GDK_NOTE (EVENTS,
g_message ("graphics expose:\tdrawable: %ld",
xevent->xgraphicsexpose.drawable));
expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
expose_rect.width = xevent->xgraphicsexpose.width;
expose_rect.height = xevent->xgraphicsexpose.height;
_gdk_window_process_expose (window, xevent->xgraphicsexpose.serial, &expose_rect);
return_val = FALSE;
}
break;
case NoExpose:

View File

@ -27,7 +27,7 @@
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include "gdkfont.h"
#include "gdkx.h"
#include "gdkprivate-x11.h"
static GHashTable *font_name_hash = NULL;
static GHashTable *fontset_name_hash = NULL;

View File

@ -1,5 +1,11 @@
#include "gdkgc.h"
#include "gdkx.h"
#include "gdkregion-generic.h"
typedef enum {
GDK_GC_DIRTY_CLIP = 1 << 0,
GDK_GC_DIRTY_TS = 1 << 1
} GdkGCDirtyValues;
static void gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
GdkGCValuesMask mask,
@ -31,6 +37,7 @@ _gdk_x11_gc_new (GdkDrawable *drawable,
{
GdkGC *gc;
GdkGCPrivate *private;
GdkGCXData *data;
XGCValues xvalues;
unsigned long xvalues_mask;
@ -39,10 +46,25 @@ _gdk_x11_gc_new (GdkDrawable *drawable,
private = (GdkGCPrivate *)gc;
private->klass = &gdk_x11_gc_class;
private->klass_data = g_new (GdkGCXData, 1);
private->klass_data = data = g_new (GdkGCXData, 1);
data->dirty_mask = 0;
data->clip_region = NULL;
GDK_GC_XDATA (gc)->xdisplay = GDK_DRAWABLE_XDISPLAY (drawable);
if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
{
values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
data->dirty_mask |= GDK_GC_DIRTY_CLIP;
}
if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
{
values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
data->dirty_mask |= GDK_GC_DIRTY_TS;
}
xvalues.function = GXcopy;
xvalues.fill_style = FillSolid;
xvalues.arc_mode = ArcPieSlice;
@ -52,7 +74,7 @@ _gdk_x11_gc_new (GdkDrawable *drawable,
gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
GDK_GC_XDATA (gc)->xgc = XCreateGC (GDK_GC_XDISPLAY (gc),
data->xgc = XCreateGC (GDK_GC_XDISPLAY (gc),
GDK_DRAWABLE_XID (drawable),
xvalues_mask, &xvalues);
@ -62,10 +84,55 @@ _gdk_x11_gc_new (GdkDrawable *drawable,
static void
gdk_x11_gc_destroy (GdkGC *gc)
{
if (GDK_GC_XDATA (gc)->clip_region)
gdk_region_destroy (GDK_GC_XDATA (gc)->clip_region);
XFreeGC (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc));
g_free (GDK_GC_XDATA (gc));
}
GC
_gdk_x11_gc_flush (GdkGC *gc)
{
GdkGCPrivate *private = (GdkGCPrivate *)gc;
GdkGCXData *data = GDK_GC_XDATA (gc);
if (data->dirty_mask & GDK_GC_DIRTY_CLIP)
{
if (!data->clip_region)
XSetClipOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
private->clip_x_origin, private->clip_y_origin);
else
{
XRectangle *rectangles = g_new (XRectangle, data->clip_region->numRects);
GdkRegionBox *boxes = data->clip_region->rects;
int i;
for (i=0; i<data->clip_region->numRects; i++)
{
rectangles[i].x = CLAMP (boxes[i].x1 + private->clip_x_origin, G_MINSHORT, G_MAXSHORT);
rectangles[i].y = CLAMP (boxes[i].y1 + private->clip_y_origin, G_MINSHORT, G_MAXSHORT);
rectangles[i].width = CLAMP (boxes[i].x2 + private->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].x;
rectangles[i].height = CLAMP (boxes[i].y2 + private->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].y;
}
XSetClipRectangles(GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0, rectangles,
data->clip_region->numRects, YXBanded);
g_free (rectangles);
}
}
if (data->dirty_mask & GDK_GC_DIRTY_TS)
{
XSetTSOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
private->ts_x_origin, private->ts_y_origin);
}
data->dirty_mask = 0;
return GDK_GC_XGC (gc);
}
static void
gdk_x11_gc_get_values (GdkGC *gc,
GdkGCValues *values)
@ -215,9 +282,35 @@ gdk_x11_gc_set_values (GdkGC *gc,
GdkGCValues *values,
GdkGCValuesMask values_mask)
{
GdkGCXData *data;
XGCValues xvalues;
unsigned long xvalues_mask = 0;
g_return_if_fail (gc != NULL);
data = GDK_GC_XDATA (gc);
if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
{
values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
data->dirty_mask |= GDK_GC_DIRTY_CLIP;
}
if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
{
values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
data->dirty_mask |= GDK_GC_DIRTY_TS;
}
if (values_mask & GDK_GC_CLIP_MASK)
{
if (data->clip_region)
{
gdk_region_destroy (data->clip_region);
data->clip_region = NULL;
}
}
gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
XChangeGC (GDK_GC_XDISPLAY (gc),
@ -454,43 +547,56 @@ void
gdk_gc_set_clip_rectangle (GdkGC *gc,
GdkRectangle *rectangle)
{
XRectangle xrectangle;
GdkGCPrivate *private = (GdkGCPrivate *)gc;
GdkGCXData *data;
g_return_if_fail (gc != NULL);
data = GDK_GC_XDATA (gc);
if (data->clip_region)
gdk_region_destroy (data->clip_region);
if (rectangle)
{
xrectangle.x = rectangle->x;
xrectangle.y = rectangle->y;
xrectangle.width = rectangle->width;
xrectangle.height = rectangle->height;
XSetClipRectangles (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0,
&xrectangle, 1, Unsorted);
}
data->clip_region = gdk_region_rectangle (rectangle);
else
XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
{
data->clip_region = NULL;
XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
}
private->clip_x_origin = 0;
private->clip_y_origin = 0;
data->dirty_mask |= GDK_GC_DIRTY_CLIP;
}
void
gdk_gc_set_clip_region (GdkGC *gc,
GdkRegion *region)
gdk_gc_set_clip_region (GdkGC *gc,
GdkRegion *region)
{
GdkGCPrivate *private;
GdkGCPrivate *private = (GdkGCPrivate *)gc;
GdkGCXData *data;
g_return_if_fail (gc != NULL);
private = (GdkGCPrivate*) gc;
data = GDK_GC_XDATA (gc);
if (data->clip_region)
gdk_region_destroy (data->clip_region);
if (region)
{
GdkRegionPrivate *region_private;
region_private = (GdkRegionPrivate*) region;
XSetRegion (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), region_private->xregion);
}
data->clip_region = gdk_region_copy (region);
else
XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
{
data->clip_region = NULL;
XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
}
private->clip_x_origin = 0;
private->clip_y_origin = 0;
data->dirty_mask |= GDK_GC_DIRTY_CLIP;
}

698
gdk/x11/gdkgeometry-x11.c Normal file
View File

@ -0,0 +1,698 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* gdkgeometry-x11.c: emulation of 32 bit coordinates within the
* limits of X.
*
* By Owen Taylor <otaylor@redhat.com>
* Copyright Red Hat, Inc. 2000
*/
#include "gdk.h" /* For gdk_rectangle_intersect */
#include "gdkprivate-x11.h"
#include "gdkx.h"
#include "gdkregion.h"
typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
typedef struct _GdkWindowParentPos GdkWindowParentPos;
typedef enum {
GDK_WINDOW_QUEUE_TRANSLATE,
GDK_WINDOW_QUEUE_ANTIEXPOSE
} GdkWindowQueueType;
struct _GdkWindowQueueItem
{
GdkWindow *window;
gulong serial;
GdkWindowQueueType type;
union {
struct {
gint dx;
gint dy;
} translate;
struct {
GdkRegion *area;
} antiexpose;
} u;
};
struct _GdkWindowParentPos
{
gint x;
gint y;
gint x11_x;
gint x11_y;
GdkRectangle clip_rect;
};
static void gdk_window_compute_position (GdkWindow *window,
GdkWindowParentPos *parent_pos,
GdkXPositionInfo *info);
static void gdk_window_compute_parent_pos (GdkWindow *window,
GdkWindowParentPos *parent_pos);
static void gdk_window_premove (GdkWindow *window,
GdkWindowParentPos *parent_pos);
static void gdk_window_postmove (GdkWindow *window,
GdkWindowParentPos *parent_pos);
static void gdk_window_queue_translation (GdkWindow *window,
gint dx,
gint dy);
static void gdk_window_tmp_unset_bg (GdkWindow *window);
static void gdk_window_tmp_reset_bg (GdkWindow *window);
static void gdk_window_clip_changed (GdkWindow *window,
GdkRectangle *old_clip,
GdkRectangle *new_clip);
static GSList *translate_queue = NULL;
void
_gdk_windowing_window_get_offsets (GdkWindow *window,
gint *x_offset,
gint *y_offset)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data = (GdkWindowXData *)private->drawable.klass_data;
*x_offset = data->position_info.x_offset;
*y_offset = data->position_info.y_offset;
}
void
_gdk_window_init_position (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data;
GdkWindowParentPos parent_pos;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
data = (GdkWindowXData *)private->drawable.klass_data;
gdk_window_compute_parent_pos (window, &parent_pos);
gdk_window_compute_position (window, &parent_pos, &data->position_info);
}
void
_gdk_window_move_resize_child (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkXPositionInfo new_info;
GdkWindowParentPos parent_pos;
GdkWindowXData *data;
GList *tmp_list;
gint d_xoffset, d_yoffset;
gint dx, dy;
gboolean is_move;
gboolean is_resize;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
data = (GdkWindowXData *)private->drawable.klass_data;
dx = x - private->x;
dy = y - private->y;
is_move = dx != 0 || dy != 0;
is_resize = private->drawable.width != width || private->drawable.height != height;
if (!is_move && !is_resize)
return;
private->x = x;
private->y = y;
private->drawable.width = width;
private->drawable.height = height;
gdk_window_compute_parent_pos (window, &parent_pos);
gdk_window_compute_position (window, &parent_pos, &new_info);
gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
parent_pos.x += private->x;
parent_pos.y += private->y;
parent_pos.x11_x += new_info.x;
parent_pos.x11_y += new_info.y;
parent_pos.clip_rect = new_info.clip_rect;
d_xoffset = new_info.x_offset - data->position_info.x_offset;
d_yoffset = new_info.y_offset - data->position_info.y_offset;
if (d_xoffset != 0 || d_yoffset != 0)
{
gint new_x0, new_y0, new_x1, new_y1;
gdk_window_set_static_gravities (window, TRUE);
if (d_xoffset < 0 || d_yoffset < 0)
gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
if (d_xoffset < 0)
{
new_x0 = data->position_info.x + d_xoffset;
new_x1 = data->position_info.x + data->position_info.width;
}
else
{
new_x0 = data->position_info.x;
new_x1 = data->position_info.x + new_info.width + d_xoffset;
}
if (d_yoffset < 0)
{
new_y0 = data->position_info.y + d_yoffset;
new_y1 = data->position_info.y + data->position_info.height;
}
else
{
new_y0 = data->position_info.y;
new_y1 = data->position_info.y + new_info.height + d_yoffset;
}
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
tmp_list = private->children;
while (tmp_list)
{
gdk_window_premove (tmp_list->data, &parent_pos);
tmp_list = tmp_list->next;
}
XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_x0 + dx, new_y0 + dy);
if (d_xoffset > 0 || d_yoffset > 0)
gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_info.x, new_info.y, new_info.width, new_info.height);
if (data->position_info.no_bg)
gdk_window_tmp_reset_bg (window);
if (!data->position_info.mapped && new_info.mapped && private->mapped)
XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
data->position_info = new_info;
tmp_list = private->children;
while (tmp_list)
{
gdk_window_postmove (tmp_list->data, &parent_pos);
tmp_list = tmp_list->next;
}
}
else
{
if (is_move && is_resize)
gdk_window_set_static_gravities (window, FALSE);
if (data->position_info.mapped && !new_info.mapped)
XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
tmp_list = private->children;
while (tmp_list)
{
gdk_window_premove (tmp_list->data, &parent_pos);
tmp_list = tmp_list->next;
}
if (is_resize)
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_info.x, new_info.y, new_info.width, new_info.height);
else
XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_info.x, new_info.y);
tmp_list = private->children;
while (tmp_list)
{
gdk_window_postmove (tmp_list->data, &parent_pos);
tmp_list = tmp_list->next;
}
if (data->position_info.no_bg)
gdk_window_tmp_reset_bg (window);
if (!data->position_info.mapped && new_info.mapped && private->mapped)
XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
data->position_info = new_info;
}
}
static void
gdk_window_compute_position (GdkWindow *window,
GdkWindowParentPos *parent_pos,
GdkXPositionInfo *info)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
int parent_x_offset;
int parent_y_offset;
info->big = FALSE;
if (private->drawable.width <= 32768)
{
info->width = private->drawable.width;
info->x = parent_pos->x + private->x - parent_pos->x11_x;
}
else
{
info->big = TRUE;
info->width = 32768;
if (parent_pos->x + private->x < -16384)
{
if (parent_pos->x + private->x + private->drawable.width < 16384)
info->x = parent_pos->x + private->x + private->drawable.width - 32768 - parent_pos->x11_x;
else
info->x = -16384 - parent_pos->x11_y;
}
else
info->x = parent_pos->x + private->x - parent_pos->x11_x;
}
if (private->drawable.height <= 32768)
{
info->height = private->drawable.height;
info->y = parent_pos->y + private->y - parent_pos->x11_y;
}
else
{
info->big = TRUE;
info->height = 32768;
if (parent_pos->y + private->y < -16384)
{
if (parent_pos->y + private->y + private->drawable.height < 16384)
info->y = parent_pos->y + private->y + private->drawable.height - 32768 - parent_pos->x11_y;
else
info->y = -16384 - parent_pos->x11_y;
}
else
info->y = parent_pos->y + private->y - parent_pos->x11_y;
}
parent_x_offset = parent_pos->x11_x - parent_pos->x;
parent_y_offset = parent_pos->x11_y - parent_pos->y;
info->x_offset = parent_x_offset + info->x - private->x;
info->y_offset = parent_y_offset + info->y - private->y;
/* We don't considering the clipping of toplevel windows and their immediate children
* by their parents, and simply always map those windows.
*/
if (parent_pos->clip_rect.width == G_MAXINT)
info->mapped = TRUE;
/* Check if the window would wrap around into the visible space in either direction */
else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
info->y + info->width + parent_y_offset > parent_pos->clip_rect.y + 65536)
info->mapped = FALSE;
else
info->mapped = TRUE;
info->no_bg = FALSE;
if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
{
info->clip_rect.x = private->x;
info->clip_rect.y = private->y;
info->clip_rect.width = private->drawable.width;
info->clip_rect.height = private->drawable.height;
gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
info->clip_rect.x -= private->x;
info->clip_rect.y -= private->y;
}
else
{
info->clip_rect.x = 0;
info->clip_rect.y = 0;
info->clip_rect.width = G_MAXINT;
info->clip_rect.height = G_MAXINT;
}
}
static void
gdk_window_compute_parent_pos (GdkWindow *window,
GdkWindowParentPos *parent_pos)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data;
GdkRectangle tmp_clip;
int clip_xoffset = 0;
int clip_yoffset = 0;
parent_pos->x = 0;
parent_pos->y = 0;
parent_pos->x11_x = 0;
parent_pos->x11_y = 0;
/* We take a simple approach here and simply consider toplevel
* windows not to clip their children on the right/bottom, since the
* size of toplevel windows is not directly under our
* control. Clipping only really matters when scrolling and
* generally we aren't going to be moving the immediate child of a
* toplevel beyond the bounds of that toplevel.
*
* We could go ahead and recompute the clips of toplevel windows and
* their descendents when we receive size notification, but it would
* probably not be an improvement in most cases.
*/
parent_pos->clip_rect.x = 0;
parent_pos->clip_rect.y = 0;
parent_pos->clip_rect.width = G_MAXINT;
parent_pos->clip_rect.height = G_MAXINT;
private = (GdkWindowPrivate *)private->parent;
while (private && private->drawable.window_type == GDK_WINDOW_CHILD)
{
data = (GdkWindowXData *)private->drawable.klass_data;
tmp_clip.x = - clip_xoffset;
tmp_clip.y = - clip_yoffset;
tmp_clip.width = private->drawable.width;
tmp_clip.height = private->drawable.height;
gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
parent_pos->x += private->x;
parent_pos->y += private->y;
parent_pos->x11_x += data->position_info.x;
parent_pos->x11_y += data->position_info.y;
clip_xoffset += private->x;
clip_yoffset += private->y;
private = (GdkWindowPrivate *)private->parent;
}
}
static void
gdk_window_premove (GdkWindow *window,
GdkWindowParentPos *parent_pos)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data = GDK_WINDOW_XDATA (window);
GdkXPositionInfo new_info;
GList *tmp_list;
gint d_xoffset, d_yoffset;
GdkWindowParentPos this_pos;
gdk_window_compute_position (window, parent_pos, &new_info);
gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
this_pos.x = parent_pos->x + private->x;
this_pos.y = parent_pos->y + private->y;
this_pos.x11_x = parent_pos->x11_x + new_info.x;
this_pos.x11_y = parent_pos->x11_y + new_info.y;
this_pos.clip_rect = new_info.clip_rect;
if (data->position_info.mapped && !new_info.mapped)
XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
d_xoffset = new_info.x_offset - data->position_info.x_offset;
d_yoffset = new_info.y_offset - data->position_info.y_offset;
if (d_xoffset != 0 || d_yoffset != 0)
{
gint new_x0, new_y0, new_x1, new_y1;
if (d_xoffset < 0 || d_yoffset < 0)
gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
if (d_xoffset < 0)
{
new_x0 = data->position_info.x + d_xoffset;
new_x1 = data->position_info.x + data->position_info.width;
}
else
{
new_x0 = data->position_info.x;
new_x1 = data->position_info.x + new_info.width + d_xoffset;
}
if (d_yoffset < 0)
{
new_y0 = data->position_info.y + d_yoffset;
new_y1 = data->position_info.y + data->position_info.height;
}
else
{
new_y0 = data->position_info.y;
new_y1 = data->position_info.y + new_info.height + d_yoffset;
}
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
}
tmp_list = private->children;
while (tmp_list)
{
gdk_window_premove (tmp_list->data, &this_pos);
tmp_list = tmp_list->next;
}
}
static void
gdk_window_postmove (GdkWindow *window,
GdkWindowParentPos *parent_pos)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data = (GdkWindowXData *)private->drawable.klass_data;
GdkXPositionInfo new_info;
GList *tmp_list;
gint d_xoffset, d_yoffset;
GdkWindowParentPos this_pos;
gdk_window_compute_position (window, parent_pos, &new_info);
this_pos.x = parent_pos->x + private->x;
this_pos.y = parent_pos->y + private->y;
this_pos.x11_x = parent_pos->x11_x + new_info.x;
this_pos.x11_y = parent_pos->x11_y + new_info.y;
this_pos.clip_rect = new_info.clip_rect;
d_xoffset = new_info.x_offset - data->position_info.x_offset;
d_yoffset = new_info.y_offset - data->position_info.y_offset;
if (d_xoffset != 0 || d_yoffset != 0)
{
if (d_xoffset > 0 || d_yoffset > 0)
gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
new_info.x, new_info.y, new_info.width, new_info.height);
}
if (!data->position_info.mapped && new_info.mapped && private->mapped)
XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
if (data->position_info.no_bg)
gdk_window_tmp_reset_bg (window);
data->position_info = new_info;
tmp_list = private->children;
while (tmp_list)
{
gdk_window_postmove (tmp_list->data, &this_pos);
tmp_list = tmp_list->next;
}
}
static void
gdk_window_queue_translation (GdkWindow *window,
gint dx,
gint dy)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->window = window;
item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
item->type = GDK_WINDOW_QUEUE_TRANSLATE;
item->u.translate.dx = dx;
item->u.translate.dy = dy;
gdk_drawable_ref (window);
translate_queue = g_slist_append (translate_queue, item);
}
gboolean
_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
GdkRegion *area)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->window = window;
item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
item->u.antiexpose.area = area;
gdk_drawable_ref (window);
translate_queue = g_slist_append (translate_queue, item);
return TRUE;
}
void
_gdk_window_process_expose (GdkWindow *window,
gulong serial,
GdkRectangle *area)
{
GdkWindowXData *data = GDK_WINDOW_XDATA (window);
GdkRegion *invalidate_region = gdk_region_rectangle (area);
GdkRegion *clip_region;
GSList *tmp_list = translate_queue;
while (tmp_list)
{
GdkWindowQueueItem *item = tmp_list->data;
tmp_list = tmp_list->next;
if (serial < item->serial)
{
if (item->window == window)
{
if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
else /* anti-expose */
gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
}
}
else
{
GSList *tmp_link = translate_queue;
translate_queue = g_slist_remove_link (translate_queue, translate_queue);
gdk_drawable_unref (item->window);
if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
gdk_region_destroy (item->u.antiexpose.area);
g_free (item);
g_slist_free_1 (tmp_link);
}
}
clip_region = gdk_region_rectangle (&data->position_info.clip_rect);
gdk_region_intersect (invalidate_region, clip_region);
if (!gdk_region_empty (invalidate_region))
gdk_window_invalidate_region (window, invalidate_region, FALSE);
gdk_region_destroy (invalidate_region);
gdk_region_destroy (clip_region);
}
static void
gdk_window_tmp_unset_bg (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data = GDK_WINDOW_XDATA (window);
data->position_info.no_bg = TRUE;
if (private->bg_pixmap != GDK_NO_BG)
XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window), None);
}
static void
gdk_window_tmp_reset_bg (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkWindowXData *data = GDK_WINDOW_XDATA (window);
data->position_info.no_bg = FALSE;
if (private->bg_pixmap == GDK_NO_BG)
return;
if (private->bg_pixmap)
{
Pixmap xpixmap;
if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG)
xpixmap = ParentRelative;
else
xpixmap = GDK_DRAWABLE_XID (private->bg_pixmap);
XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window), xpixmap);
}
else
{
XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
private->bg_color.pixel);
}
}
static void
gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GdkRegion *old_clip_region;
GdkRegion *new_clip_region;
if (private->input_only)
return;
old_clip_region = gdk_region_rectangle (old_clip);
new_clip_region = gdk_region_rectangle (new_clip);
/* Trim invalid region of window to new clip rectangle
*/
if (private->update_area)
gdk_region_intersect (private->update_area, new_clip_region);
/* Invalidate newly exposed portion of window
*/
gdk_region_subtract (new_clip_region, old_clip_region);
if (!gdk_region_empty (new_clip_region))
{
gdk_window_tmp_unset_bg (window);
gdk_window_invalidate_region (window, new_clip_region, FALSE);
}
gdk_region_destroy (new_clip_region);
gdk_region_destroy (old_clip_region);
}

View File

@ -29,9 +29,9 @@
#include "gdk.h" /* For gdk_flush() */
#include "gdkim.h"
#include "gdkpixmap.h"
#include "gdkprivate.h"
#include "gdki18n.h"
#include "gdkx.h"
#include "gdkinternals.h"
#include "gdkprivate-x11.h"
#if HAVE_CONFIG_H
# include <config.h>

View File

@ -56,7 +56,7 @@
#include "gdk.h" /* For gdk_error_trap_* / gdk_flush_* */
#include "gdkimage.h"
#include "gdkprivate.h"
#include "gdkx.h"
#include "gdkprivate-x11.h"
static void gdk_x11_image_destroy (GdkImage *image);
static void gdk_image_put_normal (GdkImage *image,
@ -480,7 +480,7 @@ gdk_image_put_normal (GdkImage *image,
g_return_if_fail (image->type == GDK_IMAGE_NORMAL);
XPutImage (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), image_private->ximage,
GDK_GC_GET_XGC (gc), image_private->ximage,
xsrc, ysrc, xdest, ydest, width, height);
}
@ -509,7 +509,7 @@ gdk_image_put_shared (GdkImage *image,
g_return_if_fail (image->type == GDK_IMAGE_SHARED);
XShmPutImage (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
GDK_GC_XGC (gc), image_private->ximage,
GDK_GC_GET_XGC (gc), image_private->ximage,
xsrc, ysrc, xdest, ydest, width, height, False);
#else /* USE_SHM */
g_error ("trying to draw shared memory image when gdk was compiled without shared memory support");

View File

@ -25,6 +25,7 @@
*/
#include "gdkinputprivate.h"
#include "gdkinternals.h"
#include "gdkx.h"
/* Forward declarations */
@ -146,6 +147,7 @@ gdk_input_device_new(XDeviceInfo *device, gint include_core)
gdkdev->info.num_axes = 0;
gdkdev->info.num_keys = 0;
gdkdev->info.axes = NULL;
gdkdev->info.keys = NULL;
gdkdev->axes = 0;
gdkdev->info.has_cursor = 0;
@ -237,6 +239,8 @@ gdk_input_device_new(XDeviceInfo *device, gint include_core)
g_free(gdkdev->axes);
if (gdkdev->info.keys)
g_free(gdkdev->info.keys);
if (gdkdev->info.axes)
g_free (gdkdev->info.axes);
g_free(gdkdev);
return NULL;
}

View File

@ -141,8 +141,8 @@ struct _GdkInputWindow
GdkExtensionMode mode;
/* position relative to root window */
gint16 root_x;
gint16 root_y;
gint root_x;
gint root_y;
/* rectangles relative to window of windows obscuring this one */
GdkRectangle *obscuring;

View File

@ -46,8 +46,8 @@
#include "gdk.h"
#include "gdkx.h"
#include "gdkprivate.h"
#include "gdkprivate-x11.h"
#include "gdkinternals.h"
#include "gdkinputprivate.h"
typedef struct _GdkPredicate GdkPredicate;

View File

@ -33,8 +33,7 @@
#include <X11/Xlib.h>
#include "gdkpixmap.h"
#include "gdkprivate.h"
#include "gdkx.h"
#include "gdkprivate-x11.h"
typedef struct
{
@ -119,6 +118,7 @@ gdk_pixmap_new (GdkWindow *window,
width, height, depth);
private->width = width;
private->height = height;
private->depth = depth;
gdk_xid_table_insert (&GDK_DRAWABLE_XID (pixmap), pixmap);
@ -149,6 +149,7 @@ gdk_bitmap_create_from_data (GdkWindow *window,
private->width = width;
private->height = height;
private->depth = 1;
GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DRAWABLE_XDISPLAY (window);
GDK_DRAWABLE_XDATA (private)->xid = XCreateBitmapFromData (GDK_DRAWABLE_XDISPLAY (window),
@ -193,6 +194,7 @@ gdk_pixmap_create_from_data (GdkWindow *window,
private->width = width;
private->height = height;
private->depth = depth;
GDK_DRAWABLE_XDATA (private)->xdisplay = GDK_DRAWABLE_XDISPLAY (window);
GDK_DRAWABLE_XDATA (private)->xid = XCreatePixmapFromBitmapData (GDK_DRAWABLE_XDISPLAY (window),
@ -804,6 +806,7 @@ gdk_pixmap_foreign_new (guint32 anid)
private->width = w_ret;
private->height = h_ret;
private->depth = depth_ret;
gdk_xid_table_insert(&GDK_DRAWABLE_XID (pixmap), pixmap);

291
gdk/x11/gdkpoly-generic.h Normal file
View File

@ -0,0 +1,291 @@
/* $TOG: poly.h /main/5 1998/02/06 17:47:27 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
/*
* This file contains a few macros to help track
* the edge of a filled object. The object is assumed
* to be filled in scanline order, and thus the
* algorithm used is an extension of Bresenham's line
* drawing algorithm which assumes that y is always the
* major axis.
* Since these pieces of code are the same for any filled shape,
* it is more convenient to gather the library in one
* place, but since these pieces of code are also in
* the inner loops of output primitives, procedure call
* overhead is out of the question.
* See the author for a derivation if needed.
*/
/*
* In scan converting polygons, we want to choose those pixels
* which are inside the polygon. Thus, we add .5 to the starting
* x coordinate for both left and right edges. Now we choose the
* first pixel which is inside the pgon for the left edge and the
* first pixel which is outside the pgon for the right edge.
* Draw the left pixel, but not the right.
*
* How to add .5 to the starting x coordinate:
* If the edge is moving to the right, then subtract dy from the
* error term from the general form of the algorithm.
* If the edge is moving to the left, then add dy to the error term.
*
* The reason for the difference between edges moving to the left
* and edges moving to the right is simple: If an edge is moving
* to the right, then we want the algorithm to flip immediately.
* If it is moving to the left, then we don't want it to flip until
* we traverse an entire pixel.
*/
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
int dx; /* local storage */ \
\
/* \
* if the edge is horizontal, then it is ignored \
* and assumed not to be processed. Otherwise, do this stuff. \
*/ \
if ((dy) != 0) { \
xStart = (x1); \
dx = (x2) - xStart; \
if (dx < 0) { \
m = dx / (dy); \
m1 = m - 1; \
incr1 = -2 * dx + 2 * (dy) * m1; \
incr2 = -2 * dx + 2 * (dy) * m; \
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
} else { \
m = dx / (dy); \
m1 = m + 1; \
incr1 = 2 * dx - 2 * (dy) * m1; \
incr2 = 2 * dx - 2 * (dy) * m; \
d = -2 * m * (dy) + 2 * dx; \
} \
} \
}
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
if (m1 > 0) { \
if (d > 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} else {\
if (d >= 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} \
}
/*
* This structure contains all of the information needed
* to run the bresenham algorithm.
* The variables may be hardcoded into the declarations
* instead of using this structure to make use of
* register declarations.
*/
typedef struct {
int minor_axis; /* minor axis */
int d; /* decision variable */
int m, m1; /* slope and slope+1 */
int incr1, incr2; /* error increments */
} BRESINFO;
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
bres.m, bres.m1, bres.incr1, bres.incr2)
#define BRESINCRPGONSTRUCT(bres) \
BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
/*
* These are the data structures needed to scan
* convert regions. Two different scan conversion
* methods are available -- the even-odd method, and
* the winding number method.
* The even-odd rule states that a point is inside
* the polygon if a ray drawn from that point in any
* direction will pass through an odd number of
* path segments.
* By the winding number rule, a point is decided
* to be inside the polygon if a ray drawn from that
* point in any direction passes through a different
* number of clockwise and counter-clockwise path
* segments.
*
* These data structures are adapted somewhat from
* the algorithm in (Foley/Van Dam) for scan converting
* polygons.
* The basic algorithm is to start at the top (smallest y)
* of the polygon, stepping down to the bottom of
* the polygon by incrementing the y coordinate. We
* keep a list of edges which the current scanline crosses,
* sorted by x. This list is called the Active Edge Table (AET)
* As we change the y-coordinate, we update each entry in
* in the active edge table to reflect the edges new xcoord.
* This list must be sorted at each scanline in case
* two edges intersect.
* We also keep a data structure known as the Edge Table (ET),
* which keeps track of all the edges which the current
* scanline has not yet reached. The ET is basically a
* list of ScanLineList structures containing a list of
* edges which are entered at a given scanline. There is one
* ScanLineList per scanline at which an edge is entered.
* When we enter a new edge, we move it from the ET to the AET.
*
* From the AET, we can implement the even-odd rule as in
* (Foley/Van Dam).
* The winding number rule is a little trickier. We also
* keep the EdgeTableEntries in the AET linked by the
* nextWETE (winding EdgeTableEntry) link. This allows
* the edges to be linked just as before for updating
* purposes, but only uses the edges linked by the nextWETE
* link as edges representing spans of the polygon to
* drawn (as with the even-odd rule).
*/
/*
* for the winding number rule
*/
#define CLOCKWISE 1
#define COUNTERCLOCKWISE -1
typedef struct _EdgeTableEntry {
int ymax; /* ycoord at which we exit this edge. */
BRESINFO bres; /* Bresenham info to run the edge */
struct _EdgeTableEntry *next; /* next in the list */
struct _EdgeTableEntry *back; /* for insertion sort */
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
int ClockWise; /* flag for winding number rule */
} EdgeTableEntry;
typedef struct _ScanLineList{
int scanline; /* the scanline represented */
EdgeTableEntry *edgelist; /* header node */
struct _ScanLineList *next; /* next in the list */
} ScanLineList;
typedef struct {
int ymax; /* ymax for the polygon */
int ymin; /* ymin for the polygon */
ScanLineList scanlines; /* header node */
} EdgeTable;
/*
* Here is a struct to help with storage allocation
* so we can allocate a big chunk at a time, and then take
* pieces from this heap when we need to.
*/
#define SLLSPERBLOCK 25
typedef struct _ScanLineListBlock {
ScanLineList SLLs[SLLSPERBLOCK];
struct _ScanLineListBlock *next;
} ScanLineListBlock;
/*
*
* a few macros for the inner loops of the fill code where
* performance considerations don't allow a procedure call.
*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The winding number rule is in effect, so we must notify
* the caller when the edge has been removed so he
* can reorder the Winding Active Edge Table.
*/
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
fixWAET = 1; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}
/*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The even-odd rule is in effect.
*/
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}

View File

@ -0,0 +1,616 @@
/* $TOG: PolyReg.c /main/15 1998/02/06 17:47:08 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
/* $XFree86: xc/lib/X11/PolyReg.c,v 1.4 1998/10/03 08:41:21 dawes Exp $ */
#define LARGE_COORDINATE 1000000
#define SMALL_COORDINATE -LARGE_COORDINATE
#include <gdkregion.h>
#include "gdkregion-generic.h"
#include "gdkpoly-generic.h"
/*
* InsertEdgeInET
*
* Insert the given edge into the edge table.
* First we must find the correct bucket in the
* Edge table, then find the right slot in the
* bucket. Finally, we can insert it.
*
*/
static void
InsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
EdgeTable *ET;
EdgeTableEntry *ETE;
int scanline;
ScanLineListBlock **SLLBlock;
int *iSLLBlock;
{
EdgeTableEntry *start, *prev;
ScanLineList *pSLL, *pPrevSLL;
ScanLineListBlock *tmpSLLBlock;
/*
* find the right bucket to put the edge into
*/
pPrevSLL = &ET->scanlines;
pSLL = pPrevSLL->next;
while (pSLL && (pSLL->scanline < scanline))
{
pPrevSLL = pSLL;
pSLL = pSLL->next;
}
/*
* reassign pSLL (pointer to ScanLineList) if necessary
*/
if ((!pSLL) || (pSLL->scanline > scanline))
{
if (*iSLLBlock > SLLSPERBLOCK-1)
{
tmpSLLBlock =
(ScanLineListBlock *)g_malloc(sizeof(ScanLineListBlock));
(*SLLBlock)->next = tmpSLLBlock;
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
*SLLBlock = tmpSLLBlock;
*iSLLBlock = 0;
}
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
pSLL->next = pPrevSLL->next;
pSLL->edgelist = (EdgeTableEntry *)NULL;
pPrevSLL->next = pSLL;
}
pSLL->scanline = scanline;
/*
* now insert the edge in the right bucket
*/
prev = (EdgeTableEntry *)NULL;
start = pSLL->edgelist;
while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
{
prev = start;
start = start->next;
}
ETE->next = start;
if (prev)
prev->next = ETE;
else
pSLL->edgelist = ETE;
}
/*
* CreateEdgeTable
*
* This routine creates the edge table for
* scan converting polygons.
* The Edge Table (ET) looks like:
*
* EdgeTable
* --------
* | ymax | ScanLineLists
* |scanline|-->------------>-------------->...
* -------- |scanline| |scanline|
* |edgelist| |edgelist|
* --------- ---------
* | |
* | |
* V V
* list of ETEs list of ETEs
*
* where ETE is an EdgeTableEntry data structure,
* and there is one ScanLineList per scanline at
* which an edge is initially entered.
*
*/
static void
CreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
int count;
GdkPoint *pts;
EdgeTable *ET;
EdgeTableEntry *AET;
EdgeTableEntry *pETEs;
ScanLineListBlock *pSLLBlock;
{
GdkPoint *top, *bottom;
GdkPoint *PrevPt, *CurrPt;
int iSLLBlock = 0;
int dy;
if (count < 2) return;
/*
* initialize the Active Edge Table
*/
AET->next = (EdgeTableEntry *)NULL;
AET->back = (EdgeTableEntry *)NULL;
AET->nextWETE = (EdgeTableEntry *)NULL;
AET->bres.minor_axis = SMALL_COORDINATE;
/*
* initialize the Edge Table.
*/
ET->scanlines.next = (ScanLineList *)NULL;
ET->ymax = SMALL_COORDINATE;
ET->ymin = LARGE_COORDINATE;
pSLLBlock->next = (ScanLineListBlock *)NULL;
PrevPt = &pts[count-1];
/*
* for each vertex in the array of points.
* In this loop we are dealing with two vertices at
* a time -- these make up one edge of the polygon.
*/
while (count--)
{
CurrPt = pts++;
/*
* find out which point is above and which is below.
*/
if (PrevPt->y > CurrPt->y)
{
bottom = PrevPt, top = CurrPt;
pETEs->ClockWise = 0;
}
else
{
bottom = CurrPt, top = PrevPt;
pETEs->ClockWise = 1;
}
/*
* don't add horizontal edges to the Edge table.
*/
if (bottom->y != top->y)
{
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
/*
* initialize integer edge algorithm
*/
dy = bottom->y - top->y;
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
if (PrevPt->y > ET->ymax)
ET->ymax = PrevPt->y;
if (PrevPt->y < ET->ymin)
ET->ymin = PrevPt->y;
pETEs++;
}
PrevPt = CurrPt;
}
}
/*
* loadAET
*
* This routine moves EdgeTableEntries from the
* EdgeTable into the Active Edge Table,
* leaving them sorted by smaller x coordinate.
*
*/
static void
loadAET(AET, ETEs)
EdgeTableEntry *AET, *ETEs;
{
EdgeTableEntry *pPrevAET;
EdgeTableEntry *tmp;
pPrevAET = AET;
AET = AET->next;
while (ETEs)
{
while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
{
pPrevAET = AET;
AET = AET->next;
}
tmp = ETEs->next;
ETEs->next = AET;
if (AET)
AET->back = ETEs;
ETEs->back = pPrevAET;
pPrevAET->next = ETEs;
pPrevAET = ETEs;
ETEs = tmp;
}
}
/*
* computeWAET
*
* This routine links the AET by the
* nextWETE (winding EdgeTableEntry) link for
* use by the winding number rule. The final
* Active Edge Table (AET) might look something
* like:
*
* AET
* ---------- --------- ---------
* |ymax | |ymax | |ymax |
* | ... | |... | |... |
* |next |->|next |->|next |->...
* |nextWETE| |nextWETE| |nextWETE|
* --------- --------- ^--------
* | | |
* V-------------------> V---> ...
*
*/
static void
computeWAET(AET)
EdgeTableEntry *AET;
{
EdgeTableEntry *pWETE;
int inside = 1;
int isInside = 0;
AET->nextWETE = (EdgeTableEntry *)NULL;
pWETE = AET;
AET = AET->next;
while (AET)
{
if (AET->ClockWise)
isInside++;
else
isInside--;
if ((!inside && !isInside) ||
( inside && isInside))
{
pWETE->nextWETE = AET;
pWETE = AET;
inside = !inside;
}
AET = AET->next;
}
pWETE->nextWETE = (EdgeTableEntry *)NULL;
}
/*
* InsertionSort
*
* Just a simple insertion sort using
* pointers and back pointers to sort the Active
* Edge Table.
*
*/
static int
InsertionSort(AET)
EdgeTableEntry *AET;
{
EdgeTableEntry *pETEchase;
EdgeTableEntry *pETEinsert;
EdgeTableEntry *pETEchaseBackTMP;
int changed = 0;
AET = AET->next;
while (AET)
{
pETEinsert = AET;
pETEchase = AET;
while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
pETEchase = pETEchase->back;
AET = AET->next;
if (pETEchase != pETEinsert)
{
pETEchaseBackTMP = pETEchase->back;
pETEinsert->back->next = AET;
if (AET)
AET->back = pETEinsert->back;
pETEinsert->next = pETEchase;
pETEchase->back->next = pETEinsert;
pETEchase->back = pETEinsert;
pETEinsert->back = pETEchaseBackTMP;
changed = 1;
}
}
return(changed);
}
/*
* Clean up our act.
*/
static void
FreeStorage(pSLLBlock)
ScanLineListBlock *pSLLBlock;
{
ScanLineListBlock *tmpSLLBlock;
while (pSLLBlock)
{
tmpSLLBlock = pSLLBlock->next;
g_free (pSLLBlock);
pSLLBlock = tmpSLLBlock;
}
}
/*
* Create an array of rectangles from a list of points.
* If indeed these things (POINTS, RECTS) are the same,
* then this proc is still needed, because it allocates
* storage for the array, which was allocated on the
* stack by the calling procedure.
*
*/
static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg)
int numFullPtBlocks, iCurPtBlock;
POINTBLOCK *FirstPtBlock;
GdkRegion *reg;
{
GdkRegionBox *rects;
GdkPoint *pts;
POINTBLOCK *CurPtBlock;
int i;
GdkRegionBox *extents;
int numRects;
extents = &reg->extents;
numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
reg->rects = g_renew (GdkRegionBox, reg->rects, numRects);
reg->size = numRects;
CurPtBlock = FirstPtBlock;
rects = reg->rects - 1;
numRects = 0;
extents->x1 = G_MAXSHORT, extents->x2 = G_MINSHORT;
for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
/* the loop uses 2 points per iteration */
i = NUMPTSTOBUFFER >> 1;
if (!numFullPtBlocks)
i = iCurPtBlock >> 1;
for (pts = CurPtBlock->pts; i--; pts += 2) {
if (pts->x == pts[1].x)
continue;
if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
pts[1].x == rects->x2 &&
(numRects == 1 || rects[-1].y1 != rects->y1) &&
(i && pts[2].y > pts[1].y)) {
rects->y2 = pts[1].y + 1;
continue;
}
numRects++;
rects++;
rects->x1 = pts->x; rects->y1 = pts->y;
rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1;
if (rects->x1 < extents->x1)
extents->x1 = rects->x1;
if (rects->x2 > extents->x2)
extents->x2 = rects->x2;
}
CurPtBlock = CurPtBlock->next;
}
if (numRects) {
extents->y1 = reg->rects->y1;
extents->y2 = rects->y2;
} else {
extents->x1 = 0;
extents->y1 = 0;
extents->x2 = 0;
extents->y2 = 0;
}
reg->numRects = numRects;
return(TRUE);
}
/*
* polytoregion
*
* Scan converts a polygon by returning a run-length
* encoding of the resultant bitmap -- the run-length
* encoding is in the form of an array of rectangles.
*/
GdkRegion *
gdk_region_polygon(GdkPoint *Pts, gint Count, GdkFillRule rule)
{
GdkRegion *region;
EdgeTableEntry *pAET; /* Active Edge Table */
int y; /* current scanline */
int iPts = 0; /* number of pts in buffer */
EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/
ScanLineList *pSLL; /* current scanLineList */
GdkPoint *pts; /* output buffer */
EdgeTableEntry *pPrevAET; /* ptr to previous AET */
EdgeTable ET; /* header node for ET */
EdgeTableEntry AET; /* header node for AET */
EdgeTableEntry *pETEs; /* EdgeTableEntries pool */
ScanLineListBlock SLLBlock; /* header for scanlinelist */
int fixWAET = FALSE;
POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
region = gdk_region_new ();
/* special case a rectangle */
pts = Pts;
if (((Count == 4) ||
((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) &&
(((pts[0].y == pts[1].y) &&
(pts[1].x == pts[2].x) &&
(pts[2].y == pts[3].y) &&
(pts[3].x == pts[0].x)) ||
((pts[0].x == pts[1].x) &&
(pts[1].y == pts[2].y) &&
(pts[2].x == pts[3].x) &&
(pts[3].y == pts[0].y)))) {
region->extents.x1 = MIN(pts[0].x, pts[2].x);
region->extents.y1 = MIN(pts[0].y, pts[2].y);
region->extents.x2 = MAX(pts[0].x, pts[2].x);
region->extents.y2 = MAX(pts[0].y, pts[2].y);
if ((region->extents.x1 != region->extents.x2) &&
(region->extents.y1 != region->extents.y2)) {
region->numRects = 1;
*(region->rects) = region->extents;
}
return(region);
}
pETEs = g_new (EdgeTableEntry, Count);
pts = FirstPtBlock.pts;
CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
pSLL = ET.scanlines.next;
curPtBlock = &FirstPtBlock;
if (rule == GDK_EVEN_ODD_RULE) {
/*
* for each scanline
*/
for (y = ET.ymin; y < ET.ymax; y++) {
/*
* Add a new edge to the active edge table when we
* get to the next edge.
*/
if (pSLL != NULL && y == pSLL->scanline) {
loadAET(&AET, pSLL->edgelist);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
/*
* for each active edge
*/
while (pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y;
pts++, iPts++;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++;
iPts = 0;
}
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
}
(void) InsertionSort(&AET);
}
}
else {
/*
* for each scanline
*/
for (y = ET.ymin; y < ET.ymax; y++) {
/*
* Add a new edge to the active edge table when we
* get to the next edge.
*/
if (pSLL != NULL && y == pSLL->scanline) {
loadAET(&AET, pSLL->edgelist);
computeWAET(&AET);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
pWETE = pAET;
/*
* for each active edge
*/
while (pAET) {
/*
* add to the buffer only those edges that
* are in the Winding active edge table.
*/
if (pWETE == pAET) {
pts->x = pAET->bres.minor_axis, pts->y = y;
pts++, iPts++;
/*
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
tmpPtBlock = (POINTBLOCK *)g_malloc(sizeof(POINTBLOCK));
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
pts = curPtBlock->pts;
numFullPtBlocks++; iPts = 0;
}
pWETE = pWETE->nextWETE;
}
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
}
/*
* recompute the winding active edge table if
* we just resorted or have exited an edge.
*/
if (InsertionSort(&AET) || fixWAET) {
computeWAET(&AET);
fixWAET = FALSE;
}
}
}
FreeStorage(SLLBlock.next);
(void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
tmpPtBlock = curPtBlock->next;
g_free (curPtBlock);
curPtBlock = tmpPtBlock;
}
g_free (pETEs);
return(region);
}

View File

@ -1,109 +1,42 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
/*
* Private uninstalled header defining things local to X windowing code
*/
#ifndef __GDK_PRIVATE_X11_H__
#define __GDK_PRIVATE_X11_H__
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <gdk/gdkfont.h>
#include <gdk/gdkprivate.h>
#include <gdk/gdkcursor.h>
typedef struct _GdkGCXData GdkGCXData;
typedef struct _GdkDrawableXData GdkDrawableXData;
typedef struct _GdkColormapPrivateX GdkColormapPrivateX;
typedef struct _GdkCursorPrivate GdkCursorPrivate;
typedef struct _GdkFontPrivateX GdkFontPrivateX;
typedef struct _GdkImagePrivateX GdkImagePrivateX;
typedef struct _GdkVisualPrivate GdkVisualPrivate;
typedef struct _GdkRegionPrivate GdkRegionPrivate;
#ifdef USE_XIM
typedef struct _GdkICPrivate GdkICPrivate;
#endif /* USE_XIM */
#define GDK_DRAWABLE_XDATA(win) ((GdkDrawableXData *)(((GdkDrawablePrivate*)(win))->klass_data))
#define GDK_GC_XDATA(gc) ((GdkGCXData *)(((GdkGCPrivate*)(gc))->klass_data))
struct _GdkGCXData
{
GC xgc;
Display *xdisplay;
};
struct _GdkDrawableXData
{
Window xid;
Display *xdisplay;
};
struct _GdkCursorPrivate
{
GdkCursor cursor;
Cursor xcursor;
Display *xdisplay;
};
struct _GdkFontPrivateX
{
GdkFontPrivate base;
/* XFontStruct *xfont; */
/* generic pointer point to XFontStruct or XFontSet */
gpointer xfont;
Display *xdisplay;
GSList *names;
};
struct _GdkVisualPrivate
{
GdkVisual visual;
Visual *xvisual;
};
struct _GdkColormapPrivateX
{
GdkColormapPrivate base;
Colormap xcolormap;
Display *xdisplay;
gint private_val;
GHashTable *hash;
GdkColorInfo *info;
time_t last_sync_time;
};
struct _GdkImagePrivateX
{
GdkImagePrivate base;
XImage *ximage;
Display *xdisplay;
gpointer x_shm_info;
};
struct _GdkRegionPrivate
{
GdkRegion region;
Region xregion;
};
#ifdef USE_XIM
struct _GdkICPrivate
{
XIC xic;
GdkICAttr *attr;
GdkICAttributesType mask;
};
#endif /* USE_XIM */
#include "gdkx.h"
void gdk_xid_table_insert (XID *xid,
gpointer data);
void gdk_xid_table_remove (XID xid);
gpointer gdk_xid_table_lookup (XID xid);
gint gdk_send_xevent (Window window,
gboolean propagate,
glong event_mask,
@ -114,6 +47,8 @@ GdkGC * _gdk_x11_gc_new (GdkDrawable *drawable,
GdkColormap * gdk_colormap_lookup (Colormap xcolormap);
GdkVisual * gdk_visual_lookup (Visual *xvisual);
void gdk_window_add_colormap_windows (GdkWindow *window);
/* Please see gdkwindow.c for comments on how to use */
Window gdk_window_xid_at (Window base,
gint bx,
@ -127,19 +62,25 @@ Window gdk_window_xid_at_coords (gint x,
GList *excludes,
gboolean excl_child);
/* Routines from gdkgeometry-x11.c */
void _gdk_window_init_position (GdkWindow *window);
void _gdk_window_move_resize_child (GdkWindow *window,
gint x,
gint y,
gint width,
gint height);
void _gdk_window_process_expose (GdkWindow *window,
gulong serial,
GdkRectangle *area);
extern GdkDrawableClass _gdk_x11_drawable_class;
extern gboolean gdk_use_xshm;
extern gchar *gdk_display_name;
extern Display *gdk_display;
extern Window gdk_root_window;
extern Window gdk_leader_window;
extern Atom gdk_wm_delete_window;
extern Atom gdk_wm_take_focus;
extern Atom gdk_wm_protocols;
extern Atom gdk_wm_window_protocols[];
extern Atom gdk_selection_property;
extern GdkWindow *selection_owner[];
extern gchar *gdk_progclass;
extern gboolean gdk_null_window_warnings;
extern const int gdk_nevent_masks;
extern const int gdk_event_mask_table[];
@ -156,3 +97,4 @@ extern GdkWindow *gdk_xim_window; /* currently using Window */
#endif /* __GDK_PRIVATE_X11_H__ */

1505
gdk/x11/gdkregion-generic.c Normal file

File diff suppressed because it is too large Load Diff

167
gdk/x11/gdkregion-generic.h Normal file
View File

@ -0,0 +1,167 @@
/* $TOG: region.h /main/9 1998/02/06 17:50:30 kaleb $ */
/************************************************************************
Copyright 1987, 1998 The Open Group
All Rights Reserved.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
************************************************************************/
#ifndef __GDK_REGION_GENERIC_H__
#define __GDK_REGION_GENERIC_H__
typedef struct _GdkRegionBox GdkRegionBox;
struct _GdkRegionBox
{
int x1, x2, y1, y2;
};
/*
* clip region
*/
struct _GdkRegion
{
long size;
long numRects;
GdkRegionBox *rects;
GdkRegionBox extents;
};
/* 1 if two BOXs overlap.
* 0 if two BOXs do not overlap.
* Remember, x2 and y2 are not in the region
*/
#define EXTENTCHECK(r1, r2) \
((r1)->x2 > (r2)->x1 && \
(r1)->x1 < (r2)->x2 && \
(r1)->y2 > (r2)->y1 && \
(r1)->y1 < (r2)->y2)
/*
* update region extents
*/
#define EXTENTS(r,idRect){\
if((r)->x1 < (idRect)->extents.x1)\
(idRect)->extents.x1 = (r)->x1;\
if((r)->y1 < (idRect)->extents.y1)\
(idRect)->extents.y1 = (r)->y1;\
if((r)->x2 > (idRect)->extents.x2)\
(idRect)->extents.x2 = (r)->x2;\
if((r)->y2 > (idRect)->extents.y2)\
(idRect)->extents.y2 = (r)->y2;\
}
/*
* Check to see if there is enough memory in the present region.
*/
#define MEMCHECK(reg, rect, firstrect){ \
if ((reg)->numRects >= ((reg)->size - 1)) { \
(firstrect) = g_renew (GdkRegionBox, (firstrect), 2 * (reg)->size); \
(reg)->size *= 2; \
(rect) = &(firstrect)[(reg)->numRects]; \
} \
}
/* this routine checks to see if the previous rectangle is the same
* or subsumes the new rectangle to add.
*/
#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\
(!(((Reg)->numRects > 0)&&\
((R-1)->y1 == (Ry1)) &&\
((R-1)->y2 == (Ry2)) &&\
((R-1)->x1 <= (Rx1)) &&\
((R-1)->x2 >= (Rx2))))
/* add a rectangle to the given Region */
#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\
if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
(r)->x1 = (rx1);\
(r)->y1 = (ry1);\
(r)->x2 = (rx2);\
(r)->y2 = (ry2);\
EXTENTS((r), (reg));\
(reg)->numRects++;\
(r)++;\
}\
}
/* add a rectangle to the given Region */
#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\
if ((rx1 < rx2) && (ry1 < ry2) &&\
CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\
(r)->x1 = (rx1);\
(r)->y1 = (ry1);\
(r)->x2 = (rx2);\
(r)->y2 = (ry2);\
(reg)->numRects++;\
(r)++;\
}\
}
#define EMPTY_REGION(pReg) pReg->numRects = 0
#define REGION_NOT_EMPTY(pReg) pReg->numRects
#define INBOX(r, x, y) \
( ( ((r).x2 > x)) && \
( ((r).x1 <= x)) && \
( ((r).y2 > y)) && \
( ((r).y1 <= y)) )
/*
* number of points to buffer before sending them off
* to scanlines() : Must be an even number
*/
#define NUMPTSTOBUFFER 200
/*
* used to allocate buffers for points and link
* the buffers together
*/
typedef struct _POINTBLOCK {
GdkPoint pts[NUMPTSTOBUFFER];
struct _POINTBLOCK *next;
} POINTBLOCK;
#endif /* __GDK_REGION_GENERIC_H__ */

View File

@ -89,19 +89,19 @@ void
gdk_region_get_clipbox(GdkRegion *region,
GdkRectangle *rectangle)
{
GdkRegionPrivate *rp;
XRectangle r;
g_return_if_fail(region != NULL);
g_return_if_fail(rectangle != NULL);
rp = (GdkRegionPrivate *)region;
XClipBox(rp->xregion, &r);
rectangle->x = r.x;
rectangle->y = r.y;
rectangle->width = r.width;
rectangle->height = r.height;
GdkRegionPrivate *rp;
XRectangle r;
g_return_if_fail(region != NULL);
g_return_if_fail(rectangle != NULL);
rp = (GdkRegionPrivate *)region;
XClipBox(rp->xregion, &r);
rectangle->x = r.x;
rectangle->y = r.y;
rectangle->width = r.width;
rectangle->height = r.height;
}
gboolean

View File

@ -31,7 +31,7 @@
#include "gdkproperty.h"
#include "gdkselection.h"
#include "gdkprivate.h"
#include "gdkx.h"
#include "gdkprivate-x11.h"
gboolean

View File

@ -29,6 +29,7 @@
#include "gdkvisual.h"
#include "gdkprivate-x11.h"
#include "gdkinternals.h"
static void gdk_visual_add (GdkVisual *visual);
static void gdk_visual_decompose_mask (gulong mask,

View File

@ -34,7 +34,7 @@
#include "gdkwindow.h"
#include "gdkinputprivate.h"
#include "gdkprivate-x11.h"
#include "gdkx.h"
#include "gdkinternals.h"
#include "MwmUtil.h"
#include <stdlib.h>
@ -78,6 +78,8 @@ static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on);
static gboolean gdk_window_have_shape_ext (void);
GdkDrawableClass _gdk_windowing_window_class;
static void
gdk_x11_window_destroy (GdkDrawable *drawable)
{
@ -98,22 +100,21 @@ gdk_x11_window_alloc (void)
GdkWindow *window;
GdkWindowPrivate *private;
static GdkDrawableClass klass;
static gboolean initialized = FALSE;
if (!initialized)
{
initialized = TRUE;
klass = _gdk_x11_drawable_class;
klass.destroy = gdk_x11_window_destroy;
_gdk_windowing_window_class = _gdk_x11_drawable_class;
_gdk_windowing_window_class.destroy = gdk_x11_window_destroy;
}
window = _gdk_window_alloc ();
private = (GdkWindowPrivate *)window;
private->drawable.klass = &klass;
private->drawable.klass_data = g_new (GdkDrawableXData, 1);
private->drawable.klass = &_gdk_window_class;
private->drawable.klass_data = g_new (GdkWindowXData, 1);
return window;
}
@ -207,6 +208,10 @@ gdk_window_new (GdkWindow *parent,
private->drawable.width = (attributes->width > 1) ? (attributes->width) : (1);
private->drawable.height = (attributes->height > 1) ? (attributes->height) : (1);
private->drawable.window_type = attributes->window_type;
_gdk_window_init_position (window);
if (GDK_WINDOW_XDATA (window)->position_info.big)
private->guffaw_gravity = TRUE;
if (attributes_mask & GDK_WA_VISUAL)
visual = attributes->visual;
@ -232,7 +237,7 @@ gdk_window_new (GdkWindow *parent,
}
else
xattributes.override_redirect = False;
if (parent_private && parent_private->guffaw_gravity)
{
xattributes.win_gravity = StaticGravity;
@ -243,6 +248,9 @@ gdk_window_new (GdkWindow *parent,
{
class = InputOutput;
depth = visual->depth;
private->input_only = FALSE;
private->drawable.depth = depth;
if (attributes_mask & GDK_WA_COLORMAP)
private->drawable.colormap = attributes->colormap;
@ -254,10 +262,21 @@ gdk_window_new (GdkWindow *parent,
private->drawable.colormap = gdk_colormap_new (visual, False);
}
xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
private->bg_color.pixel = BlackPixel (gdk_display, gdk_screen);
xattributes.background_pixel = private->bg_color.pixel;
private->bg_pixmap = NULL;
xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
xattributes_mask |= CWBorderPixel | CWBackPixel;
if (private->guffaw_gravity)
xattributes.bit_gravity = StaticGravity;
else
xattributes.bit_gravity = NorthWestGravity;
xattributes_mask |= CWBitGravity;
switch (private->drawable.window_type)
{
case GDK_WINDOW_TOPLEVEL:
@ -302,6 +321,7 @@ gdk_window_new (GdkWindow *parent,
{
depth = 0;
class = InputOnly;
private->input_only = TRUE;
private->drawable.colormap = NULL;
}
@ -443,7 +463,7 @@ gdk_window_foreign_new (guint32 anid)
parent_private->children = g_list_prepend (parent_private->children, window);
GDK_DRAWABLE_XDATA (window)->xid = anid;
GDK_DRAWABLE_XDATA (window)->xdisplay = GDK_DRAWABLE_XDISPLAY (parent);
GDK_DRAWABLE_XDATA (window)->xdisplay = GDK_DRAWABLE_XDISPLAY (private->parent);
private->x = attrs.x;
private->y = attrs.y;
@ -495,6 +515,12 @@ gdk_window_internal_destroy (GdkWindow *window,
if (parent_private->children)
parent_private->children = g_list_remove (parent_private->children, window);
}
if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG)
{
gdk_pixmap_unref (private->bg_pixmap);
private->bg_pixmap = NULL;
}
if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_FOREIGN)
{
@ -624,8 +650,10 @@ gdk_window_show (GdkWindow *window)
private->mapped = TRUE;
XRaiseWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window));
XMapWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window));
if (GDK_WINDOW_XDATA (window)->position_info.mapped)
XMapWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window));
}
}
@ -663,23 +691,13 @@ gdk_window_move (GdkWindow *window,
gint x,
gint y)
{
GdkWindowPrivate *private;
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->drawable.destroyed)
{
XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
x, y);
if (private->drawable.window_type == GDK_WINDOW_CHILD)
{
private->x = x;
private->y = y;
}
}
g_return_if_fail (GDK_IS_WINDOW (window));
gdk_window_move_resize (window, x, y,
private->drawable.width, private->drawable.height);
}
void
@ -699,20 +717,17 @@ gdk_window_resize (GdkWindow *window,
private = (GdkWindowPrivate*) window;
if (!private->drawable.destroyed &&
((private->resize_count > 0) ||
(private->drawable.width != (guint16) width) ||
(private->drawable.height != (guint16) height)))
if (!GDK_DRAWABLE_DESTROYED (window))
{
XResizeWindow (GDK_DRAWABLE_XDISPLAY (private),
GDK_DRAWABLE_XID (private),
width, height);
private->resize_count += 1;
if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
_gdk_window_move_resize_child (window, private->x, private->y,
width, height);
else
{
private->drawable.width = width;
private->drawable.height = height;
XResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
width, height);
private->resize_count += 1;
}
}
}
@ -738,30 +753,13 @@ gdk_window_move_resize (GdkWindow *window,
if (!GDK_DRAWABLE_DESTROYED (window))
{
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
x, y, width, height);
if (private->guffaw_gravity)
{
GList *tmp_list = private->children;
while (tmp_list)
{
GdkWindowPrivate *child_private = tmp_list->data;
child_private->x -= x - private->x;
child_private->y -= y - private->y;
tmp_list = tmp_list->next;
}
}
if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
_gdk_window_move_resize_child (window, x, y, width, height);
else
{
private->x = x;
private->y = y;
private->drawable.width = width;
private->drawable.height = height;
XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),
x, y, width, height);
}
}
}
@ -818,11 +816,11 @@ gdk_window_clear (GdkWindow *window)
}
void
gdk_window_clear_area (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
_gdk_windowing_window_clear_area (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
@ -833,11 +831,11 @@ gdk_window_clear_area (GdkWindow *window,
}
void
gdk_window_clear_area_e (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
_gdk_windowing_window_clear_area_e (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
@ -1058,12 +1056,24 @@ void
gdk_window_set_background (GdkWindow *window,
GdkColor *color)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (!GDK_DRAWABLE_DESTROYED (window))
XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window), color->pixel);
private->bg_color = *color;
if (private->bg_pixmap &&
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
private->bg_pixmap != GDK_NO_BG)
{
gdk_pixmap_unref (private->bg_pixmap);
private->bg_pixmap = NULL;
}
}
void
@ -1071,18 +1081,37 @@ gdk_window_set_back_pixmap (GdkWindow *window,
GdkPixmap *pixmap,
gboolean parent_relative)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
Pixmap xpixmap;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (pixmap)
xpixmap = GDK_DRAWABLE_XID (pixmap);
else
xpixmap = None;
g_return_if_fail (pixmap == NULL || !parent_relative);
if (private->bg_pixmap &&
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
private->bg_pixmap != GDK_NO_BG)
gdk_pixmap_unref (private->bg_pixmap);
if (parent_relative)
xpixmap = ParentRelative;
{
xpixmap = ParentRelative;
private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
}
else
{
if (pixmap)
{
gdk_pixmap_ref (pixmap);
private->bg_pixmap = pixmap;
xpixmap = GDK_DRAWABLE_XID (pixmap);
}
else
{
xpixmap = None;
private->bg_pixmap = GDK_NO_BG;
}
}
if (!GDK_DRAWABLE_DESTROYED (window))
XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
@ -2181,9 +2210,12 @@ static void
gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
{
XSetWindowAttributes xattributes;
guint xattributes_mask = 0;
g_return_if_fail (window != NULL);
xattributes.bit_gravity = StaticGravity;
xattributes_mask |= CWBitGravity;
xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
XChangeWindowAttributes (GDK_DRAWABLE_XDISPLAY (window),
GDK_DRAWABLE_XID (window),

View File

@ -27,26 +27,153 @@
#ifndef __GDK_X_H__
#define __GDK_X_H__
#include <gdk/x11/gdkprivate-x11.h>
#include <gdk/gdkprivate.h>
#include <gdk/gdkcursor.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef struct _GdkGCXData GdkGCXData;
typedef struct _GdkDrawableXData GdkDrawableXData;
typedef struct _GdkWindowXData GdkWindowXData;
typedef struct _GdkXPositionInfo GdkXPositionInfo;
typedef struct _GdkColormapPrivateX GdkColormapPrivateX;
typedef struct _GdkCursorPrivate GdkCursorPrivate;
typedef struct _GdkFontPrivateX GdkFontPrivateX;
typedef struct _GdkImagePrivateX GdkImagePrivateX;
typedef struct _GdkVisualPrivate GdkVisualPrivate;
#ifdef USE_XIM
typedef struct _GdkICPrivate GdkICPrivate;
#endif /* USE_XIM */
#define GDK_DRAWABLE_XDATA(win) ((GdkDrawableXData *)(((GdkDrawablePrivate*)(win))->klass_data))
#define GDK_WINDOW_XDATA(win) ((GdkWindowXData *)(((GdkDrawablePrivate*)(win))->klass_data))
#define GDK_GC_XDATA(gc) ((GdkGCXData *)(((GdkGCPrivate*)(gc))->klass_data))
struct _GdkGCXData
{
GC xgc;
Display *xdisplay;
GdkRegion *clip_region;
guint dirty_mask;
};
struct _GdkDrawableXData
{
Window xid;
Display *xdisplay;
};
struct _GdkXPositionInfo
{
gint x;
gint y;
gint width;
gint height;
gint x_offset; /* Offsets to add to X coordinates within window */
gint y_offset; /* to get GDK coodinates within window */
gboolean big : 1;
gboolean mapped : 1;
gboolean no_bg : 1; /* Set when the window background is temporarily
* unset during resizing and scaling */
GdkRectangle clip_rect; /* visible rectangle of window */
};
struct _GdkWindowXData
{
GdkDrawableXData drawable_data;
GdkXPositionInfo position_info;
};
struct _GdkCursorPrivate
{
GdkCursor cursor;
Cursor xcursor;
Display *xdisplay;
};
struct _GdkFontPrivateX
{
GdkFontPrivate base;
/* XFontStruct *xfont; */
/* generic pointer point to XFontStruct or XFontSet */
gpointer xfont;
Display *xdisplay;
GSList *names;
};
struct _GdkVisualPrivate
{
GdkVisual visual;
Visual *xvisual;
};
struct _GdkColormapPrivateX
{
GdkColormapPrivate base;
Colormap xcolormap;
Display *xdisplay;
gint private_val;
GHashTable *hash;
GdkColorInfo *info;
time_t last_sync_time;
};
struct _GdkImagePrivateX
{
GdkImagePrivate base;
XImage *ximage;
Display *xdisplay;
gpointer x_shm_info;
};
#ifdef USE_XIM
struct _GdkICPrivate
{
XIC xic;
GdkICAttr *attr;
GdkICAttributesType mask;
};
#endif /* USE_XIM */
#define GDK_ROOT_WINDOW() gdk_root_window
#define GDK_ROOT_PARENT() ((GdkWindow *)&gdk_parent_root)
#define GDK_ROOT_PARENT() ((GdkWindow *)gdk_parent_root)
#define GDK_DISPLAY() gdk_display
#define GDK_DRAWABLE_XDISPLAY(win) (GDK_DRAWABLE_XDATA(win)->xdisplay)
#define GDK_DRAWABLE_XID(win) (GDK_DRAWABLE_XDATA(win)->xid)
#define GDK_IMAGE_XDISPLAY(image) (((GdkImagePrivate*) image)->xdisplay)
#define GDK_IMAGE_XIMAGE(image) (((GdkImagePrivate*) image)->ximage)
#define GDK_GC_XDISPLAY(gc) (GDK_GC_XDATA(gc)->xdisplay)
#define GDK_GC_XGC(gc) (GDK_GC_XDATA(gc)->xgc)
#define GDK_COLORMAP_XDISPLAY(cmap) (((GdkColormapPrivateX *)cmap)->xdisplay)
#define GDK_COLORMAP_XCOLORMAP(cmap) (((GdkColormapPrivateX *)cmap)->xcolormap)
#define GDK_VISUAL_XVISUAL(vis) (((GdkVisualPrivate*) vis)->xvisual)
#define GDK_FONT_XDISPLAY(font) (((GdkFontPrivate*) font)->xdisplay)
#define GDK_FONT_XFONT(font) (((GdkFontPrivateX *)font)->xfont)
#define GDK_GC_XGC(gc) (GDK_GC_XDATA(gc)->xgc)
#define GDK_GC_GET_XGC(gc) (GDK_GC_XDATA(gc)->dirty_mask ? _gdk_x11_gc_flush (gc) : GDK_GC_XGC (gc))
#define GDK_WINDOW_XWINDOW GDK_DRAWABLE_XID
#define GDK_WINDOW_XDISPLAY GDK_DRAWABLE_XDISPLAY
extern Display *gdk_display;
extern Window gdk_root_window;
extern gint gdk_screen;
extern gchar *gdk_display_name;
extern Window gdk_leader_window;
extern Atom gdk_selection_property;
extern gchar *gdk_progclass;
GdkVisual* gdkx_visual_get (VisualID xvisualid);
/* XXX: Do not use this function until it is fixed. An X Colormap
* is useless unless we also have the visual. */
@ -60,4 +187,9 @@ Window gdk_get_client_window (Display *dpy,
GdkPixmap *gdk_pixmap_foreign_new (guint32 anid);
GdkWindow *gdk_window_foreign_new (guint32 anid);
/* Return the Gdk* for a particular XID */
gpointer gdk_xid_table_lookup (XID xid);
GC _gdk_x11_gc_flush (GdkGC *gc);
#endif /* __GDK_X_H__ */

View File

@ -14,6 +14,7 @@ testtree
gtkcompat.h
testthreads
libgtk.la
gtkfeatures.h
gtkmarshal.h
gtktypebuiltins.h
gtkmarshal.c

View File

@ -288,6 +288,7 @@ gtk_built_sources = @STRIP_BEGIN@ \
@STRIP_END@
# built sources that get installed with the header files
gtk_built_public_sources = @STRIP_BEGIN@ \
gtkcompat.h \
gtkmarshal.h \
gtktypebuiltins.h \
@STRIP_END@

View File

@ -238,9 +238,6 @@ gtk_aspect_frame_set (GtkAspectFrame *aspect_frame,
aspect_frame->ratio = ratio;
aspect_frame->obey_child = obey_child;
if (GTK_WIDGET_DRAWABLE(widget))
gtk_widget_queue_clear (widget);
gtk_widget_queue_resize (widget);
}
}

View File

@ -147,9 +147,7 @@ gtk_bin_unmap (GtkWidget *widget)
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
bin = GTK_BIN (widget);
if (GTK_WIDGET_NO_WINDOW (widget))
gtk_widget_queue_clear (widget);
else
if (!GTK_WIDGET_NO_WINDOW (widget))
gdk_window_hide (widget->window);
if (bin->child && GTK_WIDGET_MAPPED (bin->child))

View File

@ -847,8 +847,10 @@ gtk_container_idle_sizer (gpointer data)
gtk_container_check_resize (GTK_CONTAINER (widget));
}
gdk_window_process_all_updates ();
GDK_THREADS_LEAVE ();
return FALSE;
}

View File

@ -826,14 +826,25 @@ static void
gtk_entry_draw (GtkWidget *widget,
GdkRectangle *area)
{
GtkEntry *entry;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_ENTRY (widget));
g_return_if_fail (area != NULL);
entry = GTK_ENTRY (widget);
if (GTK_WIDGET_DRAWABLE (widget))
{
GdkRectangle tmp_area = *area;
tmp_area.x -= widget->style->klass->xthickness;
tmp_area.y -= widget->style->klass->xthickness;
gdk_window_begin_paint_rect (entry->text_area, &tmp_area);
gtk_widget_draw_focus (widget);
gtk_entry_draw_text (GTK_ENTRY (widget));
gdk_window_end_paint (entry->text_area);
}
}
@ -1295,7 +1306,6 @@ gtk_entry_draw_text (GtkEntry *entry)
gint width, height;
gint y;
GdkDrawable *drawable;
gint use_backing_pixmap;
GdkWChar *stars;
GdkWChar *toprint;
@ -1327,25 +1337,10 @@ gtk_entry_draw_text (GtkEntry *entry)
gdk_window_get_size (entry->text_area, &width, &height);
/*
If the widget has focus, draw on a backing pixmap to avoid flickering
and copy it to the text_area.
Otherwise draw to text_area directly for better speed.
*/
use_backing_pixmap = GTK_WIDGET_HAS_FOCUS (widget) && (entry->text != NULL);
if (use_backing_pixmap)
{
gtk_entry_make_backing_pixmap (entry, width, height);
drawable = entry->backing_pixmap;
}
else
{
drawable = entry->text_area;
}
gtk_paint_flat_box (widget->style, drawable,
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
NULL, widget, "entry_bg",
0, 0, width, height);
gtk_paint_flat_box (widget->style, entry->text_area,
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
NULL, widget, "entry_bg",
0, 0, width, height);
y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
y += widget->style->font->ascent;
@ -1388,7 +1383,7 @@ gtk_entry_draw_text (GtkEntry *entry)
}
if (selection_start_pos > start_pos)
gdk_draw_text_wc (drawable, widget->style->font,
gdk_draw_text_wc (entry->text_area, widget->style->font,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
INNER_BORDER + start_xoffset, y,
toprint,
@ -1398,14 +1393,14 @@ gtk_entry_draw_text (GtkEntry *entry)
(selection_start_pos < end_pos) &&
(selection_start_pos != selection_end_pos))
{
gtk_paint_flat_box (widget->style, drawable,
gtk_paint_flat_box (widget->style, entry->text_area,
selected_state, GTK_SHADOW_NONE,
NULL, widget, "text",
INNER_BORDER + selection_start_xoffset,
INNER_BORDER,
selection_end_xoffset - selection_start_xoffset,
height - 2*INNER_BORDER);
gdk_draw_text_wc (drawable, widget->style->font,
gdk_draw_text_wc (entry->text_area, widget->style->font,
widget->style->fg_gc[selected_state],
INNER_BORDER + selection_start_xoffset, y,
toprint + selection_start_pos - start_pos,
@ -1413,7 +1408,7 @@ gtk_entry_draw_text (GtkEntry *entry)
}
if (selection_end_pos < end_pos)
gdk_draw_text_wc (drawable, widget->style->font,
gdk_draw_text_wc (entry->text_area, widget->style->font,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
INNER_BORDER + selection_end_xoffset, y,
toprint + selection_end_pos - start_pos,
@ -1423,13 +1418,7 @@ gtk_entry_draw_text (GtkEntry *entry)
g_free (toprint);
if (editable->editable)
gtk_entry_draw_cursor_on_drawable (entry, drawable);
if (use_backing_pixmap)
gdk_draw_pixmap(entry->text_area,
widget->style->fg_gc[GTK_STATE_NORMAL],
entry->backing_pixmap,
0, 0, 0, 0, width, height);
gtk_entry_draw_cursor_on_drawable (entry, entry->text_area);
}
}
@ -1472,16 +1461,26 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
}
else
{
int width, height;
GdkRectangle area;
gint yoffset =
(text_area_height -
(widget->style->font->ascent + widget->style->font->descent)) / 2
+ widget->style->font->ascent;
area.x = xoffset;
area.y = INNER_BORDER;
area.width = 1;
area.height = text_area_height - INNER_BORDER;
gdk_window_get_size (entry->text_area, &width, &height);
gtk_paint_flat_box (widget->style, drawable,
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
NULL, widget, "entry_bg",
xoffset, INNER_BORDER,
1, text_area_height - INNER_BORDER);
&area, widget, "entry_bg",
0, 0, width, height);
/* Draw the character under the cursor again
*/

View File

@ -289,9 +289,6 @@ gtk_hscrollbar_size_allocate (GtkWidget *widget,
widget->style->klass->ythickness,
RANGE_CLASS (widget)->stepper_size,
widget->requisition.height - widget->style->klass->ythickness * 2);
gdk_window_resize (range->slider,
RANGE_CLASS (widget)->min_slider_size,
widget->requisition.height - widget->style->klass->ythickness * 2);
gtk_range_slider_update (GTK_RANGE (widget));
}

View File

@ -30,33 +30,18 @@
#include "gdkconfig.h"
#if defined (GDK_WINDOWING_X11)
#include "x11/gdkx.h"
#elif defined (GDK_WINDOWING_WIN32)
#include "win32/gdkwin32.h"
#endif
#include "gtklayout.h"
#include "gtksignal.h"
#include "gtkprivate.h"
typedef struct _GtkLayoutAdjData GtkLayoutAdjData;
typedef struct _GtkLayoutChild GtkLayoutChild;
struct _GtkLayoutAdjData {
gint dx;
gint dy;
};
struct _GtkLayoutChild {
GtkWidget *widget;
gint x;
gint y;
};
#define IS_ONSCREEN(x,y) ((x >= G_MINSHORT) && (x <= G_MAXSHORT) && \
(y >= G_MINSHORT) && (y <= G_MAXSHORT))
static void gtk_layout_class_init (GtkLayoutClass *class);
static void gtk_layout_init (GtkLayout *layout);
@ -83,33 +68,14 @@ static void gtk_layout_set_adjustments (GtkLayout *layout,
GtkAdjustment *hadj,
GtkAdjustment *vadj);
static void gtk_layout_position_child (GtkLayout *layout,
GtkLayoutChild *child);
static void gtk_layout_allocate_child (GtkLayout *layout,
GtkLayoutChild *child);
static void gtk_layout_position_children (GtkLayout *layout);
static void gtk_layout_adjust_allocations_recurse (GtkWidget *widget,
gpointer cb_data);
static void gtk_layout_adjust_allocations (GtkLayout *layout,
gint dx,
gint dy);
static void gtk_layout_expose_area (GtkLayout *layout,
gint x,
gint y,
gint width,
gint height);
static void gtk_layout_adjustment_changed (GtkAdjustment *adjustment,
GtkLayout *layout);
static GdkFilterReturn gtk_layout_main_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data);
static GtkWidgetClass *parent_class = NULL;
static gboolean gravity_works;
/* Public interface
*/
@ -261,9 +227,6 @@ gtk_layout_put (GtkLayout *layout,
if (GTK_WIDGET_REALIZED (layout))
gtk_widget_set_parent_window (child->widget, layout->bin_window);
if (!IS_ONSCREEN (x, y))
GTK_PRIVATE_SET_FLAG (child_widget, GTK_IS_OFFSCREEN);
if (GTK_WIDGET_REALIZED (layout))
gtk_widget_realize (child_widget);
@ -323,6 +286,9 @@ gtk_layout_set_size (GtkLayout *layout,
layout->vadjustment->upper = layout->height;
gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed");
if (GTK_WIDGET_REALIZED (layout))
gdk_window_resize (layout->bin_window, width, height);
}
void
@ -342,10 +308,7 @@ gtk_layout_thaw (GtkLayout *layout)
if (layout->freeze_count)
if (!(--layout->freeze_count))
{
gtk_layout_position_children (layout);
gtk_widget_draw (GTK_WIDGET (layout), NULL);
}
gtk_widget_draw (GTK_WIDGET (layout), NULL);
}
/* Basic Object handling procedures
@ -467,7 +430,9 @@ gtk_layout_realize (GtkWidget *widget)
attributes.x = 0;
attributes.y = 0;
attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK |
attributes.width = layout->width;
attributes.height = layout->height;
attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK |
gtk_widget_get_events (widget);
layout->bin_window = gdk_window_new (widget->window,
@ -478,15 +443,6 @@ gtk_layout_realize (GtkWidget *widget)
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
gtk_style_set_background (widget->style, layout->bin_window, GTK_STATE_NORMAL);
gdk_window_add_filter (widget->window, gtk_layout_main_filter, layout);
/* gdk_window_add_filter (layout->bin_window, gtk_layout_filter, layout);*/
/* XXX: If we ever get multiple displays for GTK+, then gravity_works
* will have to become a widget member. Right now we just
* keep it as a global
*/
gravity_works = gdk_window_set_static_gravities (layout->bin_window, TRUE);
tmp_list = layout->children;
while (tmp_list)
{
@ -595,7 +551,6 @@ gtk_layout_size_allocate (GtkWidget *widget,
GtkLayoutChild *child = tmp_list->data;
tmp_list = tmp_list->next;
gtk_layout_position_child (layout, child);
gtk_layout_allocate_child (layout, child);
}
@ -604,9 +559,6 @@ gtk_layout_size_allocate (GtkWidget *widget,
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
gdk_window_move_resize (GTK_LAYOUT(widget)->bin_window,
0, 0,
allocation->width, allocation->height);
}
layout->hadjustment->page_size = allocation->width;
@ -748,38 +700,6 @@ gtk_layout_forall (GtkContainer *container,
/* Operations on children
*/
static void
gtk_layout_position_child (GtkLayout *layout,
GtkLayoutChild *child)
{
gint x;
gint y;
x = child->x - layout->xoffset;
y = child->y - layout->yoffset;
if (IS_ONSCREEN (x,y))
{
if (GTK_WIDGET_MAPPED (layout) &&
GTK_WIDGET_VISIBLE (child->widget))
{
if (!GTK_WIDGET_MAPPED (child->widget))
gtk_widget_map (child->widget);
}
if (GTK_WIDGET_IS_OFFSCREEN (child->widget))
GTK_PRIVATE_UNSET_FLAG (child->widget, GTK_IS_OFFSCREEN);
}
else
{
if (!GTK_WIDGET_IS_OFFSCREEN (child->widget))
GTK_PRIVATE_SET_FLAG (child->widget, GTK_IS_OFFSCREEN);
if (GTK_WIDGET_MAPPED (child->widget))
gtk_widget_unmap (child->widget);
}
}
static void
gtk_layout_allocate_child (GtkLayout *layout,
GtkLayoutChild *child)
@ -796,451 +716,25 @@ gtk_layout_allocate_child (GtkLayout *layout,
gtk_widget_size_allocate (child->widget, &allocation);
}
static void
gtk_layout_position_children (GtkLayout *layout)
{
GList *tmp_list;
tmp_list = layout->children;
while (tmp_list)
{
GtkLayoutChild *child = tmp_list->data;
tmp_list = tmp_list->next;
gtk_layout_position_child (layout, child);
}
}
static void
gtk_layout_adjust_allocations_recurse (GtkWidget *widget,
gpointer cb_data)
{
GtkLayoutAdjData *data = cb_data;
widget->allocation.x += data->dx;
widget->allocation.y += data->dy;
if (GTK_WIDGET_NO_WINDOW (widget) &&
GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget),
gtk_layout_adjust_allocations_recurse,
cb_data);
}
static void
gtk_layout_adjust_allocations (GtkLayout *layout,
gint dx,
gint dy)
{
GList *tmp_list;
GtkLayoutAdjData data;
data.dx = dx;
data.dy = dy;
tmp_list = layout->children;
while (tmp_list)
{
GtkLayoutChild *child = tmp_list->data;
tmp_list = tmp_list->next;
child->widget->allocation.x += dx;
child->widget->allocation.y += dy;
if (GTK_WIDGET_NO_WINDOW (child->widget) &&
GTK_IS_CONTAINER (child->widget))
gtk_container_forall (GTK_CONTAINER (child->widget),
gtk_layout_adjust_allocations_recurse,
&data);
}
}
/* Callbacks */
/* Send a synthetic expose event to the widget
*/
static void
gtk_layout_expose_area (GtkLayout *layout,
gint x, gint y, gint width, gint height)
{
if (layout->visibility == GDK_VISIBILITY_UNOBSCURED)
{
GdkEventExpose event;
event.type = GDK_EXPOSE;
event.send_event = TRUE;
event.window = layout->bin_window;
event.count = 0;
event.area.x = x;
event.area.y = y;
event.area.width = width;
event.area.height = height;
gdk_window_ref (event.window);
gtk_widget_event (GTK_WIDGET (layout), (GdkEvent *)&event);
gdk_window_unref (event.window);
}
}
#ifdef GDK_WINDOWING_X11
/* This function is used to find events to process while scrolling
*/
static Bool
gtk_layout_expose_predicate (Display *display,
XEvent *xevent,
XPointer arg)
{
if ((xevent->type == Expose) ||
((xevent->xany.window == *(Window *)arg) &&
(xevent->type == ConfigureNotify)))
return True;
else
return False;
}
#endif /* X11 */
/* This is the main routine to do the scrolling. Scrolling is
* done by "Guffaw" scrolling, as in the Mozilla XFE, with
* a few modifications.
*
* The main improvement is that we keep track of whether we
* are obscured or not. If not, we ignore the generated expose
* events and instead do the exposes ourself, without having
* to wait for a roundtrip to the server. This also provides
* a limited form of expose-event compression, since we do
* the affected area as one big chunk.
*
* Real expose event compression, as in the XFE, could be added
* here. It would help opaque drags over the region, and the
* obscured case.
*
* Code needs to be added here to do the scrolling on machines
* that don't have working WindowGravity. That could be done
*
* - XCopyArea and move the windows, and accept trailing the
* background color. (Since it is only a fallback method)
* - XmHTML style. As above, but turn off expose events when
* not obscured and do the exposures ourself.
* - gzilla-style. Move the window continuously, and reset
* every 32768 pixels
*/
static void
gtk_layout_adjustment_changed (GtkAdjustment *adjustment,
GtkLayout *layout)
{
GtkWidget *widget;
#ifdef GDK_WINDOWING_X11
XEvent xevent;
#endif
gint dx, dy;
widget = GTK_WIDGET (layout);
dx = (gint)layout->hadjustment->value - layout->xoffset;
dy = (gint)layout->vadjustment->value - layout->yoffset;
layout->xoffset = (gint)layout->hadjustment->value;
layout->yoffset = (gint)layout->vadjustment->value;
if (layout->freeze_count)
return;
if (!GTK_WIDGET_MAPPED (layout))
if (GTK_WIDGET_REALIZED (layout))
{
gtk_layout_position_children (layout);
return;
}
gtk_layout_adjust_allocations (layout, -dx, -dy);
if (dx > 0)
{
if (gravity_works)
{
gdk_window_resize (layout->bin_window,
widget->allocation.width + dx,
widget->allocation.height);
gdk_window_move (layout->bin_window, -dx, 0);
gdk_window_move_resize (layout->bin_window,
0, 0,
widget->allocation.width,
widget->allocation.height);
}
else
{
/* FIXME */
}
gtk_layout_expose_area (layout,
MAX ((gint)widget->allocation.width - dx, 0),
0,
MIN (dx, widget->allocation.width),
widget->allocation.height);
}
else if (dx < 0)
{
if (gravity_works)
{
gdk_window_move_resize (layout->bin_window,
dx, 0,
widget->allocation.width - dx,
widget->allocation.height);
gdk_window_move (layout->bin_window, 0, 0);
gdk_window_resize (layout->bin_window,
widget->allocation.width,
widget->allocation.height);
}
else
{
/* FIXME */
}
gtk_layout_expose_area (layout,
0,
0,
MIN (-dx, widget->allocation.width),
widget->allocation.height);
}
if (dy > 0)
{
if (gravity_works)
{
gdk_window_resize (layout->bin_window,
widget->allocation.width,
widget->allocation.height + dy);
gdk_window_move (layout->bin_window, 0, -dy);
gdk_window_move_resize (layout->bin_window,
0, 0,
widget->allocation.width,
widget->allocation.height);
}
else
{
/* FIXME */
}
gtk_layout_expose_area (layout,
0,
MAX ((gint)widget->allocation.height - dy, 0),
widget->allocation.width,
MIN (dy, widget->allocation.height));
}
else if (dy < 0)
{
if (gravity_works)
{
gdk_window_move_resize (layout->bin_window,
0, dy,
widget->allocation.width,
widget->allocation.height - dy);
gdk_window_move (layout->bin_window, 0, 0);
gdk_window_resize (layout->bin_window,
widget->allocation.width,
widget->allocation.height);
}
else
{
/* FIXME */
}
gtk_layout_expose_area (layout,
0,
0,
widget->allocation.width,
MIN (-dy, (gint)widget->allocation.height));
}
gtk_layout_position_children (layout);
/* We have to make sure that all exposes from this scroll get
* processed before we scroll again, or the expose events will
* have invalid coordinates.
*
* We also do expose events for other windows, since otherwise
* their updating will fall behind the scrolling
*
* This also avoids a problem in pre-1.0 GTK where filters don't
* have access to configure events that were compressed.
*/
gdk_flush();
#ifdef GDK_WINDOWING_X11
while (XCheckIfEvent(GDK_WINDOW_XDISPLAY (layout->bin_window),
&xevent,
gtk_layout_expose_predicate,
(XPointer)&GDK_WINDOW_XWINDOW (layout->bin_window)))
{
GdkEvent event;
GtkWidget *event_widget;
switch (xevent.type)
{
case Expose:
if (xevent.xany.window == GDK_WINDOW_XWINDOW (layout->bin_window))
{
/* If the window is unobscured, then we've exposed the
* regions with the following serials already, so we
* can throw out the expose events.
*/
if (layout->visibility == GDK_VISIBILITY_UNOBSCURED &&
(((dx > 0 || dy > 0) &&
xevent.xexpose.serial == layout->configure_serial) ||
((dx < 0 || dy < 0) &&
xevent.xexpose.serial == layout->configure_serial + 1)))
continue;
/* The following expose was generated while the origin was
* different from the current origin, so we need to offset it.
*/
else if (xevent.xexpose.serial == layout->configure_serial)
{
xevent.xexpose.x += layout->scroll_x;
xevent.xexpose.y += layout->scroll_y;
}
event.expose.window = layout->bin_window;
event_widget = widget;
}
else
{
event.expose.window = gdk_window_lookup (xevent.xany.window);
gdk_window_get_user_data (event.expose.window,
(gpointer *)&event_widget);
}
if (event_widget)
{
event.expose.type = GDK_EXPOSE;
event.expose.area.x = xevent.xexpose.x;
event.expose.area.y = xevent.xexpose.y;
event.expose.area.width = xevent.xexpose.width;
event.expose.area.height = xevent.xexpose.height;
event.expose.count = xevent.xexpose.count;
gdk_window_ref (event.expose.window);
gtk_widget_event (event_widget, &event);
gdk_window_unref (event.expose.window);
}
break;
case ConfigureNotify:
if (xevent.xany.window == GDK_WINDOW_XWINDOW (layout->bin_window) &&
(xevent.xconfigure.x != 0 || xevent.xconfigure.y != 0))
{
layout->configure_serial = xevent.xconfigure.serial;
layout->scroll_x = xevent.xconfigure.x;
layout->scroll_y = xevent.xconfigure.y;
}
break;
}
}
#elif defined (GDK_WINDOWING_WIN32)
/* XXX Not implemented */
#endif
}
#if 0
/* The main event filter. Actually, we probably don't really need
* this filter at all, since we are calling it directly above in the
* expose-handling hack. But in case scrollbars
* are fixed up in some manner...
*
* This routine identifies expose events that are generated when
* we've temporarily moved the bin_window_origin, and translates
* them or discards them, depending on whether we are obscured
* or not.
*/
static GdkFilterReturn
gtk_layout_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data)
{
#ifdef GDK_WINDOWING_X11
XEvent *xevent;
GtkLayout *layout;
xevent = (XEvent *)gdk_xevent;
layout = GTK_LAYOUT (data);
switch (xevent->type)
{
case Expose:
if (xevent->xexpose.serial == layout->configure_serial)
{
if (layout->visibility == GDK_VISIBILITY_UNOBSCURED)
return GDK_FILTER_REMOVE;
else
{
xevent->xexpose.x += layout->scroll_x;
xevent->xexpose.y += layout->scroll_y;
break;
}
}
break;
gdk_window_move (layout->bin_window,
- layout->hadjustment->value,
- layout->vadjustment->value);
case ConfigureNotify:
if ((xevent->xconfigure.x != 0) || (xevent->xconfigure.y != 0))
{
layout->configure_serial = xevent->xconfigure.serial;
layout->scroll_x = xevent->xconfigure.x;
layout->scroll_y = xevent->xconfigure.y;
}
break;
gdk_window_process_updates (layout->bin_window, TRUE);
}
#elif defined (GDK_WINDOWING_WIN32)
/* XXX Not implemented */
#endif
return GDK_FILTER_CONTINUE;
}
#endif 0
/* Although GDK does have a GDK_VISIBILITY_NOTIFY event,
* there is no corresponding event in GTK, so we have
* to get the events from a filter
*/
static GdkFilterReturn
gtk_layout_main_filter (GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data)
{
#ifdef GDK_WINDOWING_X11
XEvent *xevent;
GtkLayout *layout;
xevent = (XEvent *)gdk_xevent;
layout = GTK_LAYOUT (data);
if (xevent->type == VisibilityNotify)
{
switch (xevent->xvisibility.state)
{
case VisibilityFullyObscured:
layout->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
break;
case VisibilityPartiallyObscured:
layout->visibility = GDK_VISIBILITY_PARTIAL;
break;
case VisibilityUnobscured:
layout->visibility = GDK_VISIBILITY_UNOBSCURED;
break;
}
return GDK_FILTER_REMOVE;
}
#elif defined (GDK_WINDOWING_WIN32)
/* XXX Not implemented */
#endif
return GDK_FILTER_CONTINUE;
}

View File

@ -742,8 +742,17 @@ gtk_main_do_event (GdkEvent *event)
}
break;
case GDK_PROPERTY_NOTIFY:
case GDK_EXPOSE:
if (event->any.window)
gdk_window_begin_paint_rect (event->any.window, &event->expose.area);
gtk_widget_event (event_widget, event);
if (event->any.window)
gdk_window_end_paint (event->any.window);
break;
case GDK_PROPERTY_NOTIFY:
case GDK_NO_EXPOSE:
case GDK_FOCUS_CHANGE:
case GDK_CONFIGURE:

View File

@ -810,23 +810,12 @@ gtk_range_expose (GtkWidget *widget,
range = GTK_RANGE (widget);
/* We should really pass another argument -
*the redrawn area - to all the drawing functions)
*/
if (event->window == range->trough)
{
/* Don't redraw if we are only exposing the literal trough region.
* this may not work correctly if someone overrides the default
* trough-drawing handler. (Probably should really pass another
* argument - the redrawn area to all the drawing functions)
*/
gint xt = widget->style->klass->xthickness;
gint yt = widget->style->klass->ythickness;
if (!((event->area.x >= xt) &&
(event->area.y >= yt) &&
(event->area.x + event->area.width <=
widget->allocation.width - xt) &&
(event->area.y + event->area.height <=
widget->allocation.height - yt)))
gtk_range_draw_trough (range);
gtk_range_draw_trough (range);
}
else if (event->window == widget->window)
{

View File

@ -822,9 +822,13 @@ gtk_viewport_adjustment_value_changed (GtkAdjustment *adjustment,
child_allocation.y = viewport->vadjustment->lower - viewport->vadjustment->value;
if (GTK_WIDGET_REALIZED (viewport))
gdk_window_move (viewport->bin_window,
child_allocation.x,
child_allocation.y);
{
gdk_window_move (viewport->bin_window,
child_allocation.x,
child_allocation.y);
gdk_window_process_updates (viewport->bin_window, TRUE);
}
}
}

View File

@ -61,7 +61,7 @@ gtk_vpaned_get_type (void)
(GtkClassInitFunc) NULL,
};
vpaned_type = gtk_type_unique(gtk_paned_get_type(), &vpaned_info);
vpaned_type = gtk_type_unique (GTK_TYPE_PANED, &vpaned_info);
}
return vpaned_type;

View File

@ -289,9 +289,6 @@ gtk_vscrollbar_size_allocate (GtkWidget *widget,
RANGE_CLASS (widget)->stepper_size,
widget->requisition.width - widget->style->klass->xthickness * 2,
RANGE_CLASS (widget)->stepper_size);
gdk_window_resize (range->slider,
widget->requisition.width - widget->style->klass->xthickness * 2,
RANGE_CLASS (range)->min_slider_size);
gtk_range_slider_update (GTK_RANGE (widget));
}

View File

@ -164,9 +164,6 @@ static void gtk_widget_style_set (GtkWidget *widget,
GtkStyle *previous_style);
static void gtk_widget_real_grab_focus (GtkWidget *focus_widget);
static void gtk_widget_redraw_queue_remove (GtkWidget *widget);
static GdkColormap* gtk_widget_peek_colormap (void);
static GdkVisual* gtk_widget_peek_visual (void);
static GtkStyle* gtk_widget_peek_style (void);
@ -199,7 +196,6 @@ static GSList *colormap_stack = NULL;
static GSList *visual_stack = NULL;
static GSList *style_stack = NULL;
static guint composite_child_stack = 0;
static GSList *gtk_widget_redraw_queue = NULL;
static const gchar *aux_info_key = "gtk-aux-info";
static guint aux_info_key_id = 0;
@ -1297,9 +1293,6 @@ gtk_widget_unparent (GtkWidget *widget)
gtk_window_set_default (GTK_WINDOW (toplevel), NULL);
}
if (GTK_WIDGET_REDRAW_PENDING (widget))
gtk_widget_redraw_queue_remove (widget);
if (GTK_IS_RESIZE_CONTAINER (widget))
gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
@ -1697,9 +1690,6 @@ gtk_widget_unrealize (GtkWidget *widget)
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
if (GTK_WIDGET_REDRAW_PENDING (widget))
gtk_widget_redraw_queue_remove (widget);
if (GTK_WIDGET_HAS_SHAPE_MASK (widget))
gtk_widget_shape_combine_mask (widget, NULL, -1, -1);
@ -1713,124 +1703,20 @@ gtk_widget_unrealize (GtkWidget *widget)
}
/*****************************************
* gtk_widget_queue_draw:
*
* arguments:
*
* results:
* Draw queueing.
*****************************************/
typedef struct _GtkDrawData GtkDrawData;
struct _GtkDrawData {
GdkRectangle rect;
GdkWindow *window;
};
static GMemChunk *draw_data_mem_chunk = NULL;
static GSList *draw_data_free_list = NULL;
static const gchar *draw_data_key = "gtk-draw-data";
static GQuark draw_data_key_id = 0;
static const gchar *draw_data_tmp_key = "gtk-draw-data-tmp";
static GQuark draw_data_tmp_key_id = 0;
static gint gtk_widget_idle_draw (gpointer data);
static void
gtk_widget_queue_draw_data (GtkWidget *widget,
gint x,
gint y,
gint width,
gint height,
GdkWindow *window)
{
GSList *node;
GtkDrawData *data;
g_return_if_fail (widget != NULL);
g_return_if_fail (!(width < 0 || height < 0) || window == NULL);
if ((width != 0) && (height != 0) && GTK_WIDGET_DRAWABLE (widget))
{
if (!draw_data_key_id)
draw_data_key_id = g_quark_from_static_string (draw_data_key);
if (draw_data_free_list)
{
node = draw_data_free_list;
data = node->data;
draw_data_free_list = draw_data_free_list->next;
}
else
{
if (!draw_data_mem_chunk)
draw_data_mem_chunk = g_mem_chunk_create (GtkDrawData, 64,
G_ALLOC_ONLY);
data = g_chunk_new (GtkDrawData, draw_data_mem_chunk);
node = g_slist_alloc();
node->data = data;
}
data->rect.x = x;
data->rect.y = y;
if ((width < 1 && height < 1) ||
(width >= widget->allocation.width &&
height >= widget->allocation.height))
GTK_PRIVATE_SET_FLAG (widget, GTK_FULLDRAW_PENDING);
if ((width < 0) || (height < 0))
{
data->rect.width = 0;
data->rect.height = 0;
}
else
{
data->rect.width = width;
data->rect.height = height;
}
data->window = window;
if ((width < 0) || (height < 0))
{
GSList *draw_data_list =
gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_key_id);
if (draw_data_list)
draw_data_free_list = g_slist_concat (draw_data_list,
draw_data_free_list);
node->next = NULL;
}
else
node->next = gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_key_id);
if (!GTK_WIDGET_REDRAW_PENDING (widget))
{
GTK_PRIVATE_SET_FLAG (widget, GTK_REDRAW_PENDING);
if (gtk_widget_redraw_queue == NULL)
gtk_idle_add_priority (GTK_PRIORITY_REDRAW,
gtk_widget_idle_draw,
NULL);
gtk_widget_redraw_queue = g_slist_prepend (gtk_widget_redraw_queue, widget);
}
gtk_object_set_data_by_id (GTK_OBJECT (widget), draw_data_key_id, node);
}
}
void
gtk_widget_queue_draw_area (GtkWidget *widget,
gint x,
gint y,
gint width,
gint height)
gint height)
{
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
if (widget->window && gdk_window_is_viewable (widget->window) &&
!gtk_widget_is_offscreen (widget))
gtk_widget_queue_draw_data (widget, x, y, width, height, NULL);
gtk_widget_queue_clear_area (widget, x, y, width, height);
}
void
@ -1839,11 +1725,12 @@ gtk_widget_queue_draw (GtkWidget *widget)
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
if (widget->window && gdk_window_is_viewable (widget->window) &&
!gtk_widget_is_offscreen (widget))
gtk_widget_queue_draw_data (widget, 0, 0, -1, -1, NULL);
gtk_widget_queue_clear (widget);
}
/* Invalidates the given area (allocation-relative-coordinates)
* in all of the widget's windows
*/
void
gtk_widget_queue_clear_area (GtkWidget *widget,
gint x,
@ -1851,7 +1738,7 @@ gtk_widget_queue_clear_area (GtkWidget *widget,
gint width,
gint height)
{
GtkWidget *parent;
GdkRectangle invalid_rect;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
@ -1888,8 +1775,9 @@ gtk_widget_queue_clear_area (GtkWidget *widget,
{
if (widget->parent)
{
gint wx, wy, wwidth, wheight;
/* Translate widget relative to window-relative */
gint wx, wy, wwidth, wheight;
gdk_window_get_position (widget->window, &wx, &wy);
x -= wx - widget->allocation.x;
@ -1914,36 +1802,14 @@ gtk_widget_queue_clear_area (GtkWidget *widget,
if (y + height > wheight)
height = wheight - y;
}
gtk_widget_queue_draw_data (widget, x, y, width, height, widget->window);
}
}
static void
gtk_widget_redraw_queue_remove (GtkWidget *widget)
{
GSList *draw_data_list;
GSList *tmp_list;
g_return_if_fail (GTK_WIDGET_REDRAW_PENDING (widget));
gtk_widget_redraw_queue = g_slist_remove (gtk_widget_redraw_queue, widget);
draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_key_id);
tmp_list = g_slist_last (draw_data_list);
if (tmp_list)
{
tmp_list->next = draw_data_free_list;
draw_data_free_list = draw_data_list;
}
gtk_object_set_data_by_id (GTK_OBJECT (widget),
draw_data_key_id,
NULL);
invalid_rect.x = x;
invalid_rect.y = y;
invalid_rect.width = width;
invalid_rect.height = height;
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REDRAW_PENDING);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_FULLDRAW_PENDING);
gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
}
void
@ -1966,324 +1832,6 @@ gtk_widget_queue_clear (GtkWidget *widget)
}
}
static gint
gtk_widget_draw_data_combine (GtkDrawData *parent, GtkDrawData *child)
{
gint parent_x2, parent_y2;
gint child_x2, child_y2;
/* Check for intersection */
parent_x2 = parent->rect.x + parent->rect.width;
child_x2 = child->rect.x + child->rect.width;
parent_y2 = parent->rect.y + parent->rect.height;
child_y2 = child->rect.y + child->rect.height;
if ((child->rect.x > parent_x2) || (parent->rect.x > child_x2) ||
(child->rect.y > parent_y2) || (parent->rect.y > child_y2))
return FALSE;
else
{
parent->rect.x = MIN (parent->rect.x, child->rect.x);
parent->rect.y = MIN (parent->rect.y, child->rect.y);
parent->rect.width = MAX (parent_x2, child_x2) - parent->rect.x;
parent->rect.height = MAX (parent_y2, child_y2) - parent->rect.y;
}
return TRUE;
}
/* Take a rectangle with respect to window, and translate it
* to coordinates relative to widget's allocation, clipping through
* intermediate windows. Returns whether translation failed. If the
* translation failed, we have something like a handlebox, where
* the child widget's GdkWindow is not a child of the parents GdkWindow.
*/
static gboolean
gtk_widget_clip_rect (GtkWidget *widget,
GdkWindow *window,
GdkRectangle *rect,
gint *x_offset,
gint *y_offset)
{
gint x,y, width, height;
while (window && (window != widget->window))
{
gdk_window_get_position (window, &x, &y);
rect->x += x;
if (x_offset)
*x_offset += x;
rect->y += y;
if (y_offset)
*y_offset += y;
window = gdk_window_get_parent (window);
if (!window)
return FALSE;
gdk_window_get_size (window, &width, &height);
if (rect->x < 0)
{
rect->width = (rect->width > -rect->x) ? rect->width + rect->x : 0;
rect->x = 0;
}
if (rect->y < 0)
{
rect->height = (rect->height > -rect->y) ? rect->width + rect->y : 0;
rect->y = 0;
}
if (rect->x + rect->width > width)
rect->width = (width > rect->x) ? width - rect->x : 0;
if (rect->y + rect->height > height)
rect->height = (height > rect->y) ? height - rect->y : 0;
}
if (!window)
return FALSE;
if (!GTK_WIDGET_NO_WINDOW (widget))
{
if (gdk_window_get_toplevel (window) != window)
{
gdk_window_get_position (window, &x, &y);
rect->x += x - widget->allocation.x;
if (x_offset)
*x_offset += x - widget->allocation.x;
rect->y += y - widget->allocation.y;
if (y_offset)
*y_offset += y - widget->allocation.y;
}
}
return TRUE;
}
static gint
gtk_widget_idle_draw (gpointer cb_data)
{
GSList *widget_list;
GSList *old_queue;
GSList *draw_data_list;
GtkWidget *widget;
if (!draw_data_tmp_key_id)
draw_data_tmp_key_id = g_quark_from_static_string (draw_data_tmp_key);
GDK_THREADS_ENTER ();
old_queue = gtk_widget_redraw_queue;
gtk_widget_redraw_queue = NULL;
/* Translate all draw requests to be allocation-relative.
* At the same time, move all the data out of the way,
* so when we get down to the draw step, we can queue
* more information for "next time", if the application
* is that foolhardy.
*/
widget_list = old_queue;
while (widget_list)
{
widget = widget_list->data;
draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_key_id);
gtk_object_set_data_by_id (GTK_OBJECT (widget),
draw_data_key_id,
NULL);
gtk_object_set_data_by_id (GTK_OBJECT (widget),
draw_data_tmp_key_id,
draw_data_list);
/* XXX: Since we are unsetting this flag here, further
* down the only way we can check if a redraw is queued
* on a given widget is by calling gtk_object_get_data.
* for speed purposes we might well want a private
* flag GTK_REDRAW_PROCESSING or something.
*/
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REDRAW_PENDING);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_FULLDRAW_PENDING);
while (draw_data_list)
{
gboolean full_allocation = FALSE;
GtkDrawData *data = draw_data_list->data;
if (data->window)
{
/* If the translation fails, we have a handlebox,
* so redraw the whole widget. Could be done better?
*/
full_allocation = !gtk_widget_clip_rect (widget,
data->window,
&data->rect,
NULL, NULL);
data->window = NULL;
}
else if ((data->rect.width == 0) && (data->rect.height == 0))
full_allocation = TRUE;
if (full_allocation)
{
if (GTK_WIDGET_NO_WINDOW (widget))
{
data->rect.x = widget->allocation.x;
data->rect.y = widget->allocation.y;
}
else
{
data->rect.x = 0;
data->rect.y = 0;
}
data->rect.width = widget->allocation.width;
data->rect.height = widget->allocation.height;
}
draw_data_list = draw_data_list->next;
}
widget_list = widget_list->next;
}
/* Coalesce redraws.
*/
widget_list = old_queue;
while (widget_list)
{
GSList *prev_node = NULL;
widget = widget_list->data;
draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_tmp_key_id);
while (draw_data_list)
{
gint x_offset, y_offset;
GtkDrawData *data = draw_data_list->data;
GSList *parent_list = draw_data_list->next;
GtkWidget *parent;
GdkWindow *window;
x_offset = 0;
y_offset = 0;
parent = widget;
while (parent)
{
while (parent_list)
{
if (gtk_widget_draw_data_combine (parent_list->data, data))
{
GSList *tmp;
if (prev_node)
prev_node->next = draw_data_list->next;
else
gtk_object_set_data_by_id (GTK_OBJECT (widget),
draw_data_tmp_key_id,
draw_data_list->next);
tmp = draw_data_list->next;
draw_data_list->next = draw_data_free_list;
draw_data_free_list = draw_data_list;
draw_data_list = tmp;
goto next_rect;
}
parent_list = parent_list->next;
}
window = parent->window;
if (parent->parent && parent->parent->window != window)
{
if (!GTK_WIDGET_NO_WINDOW (parent))
{
gint x, y;
gdk_window_get_position (window, &x, &y);
data->rect.x -= x - parent->allocation.x;
x_offset -= x - parent->allocation.x;
data->rect.y -= y - parent->allocation.y;
y_offset -= y - parent->allocation.y;
}
/* If we can't translate the rectangle, stop trying to
* merge. (This occurs for a handlebox)
*/
if (!gtk_widget_clip_rect (parent->parent, window, &data->rect,
&x_offset, &y_offset))
parent = NULL;
}
if (parent)
parent = parent->parent;
if (parent)
parent_list = gtk_object_get_data_by_id (GTK_OBJECT (parent),
draw_data_tmp_key_id);
else
parent_list = NULL;
}
/* OK, this rectangle stays around. But take advantage
* of the work we've done to clip it to the visible area -
* rect.width/height have already been appropriately
* decreased
*/
data->rect.x -= x_offset;
data->rect.y -= y_offset;
prev_node = draw_data_list;
draw_data_list = draw_data_list->next;
next_rect:
continue;
}
widget_list = widget_list->next;
}
/* Process the draws */
widget_list = old_queue;
while (widget_list)
{
GSList *tmp_list;
widget = widget_list->data;
draw_data_list = gtk_object_get_data_by_id (GTK_OBJECT (widget),
draw_data_tmp_key_id);
gtk_object_set_data_by_id (GTK_OBJECT (widget),
draw_data_tmp_key_id,
NULL);
tmp_list = draw_data_list;
while (tmp_list)
{
GtkDrawData *data = tmp_list->data;
if ((data->rect.width != 0) && (data->rect.height != 0))
gtk_widget_draw (widget, &data->rect);
if (tmp_list->next)
tmp_list = tmp_list->next;
else
{
tmp_list->next = draw_data_free_list;
draw_data_free_list = draw_data_list;
break;
}
}
widget_list = widget_list->next;
}
g_slist_free (old_queue);
GDK_THREADS_LEAVE ();
return FALSE;
}
void
gtk_widget_queue_resize (GtkWidget *widget)
{
@ -2338,7 +1886,25 @@ gtk_widget_draw (GtkWidget *widget,
area = &temp_area;
}
if (!GTK_WIDGET_NO_WINDOW (widget))
{
GdkRectangle tmp_area = *area;
gint x, y;
if (!GTK_WIDGET_TOPLEVEL (widget))
{
gdk_window_get_position (widget->window, &x, &y);
tmp_area.x -= x - widget->allocation.x;
tmp_area.y -= y - widget->allocation.y;
}
gdk_window_begin_paint_rect (widget->window, &tmp_area);
}
gtk_signal_emit (GTK_OBJECT (widget), widget_signals[DRAW], area);
if (!GTK_WIDGET_NO_WINDOW (widget))
gdk_window_end_paint (widget->window);
}
}
@ -2469,14 +2035,13 @@ gtk_widget_size_allocate (GtkWidget *widget,
real_allocation.width = MAX (real_allocation.width, 1);
real_allocation.height = MAX (real_allocation.height, 1);
if (real_allocation.width > 32767 ||
real_allocation.height > 32767)
if (real_allocation.width < 0 || real_allocation.height < 0)
{
g_warning ("gtk_widget_size_allocate(): attempt to allocate widget with width %d and height %d",
real_allocation.width,
real_allocation.height);
real_allocation.width = MIN (real_allocation.width, 32767);
real_allocation.height = MIN (real_allocation.height, 32767);
real_allocation.width = 1;
real_allocation.height = 1;
}
if (GTK_WIDGET_NO_WINDOW (widget))
@ -2727,7 +2292,7 @@ gint
gtk_widget_event (GtkWidget *widget,
GdkEvent *event)
{
gint return_val;
gboolean return_val;
gint signal_num;
g_return_val_if_fail (widget != NULL, TRUE);
@ -2738,14 +2303,10 @@ gtk_widget_event (GtkWidget *widget,
gtk_signal_emit (GTK_OBJECT (widget), widget_signals[EVENT], event,
&return_val);
if (return_val || GTK_OBJECT_DESTROYED (widget))
{
gtk_widget_unref (widget);
return TRUE;
}
goto out;
switch (event->type)
{
GtkWidget *parent;
case GDK_NOTHING:
signal_num = -1;
break;
@ -2821,42 +2382,9 @@ gtk_widget_event (GtkWidget *widget,
signal_num = CLIENT_EVENT;
break;
case GDK_EXPOSE:
/* there is no sense in providing a widget with bogus expose events.
* also we make the optimization to discard expose events for widgets
* that have a full redraw pending (given that the event is !send_event,
* otherwise we assume we can trust the event).
*/
if (event->any.send_event)
parent = NULL;
else if (event->any.window)
{
parent = widget;
while (parent)
{
if (GTK_WIDGET_FULLDRAW_PENDING (parent))
break;
parent = parent->parent;
}
/* <HACK> gnome-dock didn't propagate draws to torn off
* children. So don't consider those ancestors.
*/
if (parent)
{
GdkWindow *parent_window = event->any.window;
if (!event->any.window) /* Why is this necessary */
goto out;
while (parent_window && parent_window != parent->window)
parent_window = gdk_window_get_parent (parent_window);
if (!parent_window)
parent = NULL;
}
/* </HACK> */
}
if (!event->any.window || parent)
{
gtk_widget_unref (widget);
return TRUE;
}
signal_num = EXPOSE_EVENT;
break;
case GDK_VISIBILITY_NOTIFY:
@ -2864,8 +2392,7 @@ gtk_widget_event (GtkWidget *widget,
break;
default:
g_warning ("could not determine signal number for event: %d", event->type);
gtk_widget_unref (widget);
return TRUE;
goto out;
}
if (signal_num != -1)
@ -2873,6 +2400,7 @@ gtk_widget_event (GtkWidget *widget,
return_val |= GTK_OBJECT_DESTROYED (widget);
out:
gtk_widget_unref (widget);
return return_val;
@ -3056,7 +2584,7 @@ gtk_widget_intersect (GtkWidget *widget,
else
dest = &tmp;
return_val = gdk_rectangle_intersect ((GdkRectangle*) &widget->allocation, area, dest);
return_val = gdk_rectangle_intersect (&widget->allocation, area, dest);
if (return_val && intersection && !GTK_WIDGET_NO_WINDOW (widget))
{

View File

@ -110,7 +110,7 @@ typedef enum
typedef struct _GtkRequisition GtkRequisition;
typedef struct _GtkAllocation GtkAllocation;
typedef struct _GdkRectangle GtkAllocation;
typedef struct _GtkSelectionData GtkSelectionData;
typedef struct _GtkWidgetClass GtkWidgetClass;
typedef struct _GtkWidgetAuxInfo GtkWidgetAuxInfo;
@ -124,20 +124,8 @@ typedef void (*GtkCallback) (GtkWidget *widget,
*/
struct _GtkRequisition
{
gint16 width;
gint16 height;
};
/* An allocation is a size and position. Where a widget
* can ask for a desired size, it is actually given
* this amount of space at the specified position.
*/
struct _GtkAllocation
{
gint16 x;
gint16 y;
guint16 width;
guint16 height;
gint width;
gint height;
};
/* The contents of a selection are returned in a GtkSelectionData