diff --git a/FL/Fl_Double_Window.H b/FL/Fl_Double_Window.H index ba7a42d90..a60e76518 100644 --- a/FL/Fl_Double_Window.H +++ b/FL/Fl_Double_Window.H @@ -6,8 +6,6 @@ #include "Fl_Window.H" class Fl_Double_Window : public Fl_Window { -protected: - void _flush(int); // used by Fl_Overlay_Window public: void show(); void show(int a, char **b) {Fl_Window::show(a,b);} diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H index 43cb0e5f8..b365f67cf 100644 --- a/FL/Fl_Window.H +++ b/FL/Fl_Window.H @@ -74,7 +74,6 @@ public: void fullscreen(); void fullscreen_off(int,int,int,int); void iconize(); - void expose(uchar flags,int X,int Y,int W,int H); int x_root() const ; int y_root() const ; diff --git a/FL/win32.H b/FL/win32.H index d3faa2a05..93f307668 100644 --- a/FL/win32.H +++ b/FL/win32.H @@ -23,7 +23,13 @@ inline Region XRectangleRegion(int x, int y, int w, int h) { return CreateRectRgn(x,y,x+w,y+h); } inline void XDestroyRegion(Region r) {DeleteObject(r);} - +inline void XClipBox(Region r,XRectangle* rect) { + RECT win_rect; GetRgnBox(r,&win_rect); + rect->x=win_rect.left; + rect->y=win_rect.top; + rect->width=win_rect.right-win_rect.left; + rect->height=win_rect.bottom-win_rect.top; +} #define XDestroyWindow(a,b) DestroyWindow(b) #define XMapWindow(a,b) ShowWindow(b, SW_RESTORE) #define XUnmapWindow(a,b) ShowWindow(b, SW_HIDE) @@ -67,7 +73,6 @@ HBRUSH fl_brush(); // allocates a brush if necessary extern HINSTANCE fl_display; extern Window fl_window; extern HDC fl_gc; -extern HDC window_dc; // for double-buffered windows extern HPALETTE fl_palette; // non-zero only on 8-bit displays! extern HDC fl_GetDC(Window); extern MSG fl_msg; @@ -75,15 +80,13 @@ extern MSG fl_msg; // off-screen pixmaps: create, destroy, draw into, copy to window #define Fl_Offscreen HBITMAP #define fl_create_offscreen(w, h) CreateCompatibleBitmap(fl_gc, w, h) -extern void fl_switch_offscreen(HBITMAP); -inline void fl_begin_offscreen(HBITMAP b) { - window_dc = fl_gc; fl_switch_offscreen(b); -} -inline void fl_end_offscreen() { - fl_gc = window_dc; -} -void fl_make_current(HBITMAP bitmap); +extern HDC fl_makeDC(HBITMAP); +#define fl_begin_offscreen(b) \ + HDC _sgc=fl_gc; Window _sw=fl_window; fl_gc=fl_makeDC(b); fl_window=b; + +#define fl_end_offscreen() \ + ReleaseDC(fl_window,fl_gc); fl_window=_sw; fl_gc = _sgc + void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP pixmap,int srcx,int srcy); #define fl_delete_offscreen(bitmap) DeleteObject(bitmap); - diff --git a/FL/x.H b/FL/x.H index 39d1e7bb3..3e6c2c01f 100644 --- a/FL/x.H +++ b/FL/x.H @@ -47,9 +47,13 @@ extern ulong fl_event_time; // off-screen pixmaps: create, destroy, draw into, copy to window: #define Fl_Offscreen ulong #define fl_create_offscreen(w,h) \ -XCreatePixmap(fl_display, fl_window, w, h, fl_visual->depth) -#define fl_begin_offscreen(pixmap) Window _sw=fl_window;fl_window=pixmap;fl_push_no_clip() -#define fl_end_offscreen() fl_pop_clip();fl_window = _sw + XCreatePixmap(fl_display, fl_window, w, h, fl_visual->depth) +// begin/end are macros that save the old state in local variables: +#define fl_begin_offscreen(pixmap) \ + Window _sw=fl_window; fl_window=pixmap; fl_push_no_clip() +#define fl_end_offscreen() \ + fl_pop_clip(); fl_window = _sw + #define fl_copy_offscreen(x,y,w,h,pixmap,srcx,srcy) \ XCopyArea(fl_display, pixmap, fl_window, fl_gc, srcx, srcy, w, h, x, y) #define fl_delete_offscreen(pixmap) XFreePixmap(fl_display, pixmap) diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index b0bb53ab8..38d37046c 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -11,7 +11,10 @@ #include #include -void Fl_Bitmap::draw(int X, int Y, int W, int H, int cx,int cy) { +void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; // clip the box down to the size of image, quit if empty: if (cx < 0) {W += cx; X -= cx; cx = 0;} if (cx+W > w) W = w-cx; diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx index 036c7ab10..4c1bc3812 100644 --- a/src/Fl_Double_Window.cxx +++ b/src/Fl_Double_Window.cxx @@ -36,6 +36,9 @@ static int can_xdbe() { } return use_xdbe; } +#define DAMAGE_TEST() (damage() && (use_xdbe || damage() != 2)) +#else +#define DAMAGE_TEST() (damage() & ~2) #endif void Fl_Double_Window::show() { @@ -51,33 +54,35 @@ void Fl_Double_Window::show() { #ifdef WIN32 -// I've removed the second one (never understool why -// it was there to begin with). +// Code used to switch output to an off-screen window. See macros in +// win32.H which save the old state in local variables. -static HDC blt_gc; - -void fl_switch_offscreen(HBITMAP bitmap) { - if (!blt_gc) { - blt_gc = CreateCompatibleDC(fl_gc); - SetTextAlign(blt_gc, TA_BASELINE|TA_LEFT); - SetBkMode(blt_gc, TRANSPARENT); +HDC fl_makeDC(HBITMAP bitmap) { + HDC new_gc = CreateCompatibleDC(fl_gc); + SetTextAlign(new_gc, TA_BASELINE|TA_LEFT); + SetBkMode(new_gc, TRANSPARENT); #if USE_COLORMAP - if (fl_palette) SelectPalette(blt_gc, fl_palette, FALSE); + if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE); #endif - } - SelectObject(blt_gc, bitmap); - fl_gc = blt_gc; + SelectObject(new_gc, bitmap); + return new_gc; } void fl_copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) { - SelectObject(blt_gc, bitmap); - BitBlt(window_dc, x, y, w, h, blt_gc, srcx, srcy, SRCCOPY); + HDC new_gc = CreateCompatibleDC(fl_gc); + SelectObject(new_gc, bitmap); + BitBlt(fl_gc, x, y, w, h, new_gc, srcx, srcy, SRCCOPY); + ReleaseDC(bitmap, new_gc); } +extern void fl_restore_clip(); + #endif -// protected method used by Fl_Overlay_Window to fake overlay: -void Fl_Double_Window::_flush(int eraseoverlay) { +// Fl_Overlay_Window relies on flush() copying the back buffer to the +// front even if damage() == 0, thus erasing the overlay inside the region: + +void Fl_Double_Window::flush() { make_current(); // make sure fl_gc is non-zero Fl_X *i = Fl_X::i(this); if (!i->other_xid) { @@ -89,50 +94,47 @@ void Fl_Double_Window::_flush(int eraseoverlay) { i->other_xid = fl_create_offscreen(w(), h()); clear_damage(~0); } - XRectangle rect = {0,0,w(),h()}; - if (damage()) { - if ( // don't draw if back buffer is ok -#if USE_XDBE - use_xdbe || -#endif - damage() != 2) { -/* #ifdef WIN32 - fl_begin_offscreen(i->other_xid); - fl_clip_region(i->region); i->region = 0; - draw(); - fl_end_offscreen(); -#else -*/ -#ifdef WIN32 - fl_begin_offscreen(i->other_xid); -#endif - fl_window = i->other_xid; - fl_clip_region(i->region); i->region = 0; - draw(); - fl_window = i->xid; -#ifdef WIN32 - fl_end_offscreen(); -#endif -//#endif - } + if (DAMAGE_TEST()) { + HDC _sgc = fl_gc; + fl_gc = fl_makeDC(i->other_xid); + fl_restore_clip(); // duplicate region into new gc + draw(); + ReleaseDC(i->other_xid, fl_gc); + fl_gc = _sgc; } - fl_clip_region(0); +#else // X: #if USE_XDBE - if (i->region && !eraseoverlay) XClipBox(i->region, &rect); - if (use_xdbe) { + int clipped = i->region != 0; +#endif + fl_clip_region(i->region); i->region = 0; + if (DAMAGE_TEST()) { + fl_window = i->other_xid; + draw(); + fl_window = i->xid; + } +#if USE_XDBE + // It appears that swapbuffers ignores the clip region (it has to + // as the gc is not passed as an argument to it). This causes it + // to erase parts of the overlay that won't be redrawn, and (at least + // on XFree86) it is slower. So I don't use it unless the entire + // window is being redrawn. Sigh. + if (use_xdbe && !clipped) { XdbeSwapInfo s; s.swap_window = fl_xid(this); s.swap_action = XdbeCopied; - XdbeSwapBuffers(fl_display,&s,1); - } else + XdbeSwapBuffers(fl_display, &s, 1); + // fl_clip_region(0); older fix for clipping problem but overlay blinked + return; + } #endif - fl_copy_offscreen(rect.x, rect.y, rect.width, rect.height, - i->other_xid, rect.x, rect.y); +#endif + // on Irix (at least) it is faster to reduce the area copied to + // the current clip region: + int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H); + fl_copy_offscreen(X, Y, W, H, i->other_xid, X, Y); } -void Fl_Double_Window::flush() {_flush(0);} - void Fl_Double_Window::resize(int X,int Y,int W,int H) { int ow = w(); int oh = h(); diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index 8778d0b4f..44b14518e 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -38,8 +38,6 @@ //////////////////////////////////////////////////////////////// -HDC fl_GetDC(HWND); - int Fl_Gl_Window::can_do(int a, const int *b) { #ifdef WIN32 Fl_Gl_Choice *g = Fl_Gl_Choice::find(a,b); @@ -99,10 +97,6 @@ int Fl_Gl_Window::mode(int m, const int *a) { return 1; } -#ifdef WIN32 -extern char fl_direct_paint; // true when responding to WM_PAINT -#endif - void Fl_Gl_Window::make_current() { #ifdef WIN32 HDC hdc = fl_private_dc(this, mode_,&g); diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index 1aac860d4..7ab4bfb86 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -9,7 +9,10 @@ #include #include -void Fl_Image::draw(int X, int Y, int W, int H, int cx,int cy) { +void Fl_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; // clip the box down to the size of image, quit if empty: if (cx < 0) {W += cx; X -= cx; cx = 0;} if (cx+W > w) W = w-cx; diff --git a/src/Fl_Menu_Window.cxx b/src/Fl_Menu_Window.cxx index f74db6ea2..aab069849 100644 --- a/src/Fl_Menu_Window.cxx +++ b/src/Fl_Menu_Window.cxx @@ -81,16 +81,20 @@ Fl_Menu_Window::~Fl_Menu_Window() { // The system is also told to "grab" events and send them to this app. extern void fl_fix_focus(); + #ifdef WIN32 -HWND fl_capture; // for some reason we must keep forcing it back on! +// We have to keep track of whether we have captured the mouse, since +// MSWindows shows little respect for this... Grep for fl_capture to +// see where and how this is used. +HWND fl_capture; #endif void Fl::grab(Fl_Window& w) { grab_ = &w; fl_fix_focus(); #ifdef WIN32 - // this seems to have no effect... - SetCapture(fl_capture = fl_xid(first_window())); + SetActiveWindow(fl_capture = fl_xid(first_window())); + SetCapture(fl_capture); #else XGrabPointer(fl_display, fl_xid(first_window()), diff --git a/src/Fl_Overlay_Window.cxx b/src/Fl_Overlay_Window.cxx index 7bbd85904..06a694c4a 100644 --- a/src/Fl_Overlay_Window.cxx +++ b/src/Fl_Overlay_Window.cxx @@ -20,10 +20,13 @@ void Fl_Overlay_Window::hide() { } void Fl_Overlay_Window::flush() { - // a non-zero argument copies entire back buffer to window, erasing - // the overlay. We should only do this if fake overlay needs redraw: - uchar overlay_damage = damage()&8; clear_damage(damage()&~8); - _flush(overlay_damage); + // turn off the bit set by redraw_overlay: + clear_damage(damage()&~8); + // even if damage() == 0, flush() will erase the fake overlay by + // copying back buffer over it. It will also set the clip to the + // region made by all the expose events: + Fl_Double_Window::flush(); + // Now draw the fake overlay, if any, using the current clip: if (overlay_ == this) draw_overlay(); } diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index 3e4e1af11..47777e047 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -17,9 +17,13 @@ extern uchar **fl_mask_bitmap; // used by fl_draw_pixmap.C to store mask void fl_restore_clip(); // in fl_rect.C -void Fl_Pixmap::draw(int X, int Y, int W, int H, int cx,int cy) { +void Fl_Pixmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { + // ignore empty or bad pixmap data: if (w<0) fl_measure_pixmap(data, w, h); if (!w) return; + // account for current clip region (faster on Irix): + int X,Y,W,H; fl_clip_box(XP,YP,WP,HP,X,Y,W,H); + cx += X-XP; cy += Y-YP; // clip the box down to the size of image, quit if empty: if (cx < 0) {W += cx; X -= cx; cx = 0;} if (cx+W > w) W = w-cx; diff --git a/src/Fl_Window_iconize.cxx b/src/Fl_Window_iconize.cxx index a89080623..6fbb35c66 100644 --- a/src/Fl_Window_iconize.cxx +++ b/src/Fl_Window_iconize.cxx @@ -11,7 +11,7 @@ void Fl_Window::iconize() { show(); } else { #ifdef WIN32 - ShowWindow(i->xid, SW_MINIMIZE); + ShowWindow(i->xid, SW_SHOWMINNOACTIVE); #else XIconifyWindow(fl_display, i->xid, fl_screen); #endif diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index d27c2c2cc..5060e51a3 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -161,29 +161,29 @@ static int mouse_event(Fl_Window *window, int what, int button, // convert a MSWindows VK_x to an Fltk (X) Keysym: // See also the inverse converter in Fl_get_key_win32.C // This table is in numeric order by VK: -static const struct {unsigned short vk, fltk;} vktab[] = { +static const struct {unsigned short vk, fltk, extended;} vktab[] = { {VK_BACK, FL_BackSpace}, {VK_TAB, FL_Tab}, {VK_CLEAR, FL_KP+'5'}, - {VK_RETURN, FL_Enter}, - {VK_SHIFT, FL_Shift_L}, - {VK_CONTROL, FL_Control_L}, - {VK_MENU, FL_Alt_L}, + {VK_RETURN, FL_Enter, FL_KP_Enter}, + {VK_SHIFT, FL_Shift_L, FL_Shift_R}, + {VK_CONTROL, FL_Control_L, FL_Control_R}, + {VK_MENU, FL_Alt_L, FL_Alt_R}, {VK_PAUSE, FL_Pause}, {VK_CAPITAL, FL_Caps_Lock}, {VK_ESCAPE, FL_Escape}, {VK_SPACE, ' '}, - {VK_PRIOR, FL_Page_Up}, - {VK_NEXT, FL_Page_Down}, - {VK_END, FL_End}, - {VK_HOME, FL_Home}, - {VK_LEFT, FL_Left}, - {VK_UP, FL_Up}, - {VK_RIGHT, FL_Right}, - {VK_DOWN, FL_Down}, - {VK_SNAPSHOT, FL_Print}, // does not work on NT - {VK_INSERT, FL_Insert}, - {VK_DELETE, FL_Delete}, + {VK_PRIOR, FL_KP+'9', FL_Page_Up}, + {VK_NEXT, FL_KP+'3', FL_Page_Down}, + {VK_END, FL_KP+'1', FL_End}, + {VK_HOME, FL_KP+'7', FL_Home}, + {VK_LEFT, FL_KP+'4', FL_Left}, + {VK_UP, FL_KP+'8', FL_Up}, + {VK_RIGHT, FL_KP+'6', FL_Right}, + {VK_DOWN, FL_KP+'2', FL_Down}, + {VK_SNAPSHOT, FL_Print}, // does not work on NT + {VK_INSERT, FL_KP+'0', FL_Insert}, + {VK_DELETE, FL_KP+'.', FL_Delete}, {VK_LWIN, FL_Meta_L}, {VK_RWIN, FL_Meta_R}, {VK_APPS, FL_Menu}, @@ -208,20 +208,19 @@ static const struct {unsigned short vk, fltk;} vktab[] = { }; static int ms2fltk(int vk, int extended) { static unsigned short vklut[256]; + static unsigned short extendedlut[256]; if (!vklut[1]) { // init the table unsigned int i; for (i = 0; i < 256; i++) vklut[i] = tolower(i); for (i=VK_F1; i<=VK_F16; i++) vklut[i] = i+(FL_F-(VK_F1-1)); for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0); - for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) + for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) { vklut[vktab[i].vk] = vktab[i].fltk; + extendedlut[vktab[i].vk] = vktab[i].extended; + } + for (i = 0; i < 256; i++) if (!extendedlut[i]) extendedlut[i] = vklut[i]; } - if (extended) switch (vk) { - case VK_CONTROL : return FL_Control_R; - case VK_MENU: return FL_Alt_R; - case VK_RETURN: return FL_KP_Enter; - } - return vklut[vk]; + return extended ? extendedlut[vk] : vklut[vk]; } #if USE_COLORMAP @@ -249,45 +248,29 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar return 0; case WM_PAINT: { - // MSWindows has already set the clip region! Fltk does not like this, - // since it wants to draw it's own damage at the same time, and - // this damage may be outside the clip region. I kludge around - // this, grep for fl_direct_paint to find the kludges... - // if (!(window->damage())) fl_direct_paint = 1; - PAINTSTRUCT ps; + + // This might be a better alternative, where we fully ignore NT's + // "facilities" for painting. MS expects applications to paint according + // to a very restrictive paradigm, and this is the way I found of + // working around it. In a sense, we are using WM_PAINT simply as an + // "exposure alert", like the X event. - // I think MSWindows refuses to allocate two DCs for the same hWnd, - // so it may kludge the way the DCs are being handled. Works for now, - // the "final" solution can wait... Whatever the behaviour of the win32 - // API, there is bound to be some small memory leak here. - // If anyone knows EXACTLY how DCs are allocated, please fix. - fl_window = hWnd; - fl_gc = BeginPaint(hWnd, &ps); - // A bug popped up because of the two following lines, which according to - // the original code's comments GetDC always resets. I just don't get - // why the problem hadn't manifested itself here earlier (well, probably - // because MSWindows was not allocating a new DC, but using the old one) - // Anyway, these followed the original GetDC calls, but for some reason - // were not here with the BeginPaint - SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT); - SetBkMode(fl_gc, TRANSPARENT); - - window->expose(2, ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right-ps.rcPaint.left, - ps.rcPaint.bottom-ps.rcPaint.top); - - Fl_X::i(window)->flush(); - window->clear_damage(); - //Since damage has been reset, we can dispose of the clip region - Region &r=Fl_X::i(window)->region; - if (r) { - DeleteObject(r); - r = 0; + Fl_X *i = Fl_X::i(window); + if (window->damage()) { + if (i->region) { + InvalidateRgn(hWnd,i->region,FALSE); + GetUpdateRgn(hWnd,i->region,0); + } + } else { + if (!i->region) i->region = CreateRectRgn(0,0,0,0); + GetUpdateRgn(hWnd,i->region,0); } - EndPaint(hWnd, &ps); - - fl_gc = 0; - fl_window = (HWND)-1; + window->clear_damage(window->damage()|2); + i->flush(); + window->clear_damage(); + // This convinces MSWindows we have painted whatever they wanted + // us to paint, and stops it from sending WM_PAINT messages. + ValidateRgn(hWnd,NULL); } break; case WM_LBUTTONDOWN: mouse_event(window, 0, 1, wParam, lParam); return 0; @@ -301,20 +284,6 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_RBUTTONUP: mouse_event(window, 2, 3, wParam, lParam); return 0; case WM_MOUSEMOVE: mouse_event(window, 3, 0, wParam, lParam); return 0; - // kludges so the pop-up menus work. Title bar still blinks, sigh... - case WM_CAPTURECHANGED: - if (fl_capture && lParam != (LPARAM)fl_capture) { - SetCapture(fl_capture); - return 0; - } - break; - case WM_ACTIVATE: - if (fl_capture && wParam && hWnd!=fl_capture) { - SetActiveWindow(fl_capture); - return 0; - } - break; - case WM_SETFOCUS: Fl::handle(FL_FOCUS, window); break; @@ -350,16 +319,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar // otherwise use it as a 0-character key... case WM_DEADCHAR: case WM_SYSDEADCHAR: - buffer[0] = 0; - Fl::e_text = buffer; - Fl::e_length = 0; - goto GETSTATE; case WM_CHAR: case WM_SYSCHAR: - buffer[0] = char(wParam); - Fl::e_text = buffer; - Fl::e_length = 1; - GETSTATE: {ulong state = Fl::e_state & 0xff000000; // keep the mouse button state // if GetKeyState is expensive we might want to comment some of these out: if (GetKeyState(VK_SHIFT)&~1) state |= FL_SHIFT; @@ -374,6 +335,17 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK; Fl::e_state = state;} if (lParam & (1<<31)) goto DEFAULT; // ignore up events after fixing shift + if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) { + buffer[0] = char(wParam); + Fl::e_length = 1; + } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) { + buffer[0] = Fl::e_keysym-FL_KP; + Fl::e_length = 1; + } else { + buffer[0] = 0; + Fl::e_length = 0; + } + Fl::e_text = buffer; // for (int i = lParam&0xff; i--;) while (window->parent()) window = window->window(); if (Fl::handle(FL_KEYBOARD,window)) return 0; @@ -472,7 +444,11 @@ Fl_X* Fl_X::make(Fl_Window* w) { if (!class_name) { // create a single WNDCLASS used for everything: class_name = "FLTK"; WNDCLASSEX wc; - wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS; + // Documentation states a device context consumes about 800 bytes + // of memory... so who cares? If 800 bytes per window is what it + // takes to speed things up, I'm game. + //wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = wc.cbWndExtra = 0; wc.hInstance = fl_display; @@ -564,7 +540,10 @@ Fl_X* Fl_X::make(Fl_Window* w) { w->set_visible(); w->handle(FL_SHOW); // get child windows to appear - ShowWindow(x->xid, fl_show_iconic ? SW_MINIMIZE : SW_SHOW); + // If we've captured the mouse, we dont want do activate any + // other windows from the code, or we loose the capture. + ShowWindow(x->xid, fl_show_iconic ? SW_SHOWMINNOACTIVE : + fl_capture? SW_SHOWNOACTIVATE : SW_SHOWNORMAL); fl_show_iconic = 0; fl_fix_focus(); return x; @@ -654,27 +633,20 @@ void Fl_Window::show() { // if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color()); Fl_X::make(this); } else { - ShowWindow(i->xid, SW_RESTORE); - SetActiveWindow(i->xid); + // Once again, we would lose the capture if we activated the window. + ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE); } } Fl_Window *Fl_Window::current_; -HDC window_dc; // the current context HDC fl_gc = 0; // the current window handle, initially set to -1 so we can correctly // allocate fl_GetDC(0) HWND fl_window = (HWND)-1; -// Here we ensure only one GetDC is ever in place. There is a little -// workaround for the case of direct_paint. +// Here we ensure only one GetDC is ever in place. HDC fl_GetDC(HWND w) { - /* - if (fl_direct_paint) { - if (w == direct_paint_window) return direct_paint_dc; - } -*/ if (fl_gc) { if (w == fl_window) return fl_gc; ReleaseDC(fl_window, fl_gc); @@ -691,19 +663,7 @@ HDC fl_GetDC(HWND w) { void Fl_Window::make_current() { fl_GetDC(fl_xid(this)); current_ = this; -} - -// WM_PAINT events and cropped damage call this: -void Fl_Window::expose(uchar flags,int X,int Y,int W,int H) { - if (i) { - Region temp= XRectangleRegion(X,Y,W,H); - if (i->region) { - CombineRgn(temp,temp,i->region,RGN_AND); - DeleteObject((HGDIOBJ)i->region); - } - i->region=temp; - } - damage(flags); + fl_clip_region(0); } #include @@ -714,7 +674,8 @@ void Fl_Widget::damage(uchar flags) { } else { Fl_X* i = Fl_X::i((Fl_Window*)this); if (i) { - if (i->region) {DeleteObject((HGDIOBJ)i->region); i->region = 0;} + if (i->region) {DeleteObject(i->region);} + i->region = 0; damage_ |= flags; Fl::damage(1); } @@ -741,13 +702,12 @@ void Fl_Widget::damage(uchar flags, int X, int Y, int W, int H) { CombineRgn(i->region,i->region,r,RGN_OR); DeleteObject(r); } - damage_ |= flags; } else { // create a new region: if (i->region) DeleteObject(i->region); i->region = XRectangleRegion(X,Y,W,H); - damage_ = flags; } + damage_ |= flags; Fl::damage(1); } } @@ -755,13 +715,8 @@ void Fl_Widget::damage(uchar flags, int X, int Y, int W, int H) { void Fl_Window::flush() { make_current(); - if (damage() & ~6) { - draw(); - } else { - fl_clip_region(i->region); - draw(); - fl_pop_clip(); - } + fl_clip_region(i->region);i->region=0; + draw(); } // End of Fl_win32.C // diff --git a/src/Makefile b/src/Makefile index 1de491e1e..72a0b60be 100644 --- a/src/Makefile +++ b/src/Makefile @@ -137,7 +137,7 @@ $(LIBRARY) : $(OBJECTS) @$(CC) -I.. $(CFLAGS) -c -o $@ $< clean : - -@ rm -f *.o *.do $(LIBRARY) $(CLEAN) core *~ makedepend + -@ rm -f *.o *.do $(LIBRARY) $(CLEAN) core *~ ../include/*~ makedepend cmap @touch makedepend depend: diff --git a/src/filename_list.cxx b/src/filename_list.cxx index 31fd52eea..5c4008c3b 100644 --- a/src/filename_list.cxx +++ b/src/filename_list.cxx @@ -5,9 +5,7 @@ #include #include -#if !defined(WIN32) || defined(__GNUC__) extern "C" { -#endif int numericsort(const dirent **, const dirent **); #if HAVE_SCANDIR #else @@ -16,9 +14,7 @@ extern "C" { int (*select)(const dirent *), int (*compar)(const dirent **, const dirent **)); #endif -#if !defined(WIN32) || defined(__GNUC__) } -#endif int filename_list(const char *d, dirent ***list) { #if defined(_AIX) || defined(CRAY) diff --git a/src/fl_boxtype.cxx b/src/fl_boxtype.cxx index 8bfa7dd71..e83f37f07 100644 --- a/src/fl_boxtype.cxx +++ b/src/fl_boxtype.cxx @@ -25,45 +25,48 @@ static uchar inactive_ramp[24] = { 48, 48, 48, 49, 49, 49, 50, 50, 51, 51, 52, 52}; -uchar* Fl_Gray_Ramp = (uchar*)active_ramp-'A'; +static int draw_it_active; +uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';} void fl_frame(const char* s, int x, int y, int w, int h) { + uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw top line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_xyline(x, y, x+w-1); y++; if (--h <= 0) break; // draw left line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_yxline(x, y+h-1, y); x++; if (--w <= 0) break; // draw bottom line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_xyline(x, y+h-1, x+w-1); if (--h <= 0) break; // draw right line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_yxline(x+w-1, y+h-1, y); if (--w <= 0) break; } } void fl_frame2(const char* s, int x, int y, int w, int h) { + uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw bottom line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_xyline(x, y+h-1, x+w-1); if (--h <= 0) break; // draw right line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_yxline(x+w-1, y+h-1, y); if (--w <= 0) break; // draw top line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_xyline(x, y, x+w-1); y++; if (--h <= 0) break; // draw left line: - fl_color(Fl_Gray_Ramp[*s++]); + fl_color(g[*s++]); fl_yxline(x, y+h-1, y); x++; if (--w <= 0) break; } @@ -250,7 +253,7 @@ void Fl_Widget::draw_box(Fl_Boxtype b, Fl_Color c) const { void Fl_Widget::draw_box(Fl_Boxtype b, int x, int y, int w, int h, Fl_Color c) const { - if (!active_r()) Fl_Gray_Ramp = inactive_ramp-'A'; + draw_it_active = active_r(); fl_box_table[b].f(x, y, w, h, c); - Fl_Gray_Ramp = active_ramp-'A'; + draw_it_active = 1; } diff --git a/src/fl_diamond_box.cxx b/src/fl_diamond_box.cxx index 81e1c27cf..e9ee57531 100644 --- a/src/fl_diamond_box.cxx +++ b/src/fl_diamond_box.cxx @@ -9,7 +9,7 @@ #include #include -extern uchar* Fl_Gray_Ramp; +extern uchar* fl_gray_ramp(); static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { w &= -2; @@ -17,13 +17,14 @@ static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { int x1 = x+w/2; int y1 = y+h/2; fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); - fl_color(Fl_Gray_Ramp['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); - fl_color(Fl_Gray_Ramp['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); - fl_color(Fl_Gray_Ramp['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); - fl_color(Fl_Gray_Ramp['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); - fl_color(Fl_Gray_Ramp['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); - fl_color(Fl_Gray_Ramp['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); - fl_color(Fl_Gray_Ramp['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); + uchar *g = fl_gray_ramp(); + fl_color(g['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); + fl_color(g['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); + fl_color(g['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); } static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { @@ -31,14 +32,15 @@ static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { h &= -2; int x1 = x+w/2; int y1 = y+h/2; - fl_color(Fl_Gray_Ramp['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); - fl_color(Fl_Gray_Ramp['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); - fl_color(Fl_Gray_Ramp['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); - fl_color(Fl_Gray_Ramp['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); - fl_color(Fl_Gray_Ramp['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); - fl_color(Fl_Gray_Ramp['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); + uchar *g = fl_gray_ramp(); + fl_color(g['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); + fl_color(g['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); - fl_color(Fl_Gray_Ramp['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); + fl_color(g['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx index f047bb824..ae31501a9 100644 --- a/src/fl_rect.cxx +++ b/src/fl_rect.cxx @@ -264,7 +264,7 @@ void fl_clip(int x, int y, int w, int h) { #ifndef WIN32 r = XCreateRegion(); #else - r = 0; //whatever, for win32 this is the same as having 0 for HRGN + r = CreateRectRgn(0,0,0,0); #endif } rstack[++rstackptr] = r; @@ -312,24 +312,6 @@ int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ default: // partial: break; } -#else -// The win32 API makes no distinction between partial and complete -// intersection, so we have to check for partial intersection ourselves. - RECT rect; - rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; - if (!RectInRegion(r,&rect)) { - W = H = 0; - return 2; - } else { - if (PtInRegion(r, rect.left, rect.top) && - PtInRegion(r, rect.left, rect.top) && - PtInRegion(r, rect.right, rect.bottom) && - PtInRegion(r, rect.right, rect.bottom)) - return 0; - } -#endif - -#ifndef WIN32 Region rr = XRectangleRegion(x,y,w,h); Region temp = XCreateRegion(); XIntersectRegion(r, rr, temp); @@ -338,14 +320,30 @@ int fl_clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ X = rect.x; Y = rect.y; W = rect.width; H = rect.height; XDestroyRegion(temp); XDestroyRegion(rr); -#else - Region rr = XRectangleRegion(x,y,w,h); - CombineRgn(rr, rr, r,RGN_AND); - GetRgnBox(rr, &rect); - X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; - DeleteObject(rr); -#endif return 1; +#else +// The win32 API makes no distinction between partial and complete +// intersection, so we have to check for partial intersection ourselves. +// However, given that the regions may be composite, we have to do +// some voodoo stuff... + Region rr = XRectangleRegion(x,y,w,h); + Region temp = CreateRectRgn(0,0,0,0); + int ret; + if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint + W = H = 0; + ret = 2; + } else if (EqualRgn(temp, rr)) { // complete + ret = 0; + } else { // parital intersection + RECT rect; + GetRgnBox(temp, &rect); + X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; + ret = 1; + } + DeleteObject(temp); + DeleteObject(rr); + return ret; +#endif } // end of fl_rect.C diff --git a/src/fl_round_box.cxx b/src/fl_round_box.cxx index c165e22ec..a6ca45e41 100644 --- a/src/fl_round_box.cxx +++ b/src/fl_round_box.cxx @@ -58,32 +58,34 @@ static void draw(int which, int x,int y,int w,int h, int inset, uchar color) } } -extern uchar* Fl_Gray_Ramp; +extern uchar* fl_gray_ramp(); static void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) { + uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, bgcolor); - draw(UPPER_LEFT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['N']); - draw(UPPER_LEFT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['H']); - draw(UPPER_LEFT, x, y, w, h, 0, Fl_Gray_Ramp['N']); - draw(UPPER_LEFT, x, y, w, h, 1, Fl_Gray_Ramp['H']); - draw(LOWER_RIGHT, x, y, w, h, 0, Fl_Gray_Ramp['S']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['U']); - draw(LOWER_RIGHT, x, y, w, h, 1, Fl_Gray_Ramp['U']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['W']); - draw(CLOSED, x, y, w, h, 2, Fl_Gray_Ramp['A']); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['N']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['H']); + draw(UPPER_LEFT, x, y, w, h, 0, g['N']); + draw(UPPER_LEFT, x, y, w, h, 1, g['H']); + draw(LOWER_RIGHT, x, y, w, h, 0, g['S']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['U']); + draw(LOWER_RIGHT, x, y, w, h, 1, g['U']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['W']); + draw(CLOSED, x, y, w, h, 2, g['A']); } static void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) { + uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, bgcolor); - draw(LOWER_RIGHT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['H']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['N']); - draw(LOWER_RIGHT, x, y, w, h, 1, Fl_Gray_Ramp['H']); - draw(LOWER_RIGHT, x, y, w, h, 2, Fl_Gray_Ramp['N']); - draw(UPPER_LEFT, x, y, w, h, 2, Fl_Gray_Ramp['U']); - draw(UPPER_LEFT, x+1, y, w-2, h, 1, Fl_Gray_Ramp['S']); - draw(UPPER_LEFT, x, y, w, h, 1, Fl_Gray_Ramp['W']); - draw(UPPER_LEFT, x+1, y, w-2, h, 0, Fl_Gray_Ramp['U']); - draw(CLOSED, x, y, w, h, 0, Fl_Gray_Ramp['A']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, g['H']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, g['N']); + draw(LOWER_RIGHT, x, y, w, h, 1, g['H']); + draw(LOWER_RIGHT, x, y, w, h, 2, g['N']); + draw(UPPER_LEFT, x, y, w, h, 2, g['U']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, g['S']); + draw(UPPER_LEFT, x, y, w, h, 1, g['W']); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, g['U']); + draw(CLOSED, x, y, w, h, 0, g['A']); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); diff --git a/test/Makefile b/test/Makefile index 384a05103..102ecf8bc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -48,4 +48,4 @@ jpeg_image: jpeg_image.C @${CXX} -I.. ${CXXFLAGS} -I../../../local/jpeg-6b -L../../../local/jpeg-6b jpeg_image.C -L../lib -lfltk ${LDLIBS} -ljpeg -lXext -o $@ clean: - -rm -f ${ALL} jpeg_image *~ + -@ rm -f ${ALL} jpeg_image *.o core *~