2 // "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $"
4 // Scrolling routines for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Drawing function to move the contents of a rectangle. This is passed
29 // a "callback" which is called to draw rectangular areas that are moved
30 // into the drawing area.
35 #include <FL/fl_draw.H>
37 // scroll a rectangle and redraw the newly exposed portions:
39 Scroll a rectangle and draw the newly exposed portions.
40 \param[in] X,Y position of top-left of rectangle
41 \param[in] W,H size of rectangle
42 \param[in] dx,dy pixel offsets for shifting rectangle
43 \param[in] draw_area callback function to draw rectangular areas
44 \param[in] data pointer to user data for callback
45 The contents of the rectangular area is first shifted by \p dx
46 and \p dy pixels. The \p draw_area callback is then called for
47 every newly exposed rectangular area.
49 void fl_scroll(int X
, int Y
, int W
, int H
, int dx
, int dy
,
50 void (*draw_area
)(void*, int,int,int,int), void* data
)
52 if (!dx
&& !dy
) return;
53 if (dx
<= -W
|| dx
>= W
|| dy
<= -H
|| dy
>= H
) {
54 // no intersection of old an new scroll
55 draw_area(data
,X
,Y
,W
,H
);
58 int src_x
, src_w
, dest_x
, clip_x
, clip_w
;
72 int src_y
, src_h
, dest_y
, clip_y
, clip_h
;
88 XCopyArea(fl_display
, fl_window
, fl_window
, fl_gc
,
89 src_x
, src_y
, src_w
, src_h
, dest_x
, dest_y
);
90 // we have to sync the display and get the GraphicsExpose events! (sigh)
92 XEvent e
; XWindowEvent(fl_display
, fl_window
, ExposureMask
, &e
);
93 if (e
.type
== NoExpose
) break;
94 // otherwise assume it is a GraphicsExpose event:
95 draw_area(data
, e
.xexpose
.x
, e
.xexpose
.y
,
96 e
.xexpose
.width
, e
.xexpose
.height
);
97 if (!e
.xgraphicsexpose
.count
) break;
100 typedef int (WINAPI
* fl_GetRandomRgn_func
)(HDC
, HRGN
, INT
);
101 static fl_GetRandomRgn_func fl_GetRandomRgn
= 0L;
102 static char first_time
= 1;
104 // We will have to do some Region magic now, so let's see if the
105 // required function is available (and it should be staring w/Win95)
107 HMODULE hMod
= GetModuleHandle("GDI32.DLL");
109 fl_GetRandomRgn
= (fl_GetRandomRgn_func
)GetProcAddress(hMod
, "GetRandomRgn");
114 // Now check if the source scrolling area is fully visible.
115 // If it is, we will do a quick scroll and just update the
116 // newly exposed area. If it is not, we go the safe route and
117 // re-render the full area instead.
118 // Note 1: we could go and find the areas that are actually
119 // obscured and recursively call fl_scroll for the newly found
120 // rectangles. However, this practice would rely on the
121 // elements of the undocumented Rgn structure.
122 // Note 2: although this method should take care of most
123 // multi-screen solutions, it will not solve issues scrolling
124 // from a different resolution screen onto another.
125 // Note 3: this has been tested with image maps, too.
126 if (fl_GetRandomRgn
) {
127 // get the DC region minus all overlapping windows
128 HRGN sys_rgn
= CreateRectRgn(0, 0, 0, 0);
129 fl_GetRandomRgn(fl_gc
, sys_rgn
, 4);
130 // now get the source scrolling rectangle
131 HRGN src_rgn
= CreateRectRgn(src_x
, src_y
, src_x
+src_w
, src_y
+src_h
);
132 POINT offset
= { 0, 0 };
133 if (GetDCOrgEx(fl_gc
, &offset
)) {
134 OffsetRgn(src_rgn
, offset
.x
, offset
.y
);
136 // see if all source pixels are available in the system region
137 // Note: we could be a bit more merciful and subtract the
138 // scroll destination region as well.
139 HRGN dst_rgn
= CreateRectRgn(0, 0, 0, 0);
140 int r
= CombineRgn(dst_rgn
, src_rgn
, sys_rgn
, RGN_DIFF
);
141 DeleteObject(dst_rgn
);
142 DeleteObject(src_rgn
);
143 DeleteObject(sys_rgn
);
145 draw_area(data
,X
,Y
,W
,H
);
150 // Great, we can do an accelerated scroll instead of re-rendering
151 BitBlt(fl_gc
, dest_x
, dest_y
, src_w
, src_h
, fl_gc
, src_x
, src_y
,SRCCOPY
);
153 #elif defined(__APPLE_QUARTZ__)
154 CGImageRef img
= Fl_X::CGImage_from_window_rect(Fl_Window::current(), src_x
, src_y
, src_w
, src_h
);
155 CGRect rect
= { { dest_x
, dest_y
}, { src_w
, src_h
} };
156 Fl_X::q_begin_image(rect
, 0, 0, src_w
, src_h
);
157 CGContextDrawImage(fl_gc
, rect
, img
);
161 # error unsupported platform
163 if (dx
) draw_area(data
, clip_x
, dest_y
, clip_w
, src_h
);
164 if (dy
) draw_area(data
, X
, clip_y
, W
, clip_h
);
168 // End of "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $".