📄 sdisplay.cxx.svn-base
字号:
// NB: updateMethod reflects the *selected* update method, not
// necessarily the one in use, since we fall back to simpler
// methods if more advanced ones fail!
if (updateMethod_ != updateMethod)
return true;
// - Check that the desktop optimisation settings haven't changed
// This isn't very efficient, but it shouldn't change very often!
if ((isWallpaperRemoved != removeWallpaper) ||
(isPatternRemoved != removePattern) ||
(areEffectsDisabled != disableEffects))
return true;
return false;
}
void SDisplay::restartCore() {
vlog.info("restarting");
// Stop the existing Core related resources
stopCore();
try {
// Start a new Core if possible
startCore();
vlog.info("restarted");
} catch (rdr::Exception& e) {
// If startCore() fails then we MUST disconnect all clients,
// to cause the server to stop() the desktop.
// Otherwise, the SDesktop is in an inconsistent state
// and the server will crash.
server->closeClients(e.str());
}
}
void SDisplay::pointerEvent(const Point& pos, int buttonmask) {
if (pb->getRect().contains(pos)) {
Point screenPos = pos.translate(screenRect.tl);
// - Check that the SDesktop doesn't need restarting
if (isRestartRequired())
restartCore();
if (ptr)
ptr->pointerEvent(screenPos, buttonmask);
}
}
void SDisplay::keyEvent(rdr::U32 key, bool down) {
// - Check that the SDesktop doesn't need restarting
if (isRestartRequired())
restartCore();
if (kbd)
kbd->keyEvent(key, down);
}
void SDisplay::clientCutText(const char* text, int len) {
CharArray clip_sz(len+1);
memcpy(clip_sz.buf, text, len);
clip_sz.buf[len] = 0;
clipboard->setClipText(clip_sz.buf);
}
void SDisplay::framebufferUpdateRequest()
{
SetEvent(updateEvent);
}
Point SDisplay::getFbSize() {
bool startAndStop = !core;
// If not started, do minimal initialisation to get desktop size.
if (startAndStop)
recreatePixelBuffer();
Point result = Point(pb->width(), pb->height());
// Destroy the initialised structures.
if (startAndStop)
stopCore();
return result;
}
void
SDisplay::notifyClipboardChanged(const char* text, int len) {
vlog.debug("clipboard text changed");
if (server)
server->serverCutText(text, len);
}
void
SDisplay::notifyDisplayEvent(WMMonitor::Notifier::DisplayEventType evt) {
switch (evt) {
case WMMonitor::Notifier::DisplaySizeChanged:
vlog.debug("desktop size changed");
recreatePixelBuffer();
break;
case WMMonitor::Notifier::DisplayPixelFormatChanged:
vlog.debug("desktop format changed");
recreatePixelBuffer();
break;
case WMMonitor::Notifier::DisplayColourMapChanged:
vlog.debug("desktop colourmap changed");
pb->updateColourMap();
if (server)
server->setColourMapEntries();
break;
default:
vlog.error("unknown display event received");
}
}
void
SDisplay::processEvent(HANDLE event) {
if (event == updateEvent) {
//vlog.write(120, "processEvent");
ResetEvent(updateEvent);
// - If the SDisplay isn't even started then quit now
if (!core) {
vlog.error("not start()ed");
return;
}
// - Ensure that the disableLocalInputs flag is respected
inputs->blockInputs(disableLocalInputs);
// - Only process updates if the server is ready
if (server && server->clientsReadyForUpdate()) {
bool try_update = false;
// - Check that the SDesktop doesn't need restarting
if (isRestartRequired()) {
restartCore();
return;
}
// - Flush any updates from the core
try {
core->flushUpdates();
} catch (rdr::Exception& e) {
vlog.error(e.str());
restartCore();
return;
}
// Ensure the cursor is up to date
WMCursor::Info info = cursor->getCursorInfo();
if (old_cursor != info) {
// Update the cursor shape if the visibility has changed
bool set_cursor = info.visible != old_cursor.visible;
// OR if the cursor is visible and the shape has changed.
set_cursor |= info.visible && (old_cursor.cursor != info.cursor);
// Update the cursor shape
if (set_cursor)
pb->setCursor(info.visible ? info.cursor : 0, server);
// Update the cursor position
// NB: First translate from Screen coordinates to Desktop
Point desktopPos = info.position.translate(screenRect.tl.negate());
server->setCursorPos(desktopPos);
try_update = true;
old_cursor = info;
}
// Flush any changes to the server
try_update = flushChangeTracker() || try_update;
if (try_update) {
server->tryUpdate();
}
}
return;
}
throw rdr::Exception("No such event");
}
// -=- Protected methods
void
SDisplay::recreatePixelBuffer(bool force) {
// Open the specified display device
// If no device is specified, open entire screen using GetDC().
// Opening the whole display with CreateDC doesn't work on multi-monitor
// systems for some reason.
DeviceContext* new_device = 0;
TCharArray deviceName(displayDevice.getData());
if (deviceName.buf[0]) {
vlog.info("Attaching to device %s", (const char*)CStr(deviceName.buf));
new_device = new DeviceDC(deviceName.buf);
}
if (!new_device) {
vlog.info("Attaching to virtual desktop");
new_device = new WindowDC(0);
}
// Get the coordinates of the specified dispay device
Rect newScreenRect;
if (deviceName.buf[0]) {
MonitorInfo info(CStr(deviceName.buf));
newScreenRect = Rect(info.rcMonitor.left, info.rcMonitor.top,
info.rcMonitor.right, info.rcMonitor.bottom);
} else {
newScreenRect = new_device->getClipBox();
}
// If nothing has changed & a recreate has not been forced, delete
// the new device context and return
if (pb && !force &&
newScreenRect.equals(screenRect) &&
new_device->getPF().equal(pb->getPF())) {
delete new_device;
return;
}
// Flush any existing changes to the server
flushChangeTracker();
// Delete the old pixelbuffer and device context
vlog.debug("deleting old pixel buffer & device");
if (pb)
delete pb;
if (device)
delete device;
// Create a DeviceFrameBuffer attached to the new device
vlog.debug("creating pixel buffer");
DeviceFrameBuffer* new_buffer = new DeviceFrameBuffer(*new_device);
// Replace the old PixelBuffer
screenRect = newScreenRect;
pb = new_buffer;
device = new_device;
// Initialise the pixels
pb->grabRegion(pb->getRect());
// Prevent future grabRect operations from throwing exceptions
pb->setIgnoreGrabErrors(true);
// Update the clipping update tracker
clipper.setClipRect(pb->getRect());
// Inform the core of the changes
if (core)
core->setScreenRect(screenRect);
// Inform the server of the changes
if (server)
server->setPixelBuffer(pb);
}
bool SDisplay::flushChangeTracker() {
if (updates.is_empty())
return false;
// vlog.write(120, "flushChangeTracker");
// Translate the update coordinates from Screen coords to Desktop
updates.translate(screenRect.tl.negate());
// Clip the updates & flush them to the server
updates.copyTo(&clipper);
updates.clear();
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -