/* mirror a region relative to a window client rect */ void mirror_region( const rectangle_t *client_rect, struct region *region ) { int start, end, i, j; for (start = 0; start < region->num_rects; start = end + 1) { for (end = start; end < region->num_rects - 1; end++) if (region->rects[end + 1].top != region->rects[end].top) break; for (i = start, j = end; i < j; i++, j--) { rectangle_t rect = region->rects[j]; region->rects[i] = region->rects[j]; region->rects[j] = rect; mirror_rect( client_rect, ®ion->rects[j] ); mirror_rect( client_rect, ®ion->rects[i] ); } if (i == j) mirror_rect( client_rect, ®ion->rects[i] ); } mirror_rect( client_rect, ®ion->extents ); }
/********************************************************************** * ExtEscape (X11DRV.@) */ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data, INT out_count, LPVOID out_data ) { X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); switch(escape) { case QUERYESCSUPPORT: if (in_data && in_count >= sizeof(DWORD)) { switch (*(const INT *)in_data) { case X11DRV_ESCAPE: return TRUE; } } break; case X11DRV_ESCAPE: if (in_data && in_count >= sizeof(enum x11drv_escape_codes)) { switch(*(const enum x11drv_escape_codes *)in_data) { case X11DRV_SET_DRAWABLE: if (in_count >= sizeof(struct x11drv_escape_set_drawable)) { const struct x11drv_escape_set_drawable *data = in_data; physDev->dc_rect = data->dc_rect; physDev->drawable = data->drawable; XFreeGC( gdi_display, physDev->gc ); physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL ); XSetGraphicsExposures( gdi_display, physDev->gc, False ); XSetSubwindowMode( gdi_display, physDev->gc, data->mode ); TRACE( "SET_DRAWABLE hdc %p drawable %lx dc_rect %s\n", dev->hdc, physDev->drawable, wine_dbgstr_rect(&physDev->dc_rect) ); return TRUE; } break; case X11DRV_GET_DRAWABLE: if (out_count >= sizeof(struct x11drv_escape_get_drawable)) { struct x11drv_escape_get_drawable *data = out_data; data->drawable = physDev->drawable; data->dc_rect = physDev->dc_rect; return TRUE; } break; case X11DRV_FLUSH_GL_DRAWABLE: if (in_count >= sizeof(struct x11drv_escape_flush_gl_drawable)) { const struct x11drv_escape_flush_gl_drawable *data = in_data; RECT rect = physDev->dc_rect; OffsetRect( &rect, -physDev->dc_rect.left, -physDev->dc_rect.top ); /* The GL drawable may be lagged behind if we don't flush first, so * flush the display make sure we copy up-to-date data */ XFlush( gdi_display ); XSetFunction( gdi_display, physDev->gc, GXcopy ); XCopyArea( gdi_display, data->gl_drawable, physDev->drawable, physDev->gc, 0, 0, rect.right, rect.bottom, physDev->dc_rect.left, physDev->dc_rect.top ); add_device_bounds( physDev, &rect ); return TRUE; } break; case X11DRV_START_EXPOSURES: XSetGraphicsExposures( gdi_display, physDev->gc, True ); physDev->exposures = 0; return TRUE; case X11DRV_END_EXPOSURES: if (out_count >= sizeof(HRGN)) { HRGN hrgn = 0, tmp = 0; XSetGraphicsExposures( gdi_display, physDev->gc, False ); if (physDev->exposures) { for (;;) { XEvent event; XWindowEvent( gdi_display, physDev->drawable, ~0, &event ); if (event.type == NoExpose) break; if (event.type == GraphicsExpose) { RECT rect; rect.left = event.xgraphicsexpose.x - physDev->dc_rect.left; rect.top = event.xgraphicsexpose.y - physDev->dc_rect.top; rect.right = rect.left + event.xgraphicsexpose.width; rect.bottom = rect.top + event.xgraphicsexpose.height; if (GetLayout( dev->hdc ) & LAYOUT_RTL) mirror_rect( &physDev->dc_rect, &rect ); TRACE( "got %s count %d\n", wine_dbgstr_rect(&rect), event.xgraphicsexpose.count ); if (!tmp) tmp = CreateRectRgnIndirect( &rect ); else SetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR ); else { hrgn = tmp; tmp = 0; } if (!event.xgraphicsexpose.count) break; } else { ERR( "got unexpected event %d\n", event.type ); break; } } if (tmp) DeleteObject( tmp ); } *(HRGN *)out_data = hrgn; return TRUE; } break; default: break; } } break; } return 0; }
/********************************************************************** * ExtEscape (X11DRV.@) */ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data, INT out_count, LPVOID out_data ) { X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); switch(escape) { case QUERYESCSUPPORT: if (in_data) { switch (*(const INT *)in_data) { case DCICOMMAND: return DD_HAL_VERSION; case X11DRV_ESCAPE: return TRUE; } } break; case X11DRV_ESCAPE: if (in_data && in_count >= sizeof(enum x11drv_escape_codes)) { switch(*(const enum x11drv_escape_codes *)in_data) { case X11DRV_SET_DRAWABLE: if (in_count >= sizeof(struct x11drv_escape_set_drawable)) { const struct x11drv_escape_set_drawable *data = in_data; physDev->dc_rect = data->dc_rect; physDev->drawable = data->drawable; wine_tsx11_lock(); XSetSubwindowMode( gdi_display, physDev->gc, data->mode ); wine_tsx11_unlock(); TRACE( "SET_DRAWABLE hdc %p drawable %lx dc_rect %s\n", dev->hdc, physDev->drawable, wine_dbgstr_rect(&physDev->dc_rect) ); return TRUE; } break; case X11DRV_GET_DRAWABLE: if (out_count >= sizeof(struct x11drv_escape_get_drawable)) { struct x11drv_escape_get_drawable *data = out_data; data->drawable = physDev->drawable; return TRUE; } break; case X11DRV_START_EXPOSURES: wine_tsx11_lock(); XSetGraphicsExposures( gdi_display, physDev->gc, True ); wine_tsx11_unlock(); physDev->exposures = 0; return TRUE; case X11DRV_END_EXPOSURES: if (out_count >= sizeof(HRGN)) { HRGN hrgn = 0, tmp = 0; wine_tsx11_lock(); XSetGraphicsExposures( gdi_display, physDev->gc, False ); wine_tsx11_unlock(); if (physDev->exposures) { for (;;) { XEvent event; wine_tsx11_lock(); XWindowEvent( gdi_display, physDev->drawable, ~0, &event ); wine_tsx11_unlock(); if (event.type == NoExpose) break; if (event.type == GraphicsExpose) { RECT rect; rect.left = event.xgraphicsexpose.x - physDev->dc_rect.left; rect.top = event.xgraphicsexpose.y - physDev->dc_rect.top; rect.right = rect.left + event.xgraphicsexpose.width; rect.bottom = rect.top + event.xgraphicsexpose.height; if (GetLayout( dev->hdc ) & LAYOUT_RTL) mirror_rect( &physDev->dc_rect, &rect ); TRACE( "got %s count %d\n", wine_dbgstr_rect(&rect), event.xgraphicsexpose.count ); if (!tmp) tmp = CreateRectRgnIndirect( &rect ); else SetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR ); else { hrgn = tmp; tmp = 0; } if (!event.xgraphicsexpose.count) break; } else { ERR( "got unexpected event %d\n", event.type ); break; } } if (tmp) DeleteObject( tmp ); } *(HRGN *)out_data = hrgn; return TRUE; } break; default: break; } } break; } return 0; }
BOOL FASTCALL IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) { BOOL vertical; *lprect = Wnd->rcClient; RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top ); if (Wnd->ExStyle & WS_EX_LAYOUTRTL) mirror_rect( &Wnd->rcWindow, lprect ); switch (nBar) { case SB_HORZ: lprect->top = lprect->bottom; lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL); if (Wnd->style & WS_BORDER) { lprect->left--; lprect->right++; } else if (Wnd->style & WS_VSCROLL) { lprect->right++; } vertical = FALSE; break; case SB_VERT: if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) { lprect->right = lprect->left; lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL); } else { lprect->left = lprect->right; lprect->right += UserGetSystemMetrics(SM_CXVSCROLL); } if (Wnd->style & WS_BORDER) { lprect->top--; lprect->bottom++; } else if (Wnd->style & WS_HSCROLL) { lprect->bottom++; } vertical = TRUE; break; case SB_CTL: IntGetClientRect (Wnd, lprect); vertical = !!(Wnd->style & SBS_VERT); break; default: return FALSE; } return vertical; }
/*********************************************************************** * IntScrollGetScrollBarRect * * Compute the scroll bar rectangle, in drawing coordinates (i.e. client * coords for SB_CTL, window coords for SB_VERT and SB_HORZ). * 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar), 'thumbSize' returns the size of * the thumb, and 'thumbPos' returns the position of the thumb * relative to the left or to the top. * Return TRUE if the scrollbar is vertical, FALSE if horizontal. */ static BOOL FASTCALL IntScrollGetScrollBarRect(HWND Wnd, INT Bar, RECT *Rect, INT *ArrowSize, INT *ThumbSize, INT *ThumbPos) { INT Pixels; BOOL Vertical; PWND pWnd; PSBINFO pSBInfo; PSBDATA pSBData; PSBWND pSBWnd; pWnd = ValidateHwnd( Wnd ); if (!pWnd) return FALSE; pSBInfo = DesktopPtrToUser(pWnd->pSBInfo); *Rect = pWnd->rcClient; OffsetRect( Rect, -pWnd->rcWindow.left, -pWnd->rcWindow.top ); if (pWnd->ExStyle & WS_EX_LAYOUTRTL) mirror_rect( &pWnd->rcWindow, Rect ); switch (Bar) { case SB_HORZ: // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect ); Rect->top = Rect->bottom; Rect->bottom += GetSystemMetrics(SM_CYHSCROLL); if (pWnd->style & WS_BORDER) { Rect->left--; Rect->right++; } else if (pWnd->style & WS_VSCROLL) { Rect->right++; } Vertical = FALSE; pSBData = &pSBInfo->Horz; break; case SB_VERT: // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect ); if (pWnd->ExStyle & WS_EX_LEFTSCROLLBAR) { Rect->right = Rect->left; Rect->left -= GetSystemMetrics(SM_CXVSCROLL); } else { Rect->left = Rect->right; Rect->right += GetSystemMetrics(SM_CXVSCROLL); } if (pWnd->style & WS_BORDER) { Rect->top--; Rect->bottom++; } else if (pWnd->style & WS_HSCROLL) { Rect->bottom++; } Vertical = TRUE; pSBData = &pSBInfo->Vert; break; case SB_CTL: GetClientRect( Wnd, Rect ); Vertical = (pWnd->style & SBS_VERT); pSBWnd = (PSBWND)pWnd; pSBData = (PSBDATA)&pSBWnd->SBCalc; break; default: return FALSE; } if (Vertical) Pixels = Rect->bottom - Rect->top; else Pixels = Rect->right - Rect->left; if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT) { if (SCROLL_MIN_RECT < Pixels) *ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2; else *ArrowSize = 0; *ThumbPos = *ThumbSize = 0; } else { *ArrowSize = GetSystemMetrics(SM_CXVSCROLL); Pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)); if (pSBData->page) { *ThumbSize = MulDiv(Pixels, pSBData->page, (pSBData->posMax - pSBData->posMin + 1)); if (*ThumbSize < SCROLL_MIN_THUMB) *ThumbSize = SCROLL_MIN_THUMB; } else *ThumbSize = GetSystemMetrics(SM_CXVSCROLL); if (((Pixels -= *ThumbSize ) < 0) || (( pSBInfo->WSBflags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)) { /* Rectangle too small or scrollbar disabled -> no thumb */ *ThumbPos = *ThumbSize = 0; } else { INT Max = pSBData->posMax - max(pSBData->page - 1, 0); if (pSBData->posMin >= Max) *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP; else *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP + MulDiv(Pixels, (pSBData->pos - pSBData->posMin),(Max - pSBData->posMin)); } } return Vertical; }