Skip to content

Commit

Permalink
First attempt at fixing all WIN32 scrolling issues. This code uses so…
Browse files Browse the repository at this point in the history
…me (legal) trickery and should take multi-monitors and partially obscured windows into account. Albrecht, I do not have a multi-monitor setup. Please verify this fix on your machine. Thanks. (STR #1601)

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@5713 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
  • Loading branch information
Matthias Melcher committed Feb 24, 2007
1 parent c47b4c9 commit 3be4efb
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 29 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -4,6 +4,8 @@ CHANGES IN FLTK 1.1.8
STR #1457, STR #1458, STR #1460, STR #1481, STR #1578)
- The sample RPM spec file now enables large file support
and threading support (STR #1603)
- Fixed scrolling of clipped areas in MSWindows (STR
#1601)
- Fixed clipping in OS X Quartz offscreen buffers (STR
#1595)
- Now flush file chooser preferences after every change to
Expand Down
80 changes: 51 additions & 29 deletions src/fl_scroll_area.cxx
Expand Up @@ -73,39 +73,59 @@ void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
clip_h = H-src_h;
}
#ifdef WIN32
BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);
// NYI: need to redraw areas that the source of BitBlt was bad due to
// overlapped windows, probably similar to X version:
// MRS: basic code needs to redraw parts that scrolled from off-screen...
int temp, limit;
int wx, wy;

// Compute the X position of the current window;
// this only works when scrolling in response to
// a user event; Fl_Window::x/y_root() do not work
// on WIN32...
wx = Fl::event_x_root() - Fl::event_x();
wy = Fl::event_y_root() - Fl::event_y();
typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
static char first_time = 1;

temp = wx + src_x;
if (temp < Fl::x()) {
draw_area(data, dest_x, dest_y, Fl::x() - temp, src_h);
}
temp = wx + src_x + src_w;
limit = Fl::x() + Fl::w();
if (temp > limit) {
draw_area(data, dest_x + src_w - temp + limit, dest_y, temp - limit, src_h);
// We will have to do some Region magic now, so let's see if the
// required function is available (and it should be staring w/Win95)
if (first_time) {
HMODULE hMod = GetModuleHandle("GDI32.DLL");
if (hMod) {
fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
}
first_time = 0;
}

temp = wy + src_y;
if (temp < Fl::y()) {
draw_area(data, dest_x, dest_y, src_w, Fl::y() - temp);
}
temp = wy + src_y + src_h;
limit = Fl::y() + Fl::h();
if (temp > limit) {
draw_area(data, dest_x, dest_y + src_h - temp + limit, src_w, temp - limit);
// Now check if the source scrolling area is fully visible.
// If it is, we will do a quick scroll and just update the
// newly exposed area. If it is not, we go the safe route and
// re-render the full area instead.
// Note 1: we could go and find the areas that are actually
// obscured and recursively call fl_scroll for the newly found
// rectangles. However, this practice would rely on the
// elements of the undocumented Rgn structure.
// Note 2: although this method should take care of most
// multi-screen solutions, it will not solve issues scrolling
// from a different resolution screen onto another.
// Note 3: this has been tested with image maps, too.
if (fl_GetRandomRgn) {
// get the DC region minus all overlapping windows
HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
int nn = fl_GetRandomRgn(fl_gc, sys_rgn, 4);
// now get the source scrolling rectangle
HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
POINT offset = { 0, 0 };
if (GetDCOrgEx(fl_gc, &offset)) {
OffsetRgn(src_rgn, offset.x, offset.y);
}
// see if all source pixels are available in the system region
// Note: we could be a bit more merciful and subtract the
// scroll destination region as well.
HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
DeleteObject(dst_rgn);
DeleteObject(src_rgn);
DeleteObject(sys_rgn);
if (r!=NULLREGION) {
draw_area(data,X,Y,W,H);
return;
}
}

// Great, we can do an accelerated scroll insteasd of re-rendering
BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);

#elif defined(__APPLE_QD__)
Rect src = { src_y, src_x, src_y+src_h, src_x+src_w };
Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w };
Expand All @@ -116,6 +136,8 @@ void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
#elif defined(__APPLE_QUARTZ__)
// warning: there does not seem to be an equivalent to this function in Quartz
// ScrollWindowRect is a QuickDraw function and won't work here.
// Since on OS X all windows are fully double buffered, we need not
// worry about offscreen or obscured areas
Rect src = { src_y, src_x, src_y+src_h, src_x+src_w };
Rect dst = { dest_y, dest_x, dest_y+src_h, dest_x+src_w };
static RGBColor bg = { 0xffff, 0xffff, 0xffff }; RGBBackColor( &bg );
Expand Down

0 comments on commit 3be4efb

Please sign in to comment.