@@ -368,7 +368,9 @@ void DesktopWindow::resizeFramebuffer(int new_w, int new_h) | |||
} | |||
} | |||
viewport->size(new_w, new_h); | |||
viewport->resizeFramebuffer(new_w, new_h); | |||
fitWindow(w(), h()); | |||
repositionWidgets(); | |||
} | |||
@@ -598,6 +600,18 @@ void DesktopWindow::handleClipboardData(const char* data) | |||
} | |||
void DesktopWindow::fitWindow(int w, int h) | |||
{ | |||
double viewport_ratio = | |||
static_cast<double>(viewport->frameBufferWidth())/viewport->frameBufferHeight(); | |||
double window_ratio = static_cast<double>(w)/h; | |||
if (window_ratio < viewport_ratio) | |||
viewport->size(w, w/viewport_ratio); | |||
else | |||
viewport->size(h*viewport_ratio, h); | |||
} | |||
void DesktopWindow::resize(int x, int y, int w, int h) | |||
{ | |||
bool resizing; | |||
@@ -660,6 +674,8 @@ void DesktopWindow::resize(int x, int y, int w, int h) | |||
Fl_Window::resize(x, y, w, h); | |||
fitWindow(w, h); | |||
if (resizing) { | |||
// Try to get the remote size to match our window size, provided | |||
// the following conditions are true: |
@@ -108,6 +108,8 @@ private: | |||
void repositionWidgets(); | |||
void fitWindow(int w, int h); | |||
static void handleClose(Fl_Widget *wnd, void *data); | |||
static void handleOptions(void *data); |
@@ -47,6 +47,10 @@ public: | |||
void blend(int src_x, int src_y, int x, int y, int w, int h, int a=255); | |||
void blend(Surface* dst, int src_x, int src_y, int x, int y, int w, int h, int a=255); | |||
void setScale(double x, double y); | |||
double scaleX() { return scale_x; } | |||
double scaleY() { return scale_y; } | |||
protected: | |||
void alloc(); | |||
void dealloc(); | |||
@@ -54,6 +58,7 @@ protected: | |||
protected: | |||
int w, h; | |||
double scale_x, scale_y; | |||
#if defined(WIN32) | |||
RGBQUAD* data; |
@@ -53,6 +53,20 @@ void Surface::draw(int src_x, int src_y, int x, int y, int w, int h) | |||
XRenderFreePicture(fl_display, winPict); | |||
} | |||
void Surface::setScale(double x, double y) | |||
{ | |||
scale_x = x; | |||
scale_y = y; | |||
XTransform transform_matrix = {{ | |||
{XDoubleToFixed(x), XDoubleToFixed(0), XDoubleToFixed(0)}, | |||
{XDoubleToFixed(0), XDoubleToFixed(y), XDoubleToFixed(0)}, | |||
{XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1)} | |||
}}; | |||
XRenderSetPictureTransform(fl_display, picture, &transform_matrix); | |||
XRenderSetPictureFilter(fl_display, picture, FilterBilinear, 0, 0 ); | |||
} | |||
void Surface::draw(Surface* dst, int src_x, int src_y, int x, int y, int w, int h) | |||
{ | |||
XRenderComposite(fl_display, PictOpSrc, picture, None, dst->picture, |
@@ -232,7 +232,8 @@ void Viewport::updateWindow() | |||
Rect r; | |||
r = frameBuffer->getDamage(); | |||
damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height()); | |||
damage(FL_DAMAGE_USER1, r.tl.x/frameBuffer->scaleX() + x(), r.tl.y/frameBuffer->scaleY() + y(), | |||
r.width()/frameBuffer->scaleX(), r.height()/frameBuffer->scaleY()); | |||
} | |||
static const char * dotcursor_xpm[] = { | |||
@@ -541,17 +542,45 @@ void Viewport::draw() | |||
} | |||
void Viewport::resize(int x, int y, int w, int h) | |||
void Viewport::updateFrameBufferScale(int w, int h) | |||
{ | |||
double new_scale_x = static_cast<double>(frameBuffer->width())/w; | |||
double new_scale_y = static_cast<double>(frameBuffer->height())/h; | |||
frameBuffer->setScale(new_scale_x, new_scale_y); | |||
} | |||
void Viewport::resizeFramebuffer(int w, int h) | |||
{ | |||
if ((w != frameBuffer->width()) || (h != frameBuffer->height())) { | |||
vlog.debug("Resizing framebuffer from %dx%d to %dx%d", | |||
frameBuffer->width(), frameBuffer->height(), w, h); | |||
// XXX: memory leak? | |||
frameBuffer = new PlatformPixelBuffer(w, h); | |||
assert(frameBuffer); | |||
cc->setFramebuffer(frameBuffer); | |||
updateFrameBufferScale(this->w(), this->h()); | |||
} | |||
} | |||
int Viewport::frameBufferWidth() | |||
{ | |||
return frameBuffer->width(); | |||
} | |||
int Viewport::frameBufferHeight() | |||
{ | |||
return frameBuffer->height(); | |||
} | |||
void Viewport::resize(int x, int y, int w, int h) | |||
{ | |||
updateFrameBufferScale(w, h); | |||
Fl_Widget::resize(x, y, w, h); | |||
} | |||
@@ -665,9 +694,13 @@ void Viewport::sendPointerEvent(const rfb::Point& pos, int buttonMask) | |||
if (viewOnly) | |||
return; | |||
rfb::Point scaled_pos; | |||
scaled_pos.x = pos.x * frameBuffer->scaleX(); | |||
scaled_pos.y = pos.y * frameBuffer->scaleY(); | |||
if ((pointerEventInterval == 0) || (buttonMask != lastButtonMask)) { | |||
try { | |||
cc->writer()->writePointerEvent(pos, buttonMask); | |||
cc->writer()->writePointerEvent(scaled_pos, buttonMask); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("%s", e.str()); | |||
abort_connection_with_unexpected_error(e); | |||
@@ -677,7 +710,7 @@ void Viewport::sendPointerEvent(const rfb::Point& pos, int buttonMask) | |||
Fl::add_timeout((double)pointerEventInterval/1000.0, | |||
handlePointerTimeout, this); | |||
} | |||
lastPointerPos = pos; | |||
lastPointerPos = scaled_pos; | |||
lastButtonMask = buttonMask; | |||
} | |||
@@ -67,6 +67,10 @@ public: | |||
void resize(int x, int y, int w, int h); | |||
void resizeFramebuffer(int w, int h); | |||
int frameBufferWidth(); | |||
int frameBufferHeight(); | |||
int handle(int event); | |||
protected: | |||
@@ -105,6 +109,8 @@ private: | |||
static void handleOptions(void *data); | |||
void updateFrameBufferScale(int w, int h); | |||
private: | |||
CConn* cc; | |||