blob: 28f6c09add52df5320d48a776ab70794fc9965a5 [file] [log] [blame]
Pierre Ossman5156d5e2011-03-09 09:42:34 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
3 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
20#include <assert.h>
21#include <stdio.h>
22#include <string.h>
23
24#include <FL/fl_draw.H>
25
26#include <rfb/CMsgWriter.h>
27#include <rfb/LogWriter.h>
28
29#include "DesktopWindow.h"
30#include "CConn.h"
31#include "i18n.h"
32#include "parameters.h"
33
34using namespace rfb;
35
36extern void exit_vncviewer();
37
38static rfb::LogWriter vlog("DesktopWindow");
39
40DesktopWindow::DesktopWindow(int w, int h, const char *name,
41 const rfb::PixelFormat& serverPF,
42 CConn* cc_)
43 : Fl_Window(w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL)
44{
45 callback(handleClose, this);
46
47 setName(name);
48
49 frameBuffer = new ManagedPixelBuffer(getPreferredPF(), w, h);
50 assert(frameBuffer);
51
52 setServerPF(serverPF);
53
54 show();
55}
56
57
58DesktopWindow::~DesktopWindow()
59{
60 delete frameBuffer;
61
62 if (pixelTrans)
63 delete pixelTrans;
64}
65
66
67void DesktopWindow::setServerPF(const rfb::PixelFormat& pf)
68{
69 if (pixelTrans)
70 delete pixelTrans;
71 pixelTrans = NULL;
72
73 if (pf.equal(getPreferredPF()))
74 return;
75
76 pixelTrans = new PixelTransformer();
77 pixelTrans->init(pf, &colourMap, getPreferredPF());
78}
79
80
81const rfb::PixelFormat &DesktopWindow::getPreferredPF()
82{
83 static PixelFormat prefPF(32, 24, false, true, 255, 255, 255, 0, 8, 16);
84
85 return prefPF;
86}
87
88
89// Cursor stuff
90
91void DesktopWindow::setCursor(int width, int height, const Point& hotspot,
92 void* data, void* mask)
93{
94}
95
96
97void DesktopWindow::setName(const char *name)
98{
99 CharArray windowNameStr;
100 windowNameStr.replaceBuf(new char[256]);
101
102 snprintf(windowNameStr.buf, 256, _("TigerVNC: %.240s"), name);
103
104 copy_label(windowNameStr.buf);
105}
106
107// setColourMapEntries() changes some of the entries in the colourmap.
108// Unfortunately these messages are often sent one at a time, so we delay the
109// settings taking effect by 100ms. This is because recalculating the internal
110// translation table can be expensive.
111void DesktopWindow::setColourMapEntries(int firstColour, int nColours,
112 rdr::U16* rgbs)
113{
114 for (int i = 0; i < nColours; i++)
115 colourMap.set(firstColour+i, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]);
116
117 if (!Fl::has_timeout(handleColourMap, this))
118 Fl::add_timeout(0.100, handleColourMap, this);
119}
120
121
122// Copy the areas of the framebuffer that have been changed (damaged)
123// to the displayed window.
124
125void DesktopWindow::updateWindow()
126{
127 Rect r;
128
129 Fl::remove_timeout(handleUpdateTimeout, this);
130
131 r = damage.get_bounding_rect();
132 Fl_Window::damage(FL_DAMAGE_USER1, r.tl.x, r.tl.y, r.width(), r.height());
133
134 damage.clear();
135}
136
137
138void DesktopWindow::draw()
139{
140 int X, Y, W, H;
141
142 int pixel_bytes, stride_bytes;
143 const uchar *buf_start;
144
145 // Check what actually needs updating
146 fl_clip_box(0, 0, w(), h(), X, Y, W, H);
147 if ((W == 0) || (H == 0))
148 return;
149
150 pixel_bytes = frameBuffer->getPF().bpp/8;
151 stride_bytes = pixel_bytes * frameBuffer->getStride();
152 buf_start = frameBuffer->data +
153 pixel_bytes * X +
154 stride_bytes * Y;
155
156 // FIXME: Check how efficient this thing really is
157 fl_draw_image(buf_start, X, Y, W, H, pixel_bytes, stride_bytes);
158}
159
160
161void DesktopWindow::handleUpdateTimeout(void *data)
162{
163 DesktopWindow *self = (DesktopWindow *)data;
164
165 assert(self);
166
167 self->updateWindow();
168}
169
170
171void DesktopWindow::handleColourMap(void *data)
172{
173 DesktopWindow *self = (DesktopWindow *)data;
174
175 assert(self);
176
177 if (self->pixelTrans != NULL)
178 self->pixelTrans->setColourMapEntries(0, 0);
179
180 self->Fl_Window::damage(FL_DAMAGE_ALL);
181}
182
183void DesktopWindow::handleClose(Fl_Widget *wnd, void *data)
184{
185 exit_vncviewer();
186}