📄 sdisplay.cxx.svn-base
字号:
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
// -=- SDisplay.cxx
//
// The SDisplay class encapsulates a particular system display.
#include <rfb_wince/SDisplay.h>
#include <rfb_wince/Service.h>
#include <rfb_wince/TsSessions.h>
#include <rfb_wince/CleanDesktop.h>
#include <rfb_wince/CurrentUser.h>
#include <rfb_wince/DynamicFn.h>
#include <rfb_wince/MonitorInfo.h>
#include <rfb_wince/SDisplayCorePolling.h>
#include <rfb_wince/SDisplayCoreWMHooks.h>
#include <rfb_wince/SDisplayCoreDriver.h>
#include <rfb/Exception.h>
#include <rfb/LogWriter.h>
using namespace rdr;
using namespace rfb;
using namespace rfb::win32;
static LogWriter vlog("SDisplay");
#ifdef _WIN32
#define stricmp _stricmp
#endif
// - SDisplay-specific configuration options
IntParameter rfb::win32::SDisplay::updateMethod("UpdateMethod",
"How to discover desktop updates; 0 - Polling, 1 - Application hooking, 2 - Driver hooking.", 1);
BoolParameter rfb::win32::SDisplay::disableLocalInputs("DisableLocalInputs",
"Disable local keyboard and pointer input while the server is in use", false);
StringParameter rfb::win32::SDisplay::disconnectAction("DisconnectAction",
"Action to perform when all clients have disconnected. (None, Lock, Logoff)", "None");
StringParameter displayDevice("DisplayDevice",
"Display device name of the monitor to be remoted, or empty to export the whole desktop.", "");
BoolParameter rfb::win32::SDisplay::removeWallpaper("RemoveWallpaper",
"Remove the desktop wallpaper when the server is in use.", false);
BoolParameter rfb::win32::SDisplay::removePattern("RemovePattern",
"Remove the desktop background pattern when the server is in use.", false);
BoolParameter rfb::win32::SDisplay::disableEffects("DisableEffects",
"Disable desktop user interface effects when the server is in use.", false);
//////////////////////////////////////////////////////////////////////////////
//
// SDisplay
//
typedef BOOL (WINAPI *_LockWorkStation_proto)();
DynamicFn<_LockWorkStation_proto> _LockWorkStation(_T("user32.dll"), "LockWorkStation");
// -=- Constructor/Destructor
SDisplay::SDisplay()
: server(0), pb(0), device(0),
core(0), ptr(0), kbd(0), clipboard(0),
inputs(0), monitor(0), cleanDesktop(0), cursor(0),
statusLocation(0)
{
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
}
SDisplay::~SDisplay()
{
// XXX when the VNCServer has been deleted with clients active, stop()
// doesn't get called - this ought to be fixed in VNCServerST. In any event,
// we should never call any methods on VNCServer once we're being deleted.
// This is because it is supposed to be guaranteed that the SDesktop exists
// throughout the lifetime of the VNCServer. So if we're being deleted, then
// the VNCServer ought not to exist and therefore we shouldn't invoke any
// methods on it. Setting server to zero here ensures that stop() doesn't
// call setPixelBuffer(0) on the server.
server = 0;
if (core) stop();
}
// -=- SDesktop interface
void SDisplay::start(VNCServer* vs)
{
vlog.debug("starting");
// Try to make session zero the console session
if (!inConsoleSession())
setConsoleSession();
// Start the SDisplay core
server = vs;
startCore();
vlog.debug("started");
if (statusLocation) *statusLocation = true;
}
void SDisplay::stop()
{
vlog.debug("stopping");
// If we successfully start()ed then perform the DisconnectAction
/* Peica Cut
if (core) {
CurrentUserToken cut;
CharArray action = disconnectAction.getData();
if (stricmp(action.buf, "Logoff") == 0) {
if (!cut.h)
vlog.info("ignoring DisconnectAction=Logoff - no current user");
else
ExitWindowsEx(EWX_LOGOFF, 0);
} else if (stricmp(action.buf, "Lock") == 0) {
if (!cut.h) {
vlog.info("ignoring DisconnectAction=Lock - no current user");
} else {
if (_LockWorkStation.isValid())
(*_LockWorkStation)();
else
ExitWindowsEx(EWX_LOGOFF, 0);
}
}
}
*/
// Stop the SDisplayCore
if (server)
server->setPixelBuffer(0);
stopCore();
server = 0;
vlog.debug("stopped");
if (statusLocation) *statusLocation = false;
}
void SDisplay::startCore() {
// Currently, we just check whether we're in the console session, and
// fail if not
if (!inConsoleSession())
throw rdr::Exception("Console is not session zero - oreconnect to restore Console sessin");
// Switch to the current input desktop
if (rfb::win32::desktopChangeRequired()) {
if (!rfb::win32::changeDesktop())
throw rdr::Exception("unable to switch into input desktop");
}
// Initialise the change tracker and clipper
updates.clear();
clipper.setUpdateTracker(server);
// Create the framebuffer object
recreatePixelBuffer(true);
// Create the SDisplayCore
updateMethod_ = updateMethod;
int tryMethod = updateMethod_;
while (!core) {
try {
if (tryMethod == 2) {
core = new SDisplayCoreDriver(this, &updates);
}
else if (tryMethod == 1) {
core = new SDisplayCoreWMHooks(this, &updates);
}
else {
// NB by Peica:
// SDisplayCorePolling may cause the high CPU load issue, so we
// must set the suitable polling interval. The better choose is
// to use the WMHook method.
core = new SDisplayCorePolling(this, &updates, 240);
}
core->setScreenRect(screenRect);
} catch (rdr::Exception& e) {
delete core; core = 0;
if (tryMethod == 0)
throw rdr::Exception("unable to access desktop");
tryMethod--;
vlog.error(e.str());
}
}
vlog.info("Started %s", core->methodName());
// Start display monitor, clipboard handler and input handlers
monitor = new WMMonitor;
monitor->setNotifier(this);
clipboard = new Clipboard;
clipboard->setNotifier(this);
ptr = new SPointer;
kbd = new SKeyboard;
inputs = new WMBlockInput;
cursor = new WMCursor;
// Apply desktop optimisations
cleanDesktop = new CleanDesktop;
if (removePattern)
cleanDesktop->disablePattern();
if (removeWallpaper)
cleanDesktop->disableWallpaper();
if (disableEffects)
cleanDesktop->disableEffects();
isWallpaperRemoved = removeWallpaper;
isPatternRemoved = removePattern;
areEffectsDisabled = disableEffects;
}
void SDisplay::stopCore() {
if (core)
vlog.info("Stopping %s", core->methodName());
delete core; core = 0;
delete pb; pb = 0;
delete device; device = 0;
delete monitor; monitor = 0;
delete clipboard; clipboard = 0;
delete inputs; inputs = 0;
delete ptr; ptr = 0;
delete kbd; kbd = 0;
delete cleanDesktop; cleanDesktop = 0;
delete cursor; cursor = 0;
ResetEvent(updateEvent);
}
bool SDisplay::areHooksAvailable() {
return WMHooks::areAvailable();
}
bool SDisplay::isDriverAvailable() {
return SDisplayCoreDriver::isAvailable();
}
bool SDisplay::isRestartRequired() {
// - We must restart the SDesktop if:
// 1. We are no longer in the input desktop.
// 2. The any setting has changed.
// - Check that our session is the Console
if (!inConsoleSession())
return true;
// - Check that we are in the input desktop
if (rfb::win32::desktopChangeRequired())
return true;
// - Check that the update method setting hasn't changed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -