/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtGui module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "qglobal.h" | |
#include "qlibrary.h" | |
#include "qcursor.h" | |
#include "qapplication.h" | |
#include "private/qapplication_p.h" | |
#include "qwidget.h" | |
#include "qbitarray.h" | |
#include "qpainter.h" | |
#include "qpixmapcache.h" | |
#include "qdatetime.h" | |
#include "qtextcodec.h" | |
#include "qdatastream.h" | |
#include "qbuffer.h" | |
#include "qsocketnotifier.h" | |
#include "qsessionmanager.h" | |
#include "qclipboard.h" | |
#include "qbitmap.h" | |
#include "qwssocket_qws.h" | |
#include "qtransportauth_qws.h" | |
#include "private/qtransportauth_qws_p.h" | |
#include "qwsevent_qws.h" | |
#include "private/qwscommand_qws_p.h" | |
#include "qwsproperty_qws.h" | |
#include "qscreen_qws.h" | |
#include "qscreenproxy_qws.h" | |
#include "qcopchannel_qws.h" | |
#include "private/qlock_p.h" | |
#include "private/qwslock_p.h" | |
//#include "qmemorymanager_qws.h" | |
#include "qwsmanager_qws.h" | |
//#include "qwsregionmanager_qws.h" | |
#include "qwindowsystem_qws.h" | |
#include "private/qwindowsystem_p.h" | |
#include "qdecorationfactory_qws.h" | |
#include "qwsdisplay_qws.h" | |
#include "private/qwsdisplay_qws_p.h" | |
#include "private/qwsinputcontext_p.h" | |
#include "qfile.h" | |
#include "qhash.h" | |
#include "qdesktopwidget.h" | |
#include "qcolormap.h" | |
#include "private/qcursor_p.h" | |
#include "qsettings.h" | |
#include "qdebug.h" | |
#include "qeventdispatcher_qws_p.h" | |
#if !defined(QT_NO_GLIB) | |
# include "qeventdispatcher_glib_qws_p.h" | |
#endif | |
#include "private/qwidget_p.h" | |
#include "private/qbackingstore_p.h" | |
#include "private/qwindowsurface_qws_p.h" | |
#include "private/qfont_p.h" | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <locale.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#ifdef Q_OS_VXWORKS | |
# include <sys/times.h> | |
#else | |
# include <sys/time.h> | |
#endif | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <qvfbhdr.h> | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
#ifdef QT_NO_QSHM | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#ifndef Q_OS_DARWIN | |
# include <sys/sem.h> | |
#endif | |
#include <sys/socket.h> | |
#else | |
#include "private/qwssharedmemory_p.h" | |
#endif | |
#endif | |
QT_BEGIN_NAMESPACE | |
#ifndef QT_NO_DIRECTPAINTER | |
class QDirectPainter; | |
extern void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type); | |
#ifndef QT_NO_QWSEMBEDWIDGET | |
extern void qt_directpainter_embedevent(QDirectPainter *dp, | |
const QWSEmbedEvent *e); | |
#endif | |
#endif // QT_NO_DIRECTPAINTER | |
const int qwsSharedRamSize = 1 * 1024; // misc data, written by server, read by clients | |
extern QApplication::Type qt_appType; | |
extern QDesktopWidget *qt_desktopWidget; | |
//these used to be environment variables, they are initialized from | |
//environment variables in | |
bool qws_savefonts = false; | |
bool qws_screen_is_interlaced=false; //### should be detected | |
bool qws_shared_memory = false; | |
bool qws_sw_cursor = true; | |
bool qws_accel = true; // ### never set | |
QByteArray qws_display_spec(":0"); | |
Q_GUI_EXPORT int qws_display_id = 0; | |
Q_GUI_EXPORT int qws_client_id = 0; | |
QWidget *qt_pressGrab = 0; | |
QWidget *qt_mouseGrb = 0; | |
int *qt_last_x = 0; | |
int *qt_last_y = 0; | |
static int mouse_x_root = -1; | |
static int mouse_y_root = -1; | |
static int mouse_state = 0; | |
static int mouse_double_click_distance = 5; | |
int qt_servershmid = -1; | |
bool qws_overrideCursor = false; | |
#ifndef QT_NO_QWS_MANAGER | |
extern Q_GUI_EXPORT QWSServer *qwsServer; | |
static QDecoration *qws_decoration = 0; | |
#endif | |
#if defined(QT_DEBUG) | |
/* | |
extern "C" void dumpmem(const char* m) | |
{ | |
static int init=0; | |
static int prev=0; | |
FILE* f = fopen("/proc/meminfo","r"); | |
// char line[100]; | |
int total=0,used=0,free=0,shared=0,buffers=0,cached=0; | |
fscanf(f,"%*[^M]Mem: %d %d %d %d %d %d",&total,&used,&free,&shared,&buffers,&cached); | |
used -= buffers + cached; | |
if (!init) { | |
init=used; | |
} else { | |
printf("%40s: %+8d = %8d\n",m,used-init-prev,used-init); | |
prev = used-init; | |
} | |
fclose(f); | |
} | |
*/ | |
#endif | |
// Get the name of the directory where Qt for Embedded Linux temporary data should | |
// live. | |
QString qws_dataDir() | |
{ | |
static QString result; | |
if (!result.isEmpty()) | |
return result; | |
result = QT_VFB_DATADIR(qws_display_id); | |
QByteArray dataDir = result.toLocal8Bit(); | |
if (QT_MKDIR(dataDir, 0700)) { | |
if (errno != EEXIST) { | |
qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); | |
} | |
} | |
QT_STATBUF buf; | |
if (QT_LSTAT(dataDir, &buf)) | |
qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData()); | |
if (!S_ISDIR(buf.st_mode)) | |
qFatal("%s is not a directory", dataDir.constData()); | |
#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) | |
if (buf.st_uid != getuid()) | |
qFatal("Qt for Embedded Linux data directory is not owned by user %d", getuid()); | |
if ((buf.st_mode & 0677) != 0600) | |
qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); | |
#endif | |
result.append("/"); | |
return result; | |
} | |
// Get the filename of the pipe Qt for Embedded Linux uses for server/client comms | |
Q_GUI_EXPORT QString qws_qtePipeFilename() | |
{ | |
qws_dataDir(); | |
return QTE_PIPE(qws_display_id); | |
} | |
static void setMaxWindowRect(const QRect &rect) | |
{ | |
const QList<QScreen*> subScreens = qt_screen->subScreens(); | |
QScreen *screen = qt_screen; | |
int screenNo = 0; | |
for (int i = 0; i < subScreens.size(); ++i) { | |
if (subScreens.at(i)->region().contains(rect)) { | |
screen = subScreens.at(i); | |
screenNo = i; | |
break; | |
} | |
} | |
QApplicationPrivate *ap = QApplicationPrivate::instance(); | |
ap->setMaxWindowRect(screen, screenNo, rect); | |
} | |
void QApplicationPrivate::setMaxWindowRect(const QScreen *screen, int screenNo, | |
const QRect &rect) | |
{ | |
if (maxWindowRects.value(screen) == rect) | |
return; | |
maxWindowRects[screen] = rect; | |
// Re-resize any maximized windows | |
QWidgetList l = QApplication::topLevelWidgets(); | |
for (int i = 0; i < l.size(); ++i) { | |
QWidget *w = l.at(i); | |
QScreen *s = w->d_func()->getScreen(); | |
if (w->isMaximized() && s == screen) | |
w->d_func()->setMaxWindowState_helper(); | |
} | |
if ( qt_desktopWidget ) // XXX workaround crash | |
emit QApplication::desktop()->workAreaResized(screenNo); | |
} | |
#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION | |
typedef void (*TransformFunc)(QScreen *, int); | |
#ifndef QT_NO_QWS_TRANSFORMED | |
extern "C" void qws_setScreenTransformation(QScreen *, int); | |
#endif | |
static TransformFunc getTransformationFunction() | |
{ | |
static TransformFunc func = 0; | |
if (!func) { | |
#ifdef QT_NO_QWS_TRANSFORMED | |
# ifndef QT_NO_LIBRARY | |
// symbol is not built into the library, search for the plugin | |
const QStringList paths = QApplication::libraryPaths(); | |
foreach (const QString &path, paths) { | |
const QString file = path + QLatin1String("/gfxdrivers/libqgfxtransformed"); | |
func = (TransformFunc)QLibrary::resolve(file, | |
"qws_setScreenTransformation"); | |
if (func) | |
break; | |
} | |
# endif | |
#else | |
func = qws_setScreenTransformation; | |
#endif | |
if (!func) | |
func = (TransformFunc)-1; | |
} | |
if (func == (TransformFunc)-1) | |
return 0; | |
return func; | |
} | |
static void setScreenTransformation(int screenNo, int transformation) | |
{ | |
QScreen *screen = QScreen::instance(); | |
const QList<QScreen*> subScreens = screen->subScreens(); | |
if (screenNo == -1) | |
screenNo = 0; | |
if (screenNo == -1 && !subScreens.isEmpty()) | |
screenNo = 0; | |
if (subScreens.isEmpty() && screenNo == 0) { | |
// nothing | |
} else if (screenNo < 0 || screenNo >= subScreens.size()) { | |
qWarning("setScreenTransformation: invalid screen %i", screenNo); | |
return; | |
} | |
if (screenNo < subScreens.size()) | |
screen = subScreens.at(screenNo); | |
QApplicationPrivate *ap = QApplicationPrivate::instance(); | |
ap->setScreenTransformation(screen, screenNo, transformation); | |
} | |
void QApplicationPrivate::setScreenTransformation(QScreen *screen, | |
int screenNo, | |
int transformation) | |
{ | |
QScreen *transformed = screen; | |
while (transformed->classId() == QScreen::ProxyClass) | |
transformed = static_cast<QProxyScreen*>(transformed)->screen(); | |
if (transformed->classId() != QScreen::TransformedClass) | |
return; | |
TransformFunc setScreenTransformation = getTransformationFunction(); | |
if (!setScreenTransformation) | |
return; | |
setScreenTransformation(transformed, transformation); | |
// need to re-configure() proxies bottom-up | |
if (screen->classId() == QScreen::ProxyClass) { | |
QList<QProxyScreen*> proxies; | |
QScreen *s = screen; | |
do { | |
QProxyScreen *proxy = static_cast<QProxyScreen*>(s); | |
proxies.append(proxy); | |
s = proxy->screen(); | |
} while (s->classId() == QScreen::ProxyClass); | |
do { | |
QProxyScreen *proxy = proxies.takeLast(); | |
proxy->setScreen(proxy->screen()); // triggers configure() | |
} while (!proxies.isEmpty()); | |
} | |
if (qt_desktopWidget) { // XXX workaround crash for early screen transform events | |
QDesktopWidget *desktop = QApplication::desktop(); | |
emit desktop->resized(screenNo); | |
if (maxWindowRect(screen).isEmpty()) // not explicitly set | |
emit desktop->workAreaResized(screenNo); | |
} | |
QWSServer *server = QWSServer::instance(); | |
if (server) { | |
server->updateWindowRegions(); | |
QRegion r = screen->region(); | |
server->refresh(r); | |
} | |
// make sure maximized and fullscreen windows are updated | |
QWidgetList list = QApplication::topLevelWidgets(); | |
for (int i = list.size() - 1; i >= 0; --i) { | |
QWidget *w = list.at(i); | |
if (w->isFullScreen()) | |
w->d_func()->setFullScreenSize_helper(); | |
else if (w->isMaximized()) | |
w->d_func()->setMaxWindowState_helper(); | |
} | |
} | |
#endif // QT_NO_QWS_DYNAMICSCREENTRANSFORMATION | |
/***************************************************************************** | |
Internal variables and functions | |
*****************************************************************************/ | |
static QString appName; // application name | |
static const char *appFont = 0; // application font | |
static const char *appBGCol = 0; // application bg color | |
static const char *appFGCol = 0; // application fg color | |
static const char *appBTNCol = 0; // application btn color | |
static const char *mwGeometry = 0; // main widget geometry | |
static const char *mwTitle = 0; // main widget title | |
//static bool mwIconic = false; // main widget iconified | |
static bool app_do_modal = false; // modal mode | |
Q_GUI_EXPORT QWSDisplay *qt_fbdpy = 0; // QWS `display' | |
QLock *QWSDisplay::lock = 0; | |
static int mouseButtonPressed = 0; // last mouse button pressed | |
static int mouseButtonPressTime = 0; // when was a button pressed | |
static short mouseXPos, mouseYPos; // mouse position in act window | |
extern QWidgetList *qt_modal_stack; // stack of modal widgets | |
static QWidget *popupButtonFocus = 0; | |
static QWidget *popupOfPopupButtonFocus = 0; | |
static bool popupCloseDownMode = false; | |
static bool popupGrabOk; | |
static QPointer<QWidget> *mouseInWidget = 0; | |
QPointer<QWidget> qt_last_mouse_receiver = 0; | |
static bool sm_blockUserInput = false; // session management | |
QWidget *qt_button_down = 0; // widget got last button-down | |
WId qt_last_cursor = 0xffffffff; // Was -1, but WIds are unsigned | |
class QWSMouseEvent; | |
class QWSKeyEvent; | |
class QETWidget : public QWidget // event translator widget | |
{ | |
public: | |
bool translateMouseEvent(const QWSMouseEvent *, int oldstate); | |
bool translateKeyEvent(const QWSKeyEvent *, bool grab); | |
bool translateRegionEvent(const QWSRegionEvent *); | |
#ifndef QT_NO_QWSEMBEDWIDGET | |
void translateEmbedEvent(const QWSEmbedEvent *event); | |
#endif | |
bool translateWheelEvent(const QWSMouseEvent *me); | |
void repaintDecoration(QRegion r, bool post); | |
void updateRegion(); | |
bool raiseOnClick() | |
{ | |
// With limited windowmanagement/taskbar/etc., raising big windows | |
// (eg. spreadsheet) over the top of everything else (eg. calculator) | |
// is just annoying. | |
return !isMaximized() && !isFullScreen(); | |
} | |
}; | |
void QApplicationPrivate::createEventDispatcher() | |
{ | |
Q_Q(QApplication); | |
#if !defined(QT_NO_GLIB) | |
if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) | |
eventDispatcher = (q->type() != QApplication::Tty | |
? new QWSEventDispatcherGlib(q) | |
: new QEventDispatcherGlib(q)); | |
else | |
#endif | |
eventDispatcher = (q->type() != QApplication::Tty | |
? new QEventDispatcherQWS(q) | |
: new QEventDispatcherUNIX(q)); | |
} | |
// Single-process stuff. This should maybe move into qwindowsystem_qws.cpp | |
static bool qws_single_process; | |
static QList<QWSEvent*> incoming; | |
static QList<QWSCommand*> outgoing; | |
void qt_client_enqueue(const QWSEvent *event) | |
{ | |
QWSEvent *copy = QWSEvent::factory(event->type); | |
copy->copyFrom(event); | |
incoming.append(copy); | |
} | |
QList<QWSCommand*> *qt_get_server_queue() | |
{ | |
return &outgoing; | |
} | |
void qt_server_enqueue(const QWSCommand *command) | |
{ | |
QWSCommand *copy = QWSCommand::factory(command->type); | |
QT_TRY { | |
copy->copyFrom(command); | |
outgoing.append(copy); | |
} QT_CATCH(...) { | |
delete copy; | |
QT_RETHROW; | |
} | |
} | |
QWSDisplay::Data::Data(QObject* parent, bool singleProcess) | |
{ | |
#ifdef QT_NO_QWS_MULTIPROCESS | |
Q_UNUSED(parent); | |
Q_UNUSED(singleProcess); | |
#else | |
if (singleProcess) | |
csocket = 0; | |
else { | |
csocket = new QWSSocket(parent); | |
QObject::connect(csocket, SIGNAL(disconnected()), | |
qApp, SLOT(quit())); | |
} | |
clientLock = 0; | |
#endif | |
init(); | |
} | |
QWSDisplay::Data::~Data() | |
{ | |
// delete rgnMan; rgnMan = 0; | |
// delete memorymanager; memorymanager = 0; | |
qt_screen->disconnect(); | |
delete qt_screen; qt_screen = 0; | |
#ifndef QT_NO_QWS_CURSOR | |
delete qt_screencursor; qt_screencursor = 0; | |
#endif | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
shm.detach(); | |
if (csocket) { | |
QWSCommand shutdownCmd(QWSCommand::Shutdown, 0, 0); | |
shutdownCmd.write(csocket); | |
csocket->flush(); // may be pending QCop message, eg. | |
delete csocket; | |
} | |
delete clientLock; | |
clientLock = 0; | |
#endif | |
delete connected_event; | |
delete mouse_event; | |
delete current_event; | |
qDeleteAll(queue); | |
#ifndef QT_NO_COP | |
delete qcop_response; | |
#endif | |
} | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
bool QWSDisplay::Data::lockClient(QWSLock::LockType type, int timeout) | |
{ | |
return !clientLock || clientLock->lock(type, timeout); | |
} | |
void QWSDisplay::Data::unlockClient(QWSLock::LockType type) | |
{ | |
if (clientLock) clientLock->unlock(type); | |
} | |
bool QWSDisplay::Data::waitClient(QWSLock::LockType type, int timeout) | |
{ | |
return !clientLock || clientLock->wait(type, timeout); | |
} | |
QWSLock* QWSDisplay::Data::getClientLock() | |
{ | |
return clientLock; | |
} | |
#endif // QT_NO_QWS_MULTIPROCESS | |
void QWSDisplay::Data::flush() | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) { | |
csocket->waitForReadyRead(0); | |
csocket->flush(); | |
} | |
#endif | |
} | |
#if 0 | |
void QWSDisplay::Data::debugQueue() { | |
for (int i = 0; i < queue.size(); ++i) { | |
QWSEvent *e = queue.at(i); | |
qDebug( " ev %d type %d sl %d rl %d", i, e->type, e->simpleLen, e->rawLen); | |
} | |
} | |
#endif | |
bool QWSDisplay::Data::queueNotEmpty() | |
{ | |
return mouse_event/*||region_event*/||queue.count() > 0; | |
} | |
QWSEvent* QWSDisplay::Data::dequeue() | |
{ | |
QWSEvent *r=0; | |
if (queue.count()) { | |
r = queue.first(); | |
queue.removeFirst(); | |
if (r->type == QWSEvent::Region) | |
region_events_count--; | |
} else if (mouse_event) { | |
r = mouse_event; | |
mouse_event = 0; | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
mouse_event_count = 0; | |
#endif | |
} | |
return r; | |
} | |
QWSEvent* QWSDisplay::Data::peek() | |
{ | |
return queue.first(); | |
} | |
bool QWSDisplay::Data::directServerConnection() | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
return csocket == 0; | |
#else | |
return true; | |
#endif | |
} | |
void QWSDisplay::Data::create(int n) | |
{ | |
QWSCreateCommand cmd(n); | |
sendCommand(cmd); | |
} | |
void QWSDisplay::Data::flushCommands() | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) | |
csocket->flush(); | |
#endif | |
} | |
void QWSDisplay::Data::sendCommand(QWSCommand & cmd) | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) | |
cmd.write(csocket); | |
else | |
#endif | |
qt_server_enqueue(&cmd); | |
} | |
void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd) | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) { | |
lockClient(QWSLock::Communication); | |
cmd.write(csocket); | |
bool ok = true; | |
while (csocket->bytesToWrite() > 0) { | |
if (!csocket->waitForBytesWritten(-1)) { | |
qCritical("QWSDisplay::Data::sendSynchronousCommand: %s", | |
qPrintable(csocket->errorString())); | |
ok = false; | |
break; | |
} | |
} | |
if (ok) | |
waitClient(QWSLock::Communication); | |
} else | |
#endif | |
qt_server_enqueue(&cmd); | |
} | |
int QWSDisplay::Data::takeId() | |
{ | |
int unusedIdCount = unused_identifiers.count(); | |
if (unusedIdCount <= 10) | |
create(15); | |
if (unusedIdCount == 0) { | |
create(1); // Make sure we have an incoming id to wait for, just in case we're recursive | |
waitForCreation(); | |
} | |
return unused_identifiers.takeFirst(); | |
} | |
void QWSDisplay::Data::setMouseFilter(void (*filter)(QWSMouseEvent*)) | |
{ | |
mouseFilter = filter; | |
} | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
QWSLock* QWSDisplay::Data::clientLock = 0; | |
void Q_GUI_EXPORT qt_app_reinit( const QString& newAppName ) | |
{ | |
qt_fbdpy->d->reinit( newAppName ); | |
} | |
#endif // QT_NO_QWS_MULTIPROCESS | |
class QDesktopWidget; | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
void QWSDisplay::Data::reinit( const QString& newAppName ) | |
{ | |
Q_ASSERT(csocket); | |
delete connected_event; | |
connected_event = 0; | |
region_events_count = 0; | |
// region_ack = 0; | |
delete mouse_event; | |
mouse_event = 0; | |
// region_event = 0; | |
region_offset_window = 0; | |
#ifndef QT_NO_COP | |
delete qcop_response; | |
qcop_response = 0; | |
#endif | |
delete current_event; | |
current_event = 0; | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
mouse_event_count = 0; | |
#endif | |
mouseFilter = 0; | |
qt_desktopWidget = 0; | |
delete QWSDisplay::Data::clientLock; | |
QWSDisplay::Data::clientLock = 0; | |
QString pipe = qws_qtePipeFilename(); | |
// QWS client | |
// Cleanup all cached ids | |
unused_identifiers.clear(); | |
delete csocket; | |
appName = newAppName; | |
qApp->setObjectName( appName ); | |
csocket = new QWSSocket(); | |
QObject::connect(csocket, SIGNAL(disconnected()), | |
qApp, SLOT(quit())); | |
csocket->connectToLocalFile(pipe); | |
QWSDisplay::Data::clientLock = new QWSLock(); | |
QWSIdentifyCommand cmd; | |
cmd.setId(appName, QWSDisplay::Data::clientLock->id()); | |
#ifndef QT_NO_SXE | |
QTransportAuth *a = QTransportAuth::getInstance(); | |
QTransportAuth::Data *d = a->connectTransport( | |
QTransportAuth::UnixStreamSock | | |
QTransportAuth::Trusted, | |
csocket->socketDescriptor()); | |
QAuthDevice *ad = a->authBuf( d, csocket ); | |
ad->setClient( csocket ); | |
cmd.write(ad); | |
#else | |
cmd.write(csocket); | |
#endif | |
// wait for connect confirmation | |
waitForConnection(); | |
qws_client_id = connected_event->simpleData.clientId; | |
if (!QWSDisplay::initLock(pipe, false)) | |
qFatal("Cannot get display lock"); | |
if (shm.attach(connected_event->simpleData.servershmid)) { | |
sharedRam = static_cast<uchar *>(shm.address()); | |
QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData()); | |
if (s) | |
sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData())); | |
} else { | |
perror("QWSDisplay::Data::init"); | |
qFatal("Client can't attach to main ram memory."); | |
} | |
qApp->desktop(); | |
// We wait for creation mainly so that we can process important | |
// initialization events such as MaxWindowRect that are sent | |
// before object id creation. Waiting here avoids later window | |
// resizing since we have the MWR before windows are displayed. | |
waitForCreation(); | |
sharedRamSize -= sizeof(int); | |
qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize); | |
sharedRamSize -= sizeof(int); | |
qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize); | |
#ifndef QT_NO_COP | |
QCopChannel::reregisterAll(); | |
#endif | |
csocket->flush(); | |
} | |
#endif | |
void QWSDisplay::Data::init() | |
{ | |
connected_event = 0; | |
region_events_count = 0; | |
// region_ack = 0; | |
mouse_event = 0; | |
mouse_state = -1; | |
mouse_winid = 0; | |
// region_event = 0; | |
region_offset_window = 0; | |
#ifndef QT_NO_COP | |
qcop_response = 0; | |
#endif | |
current_event = 0; | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
mouse_event_count = 0; | |
#endif | |
mouseFilter = 0; | |
QString pipe = qws_qtePipeFilename(); | |
sharedRamSize = qwsSharedRamSize; | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) { | |
// QWS client | |
connectToPipe(); | |
QWSDisplay::Data::clientLock = new QWSLock(); | |
QWSIdentifyCommand cmd; | |
cmd.setId(appName, QWSDisplay::Data::clientLock->id()); | |
#ifndef QT_NO_SXE | |
QTransportAuth *a = QTransportAuth::getInstance(); | |
QTransportAuth::Data *d = a->connectTransport( | |
QTransportAuth::UnixStreamSock | | |
QTransportAuth::Trusted, | |
csocket->socketDescriptor()); | |
QAuthDevice *ad = a->authBuf( d, csocket ); | |
ad->setClient( csocket ); | |
cmd.write(ad); | |
#else | |
cmd.write(csocket); | |
#endif | |
// create(30); // not necessary, server will send ids anyway | |
waitForConnection(); | |
qws_client_id = connected_event->simpleData.clientId; | |
// now we want to get the exact display spec to use if we haven't | |
// specified anything. | |
if (qws_display_spec.at(0) == ':') | |
qws_display_spec = connected_event->display; | |
if (!QWSDisplay::initLock(pipe, false)) | |
qFatal("Cannot get display lock"); | |
if (shm.attach(connected_event->simpleData.servershmid)) { | |
sharedRam = static_cast<uchar *>(shm.address()); | |
QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData()); | |
if (s) | |
sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData())); | |
} else { | |
perror("QWSDisplay::Data::init"); | |
qFatal("Client can't attach to main ram memory."); | |
} | |
// We wait for creation mainly so that we can process important | |
// initialization events such as MaxWindowRect that are sent | |
// before object id creation. Waiting here avoids later window | |
// resizing since we have the MWR before windows are displayed. | |
waitForCreation(); | |
} else | |
#endif | |
{ | |
create(30); | |
// QWS server | |
if (!QWSDisplay::initLock(pipe, true)) | |
qFatal("Cannot get display lock"); | |
QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData()); | |
if (s) | |
sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData())); | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (!shm.create(sharedRamSize)) { | |
perror("Cannot create main ram shared memory\n"); | |
qFatal("Unable to allocate %d bytes of shared memory", sharedRamSize); | |
} | |
qt_servershmid = shm.id(); | |
sharedRam = static_cast<uchar *>(shm.address()); | |
#else | |
sharedRam=static_cast<uchar *>(malloc(sharedRamSize)); | |
#endif | |
// Need to zero index count at end of block, might as well zero | |
// the rest too | |
memset(sharedRam,0,sharedRamSize); | |
QWSIdentifyCommand cmd; | |
cmd.setId(appName, -1); | |
qt_server_enqueue(&cmd); | |
} | |
// Allow some memory for the graphics driver too | |
//### Note that sharedRamSize() has side effects; it must be called | |
//### once, and only once, and before initDevice() | |
sharedRamSize -= qt_screen->sharedRamSize(sharedRam+sharedRamSize); | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if(!csocket) | |
#endif | |
{ | |
//QWS server process | |
if (!qt_screen->initDevice()) | |
qFatal("Unable to initialize screen driver!"); | |
} | |
sharedRamSize -= sizeof(int); | |
qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize); | |
sharedRamSize -= sizeof(int); | |
qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize); | |
/* Initialise framebuffer memory manager */ | |
/* Add 4k for luck and to avoid clobbering hardware cursor */ | |
// int screensize=qt_screen->screenSize(); | |
// memorymanager=new QMemoryManager(qt_screen->base()+screensize+4096, | |
// qt_screen->totalSize()-(screensize+4096),0); | |
// #ifndef QT_NO_QWS_MULTIPROCESS | |
// rgnMan = new QWSRegionManager(pipe, csocket); | |
// #else | |
// rgnMan = new QWSRegionManager(pipe, 0); //####### not necessary | |
// #endif | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) | |
csocket->flush(); | |
#endif | |
} | |
QWSEvent* QWSDisplay::Data::readMore() | |
{ | |
#ifdef QT_NO_QWS_MULTIPROCESS | |
return incoming.isEmpty() ? 0 : incoming.takeFirst(); | |
#else | |
if (!csocket) | |
return incoming.isEmpty() ? 0 : incoming.takeFirst(); | |
// read next event | |
if (!current_event) { | |
int event_type = qws_read_uint(csocket); | |
if (event_type >= 0) { | |
current_event = QWSEvent::factory(event_type); | |
} | |
} | |
if (current_event) { | |
if (current_event->read(csocket)) { | |
// Finished reading a whole event. | |
QWSEvent* result = current_event; | |
current_event = 0; | |
return result; | |
} | |
} | |
// Not finished reading a whole event. | |
return 0; | |
#endif | |
} | |
void QWSDisplay::Data::fillQueue() | |
{ | |
QWSServer::processEventQueue(); | |
QWSEvent *e = readMore(); | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
int bytesAvailable = csocket ? csocket->bytesAvailable() : 0; | |
int bytesRead = 0; | |
#endif | |
while (e) { | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
bytesRead += QWS_PROTOCOL_ITEM_SIZE((*e)); | |
#endif | |
if (e->type == QWSEvent::Connected) { | |
connected_event = static_cast<QWSConnectedEvent *>(e); | |
return; | |
} else if (e->type == QWSEvent::Creation) { | |
QWSCreationEvent *ce = static_cast<QWSCreationEvent*>(e); | |
int id = ce->simpleData.objectid; | |
int count = ce->simpleData.count; | |
for (int i = 0; i < count; ++i) | |
unused_identifiers.append(id++); | |
delete e; | |
} else if (e->type == QWSEvent::Mouse) { | |
if (!qt_screen) { | |
delete e; | |
} else { | |
QWSMouseEvent *me = static_cast<QWSMouseEvent*>(e); | |
if (mouseFilter) | |
mouseFilter(me); | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
static const char *defaultAction= "INITIAL"; | |
const char * action = defaultAction; | |
#endif | |
delete mouse_event; | |
if (mouse_winid != me->window () | |
|| mouse_state != me->simpleData.state) { | |
queue.append(me); | |
mouse_winid = me->window(); | |
mouse_state = me->simpleData.state; | |
mouse_event = 0; | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
mouse_event_count = 0; | |
action = "ENQUEUE"; | |
#endif | |
} else { | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
if (mouse_event) | |
action = "COMPRESS"; | |
mouse_event_count++; | |
#endif | |
mouse_event = me; | |
} | |
#ifdef QAPPLICATION_EXTRA_DEBUG | |
if (me->simpleData.state !=0 || action != defaultAction || mouse_event_count != 0) | |
qDebug("fillQueue %s (%d,%d), state %x win %d count %d", action, | |
me->simpleData.x_root, me->simpleData.y_root, me->simpleData.state, | |
me->window(), mouse_event_count); | |
#endif | |
} | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
} else if (e->type == QWSEvent::Region && clientLock) { | |
// not really an unlock, decrements the semaphore | |
region_events_count++; | |
clientLock->unlock(QWSLock::RegionEvent); | |
queue.append(e); | |
#endif | |
#ifndef QT_NO_QWS_PROPERTIES | |
} else if (e->type == QWSEvent::PropertyReply) { | |
QWSPropertyReplyEvent *pe = static_cast<QWSPropertyReplyEvent*>(e); | |
int len = pe->simpleData.len; | |
char *data; | |
if (len <= 0) { | |
data = 0; | |
} else { | |
data = new char[len]; | |
memcpy(data, pe->data, len) ; | |
} | |
QPaintDevice::qwsDisplay()->getPropertyLen = len; | |
QPaintDevice::qwsDisplay()->getPropertyData = data; | |
delete e; | |
#endif // QT_NO_QWS_PROPERTIES | |
} else if (e->type==QWSEvent::MaxWindowRect && qt_screen) { | |
// Process this ASAP, in case new widgets are created (startup) | |
setMaxWindowRect((static_cast<QWSMaxWindowRectEvent*>(e))->simpleData.rect); | |
delete e; | |
#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION | |
} else if (e->type == QWSEvent::ScreenTransformation) { | |
QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(e); | |
setScreenTransformation(pe->simpleData.screen, | |
pe->simpleData.transformation); | |
delete e; | |
#endif | |
#ifndef QT_NO_COP | |
} else if (e->type == QWSEvent::QCopMessage) { | |
QWSQCopMessageEvent *pe = static_cast<QWSQCopMessageEvent*>(e); | |
if (pe->simpleData.is_response) { | |
qcop_response = pe; | |
} else { | |
queue.append(e); | |
} | |
#endif | |
} else { | |
queue.append(e); | |
} | |
//debugQueue(); | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket && bytesRead >= bytesAvailable) | |
break; | |
#endif | |
e = readMore(); | |
} | |
} | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
static int qws_connection_timeout = 5; | |
void QWSDisplay::Data::connectToPipe() | |
{ | |
Q_ASSERT(csocket); | |
int timeout = qgetenv("QWS_CONNECTION_TIMEOUT").toInt(); | |
if (timeout) | |
qws_connection_timeout = timeout; | |
const QString pipe = qws_qtePipeFilename(); | |
int i = 0; | |
while (!csocket->connectToLocalFile(pipe)) { | |
if (++i > qws_connection_timeout) { | |
qWarning("No Qt for Embedded Linux server appears to be running."); | |
qWarning("If you want to run this program as a server,"); | |
qWarning("add the \"-qws\" command-line option."); | |
exit(1); | |
} | |
sleep(1); | |
} | |
} | |
void QWSDisplay::Data::waitForConnection() | |
{ | |
connected_event = 0; | |
for (int i = 0; i < qws_connection_timeout; i++) { | |
fillQueue(); | |
if (connected_event) | |
return; | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
} | |
csocket->flush(); | |
if (!connected_event) | |
qFatal("Did not receive a connection event from the qws server"); | |
} | |
void QWSDisplay::Data::waitForRegionAck(int winId) | |
{ | |
QWSEvent *ack = 0; | |
if (csocket) { // GuiClient | |
int i = 0; | |
while (!ack) { | |
fillQueue(); | |
while (i < queue.size()) { | |
QWSEvent *e = queue.at(i); | |
if (e->type == QWSEvent::Region && e->window() == winId) { | |
ack = e; | |
queue.removeAt(i); | |
break; | |
} | |
++i; | |
} | |
if (!ack) { | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
} | |
} | |
} else { // GuiServer | |
fillQueue(); | |
for (int i = 0; i < queue.size(); /* nothing */) { | |
QWSEvent *e = queue.at(i); | |
if (e->type == QWSEvent::Region && e->window() == winId) { | |
ack = e; | |
queue.removeAt(i); | |
break; | |
} | |
++i; | |
} | |
if (!ack) // already processed | |
return; | |
} | |
Q_ASSERT(ack); | |
qApp->qwsProcessEvent(ack); | |
delete ack; | |
region_events_count--; | |
} | |
void QWSDisplay::Data::waitForRegionEvents(int winId, bool ungrabDisplay) | |
{ | |
if (!clientLock) | |
return; | |
int removedEventsCount = 0; | |
// fill queue with unreceived region events | |
if (!clientLock->hasLock(QWSLock::RegionEvent)) { | |
bool ungrabbed = false; | |
if (ungrabDisplay && QWSDisplay::grabbed()) { | |
QWSDisplay::ungrab(); | |
ungrabbed = true; | |
} | |
for (;;) { | |
fillQueue(); | |
if (clientLock->hasLock(QWSLock::RegionEvent)) | |
break; | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
} | |
if (ungrabbed) | |
QWSDisplay::grab(true); | |
} | |
// check the queue for pending region events | |
QWSEvent *regionEvent = 0; | |
for (int i = 0; i < queue.size(); /* nothing */) { | |
QWSEvent *e = queue.at(i); | |
if (e->type == QWSEvent::Region && e->window() == winId) { | |
QWSRegionEvent *re = static_cast<QWSRegionEvent*>(e); | |
if (re->simpleData.type == QWSRegionEvent::Allocation) { | |
delete regionEvent; | |
regionEvent = re; | |
} | |
queue.removeAt(i); | |
removedEventsCount++; | |
} else { | |
++i; | |
} | |
} | |
if (regionEvent) { | |
qApp->qwsProcessEvent(regionEvent); | |
delete regionEvent; | |
} | |
region_events_count -= removedEventsCount; | |
} | |
bool QWSDisplay::Data::hasPendingRegionEvents() const | |
{ | |
if (clientLock && !clientLock->hasLock(QWSLock::RegionEvent)) | |
return true; | |
return region_events_count > 0; | |
} | |
#endif // QT_NO_QWS_MULTIPROCESS | |
void QWSDisplay::Data::waitForCreation() | |
{ | |
fillQueue(); | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
while (unused_identifiers.count() == 0) { | |
if (csocket) { | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
} | |
fillQueue(); | |
} | |
#endif | |
} | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
void QWSDisplay::Data::waitForPropertyReply() | |
{ | |
if (!csocket) | |
return; | |
fillQueue(); | |
while (qt_fbdpy->getPropertyLen == -2) { | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
fillQueue(); | |
} | |
} | |
#endif | |
#ifndef QT_NO_COP | |
void QWSDisplay::Data::waitForQCopResponse() | |
{ | |
for (;;) { | |
fillQueue(); | |
if (qcop_response) | |
break; | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
if (csocket) { | |
csocket->flush(); | |
csocket->waitForReadyRead(1000); | |
} | |
#endif | |
} | |
queue.prepend(qcop_response); | |
qcop_response = 0; | |
} | |
#endif | |
/*! | |
\class QWSDisplay | |
\brief The QWSDisplay class provides a display for QWS; it is an internal class. | |
\internal | |
\ingroup qws | |
*/ | |
QWSDisplay::QWSDisplay() | |
{ | |
d = new Data(0, qws_single_process); | |
} | |
QWSDisplay::~QWSDisplay() | |
{ | |
delete d; | |
delete lock; | |
lock = 0; | |
} | |
bool QWSDisplay::grabbed() | |
{ | |
return lock->locked(); | |
} | |
void QWSDisplay::grab() | |
{ | |
lock->lock(QLock::Read); | |
} | |
void QWSDisplay::grab(bool write) | |
{ | |
lock->lock(write ? QLock::Write : QLock::Read); | |
} | |
void QWSDisplay::ungrab() | |
{ | |
lock->unlock(); | |
} | |
#if 0 | |
QWSRegionManager *QWSDisplay::regionManager() const | |
{ | |
return d->rgnMan; | |
} | |
#endif | |
bool QWSDisplay::eventPending() const | |
{ | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
d->flush(); | |
#endif | |
d->fillQueue(); | |
return d->queueNotEmpty(); | |
} | |
/* | |
Caller must delete return value! | |
*/ | |
QWSEvent *QWSDisplay::getEvent() | |
{ | |
d->fillQueue(); | |
Q_ASSERT(d->queueNotEmpty()); | |
QWSEvent* e = d->dequeue(); | |
return e; | |
} | |
uchar* QWSDisplay::frameBuffer() const { return qt_screen->base(); } | |
int QWSDisplay::width() const { return qt_screen->width(); } | |
int QWSDisplay::height() const { return qt_screen->height(); } | |
int QWSDisplay::depth() const { return qt_screen->depth(); } | |
int QWSDisplay::pixmapDepth() const { return qt_screen->pixmapDepth(); } | |
bool QWSDisplay::supportsDepth(int depth) const { return qt_screen->supportsDepth(depth); } | |
uchar *QWSDisplay::sharedRam() const { return d->sharedRam; } | |
int QWSDisplay::sharedRamSize() const { return d->sharedRamSize; } | |
#ifndef QT_NO_QWS_PROPERTIES | |
void QWSDisplay::addProperty(int winId, int property) | |
{ | |
QWSAddPropertyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::setProperty(int winId, int property, int mode, const QByteArray &data) | |
{ | |
QWSSetPropertyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
cmd.simpleData.mode = mode; | |
cmd.setData(data.constData(), data.size()); | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::setProperty(int winId, int property, int mode, | |
const char * data) | |
{ | |
QWSSetPropertyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
cmd.simpleData.mode = mode; | |
cmd.setData(data, strlen(data)); | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::removeProperty(int winId, int property) | |
{ | |
QWSRemovePropertyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
d->sendCommand(cmd); | |
} | |
/* | |
It is the caller's responsibility to delete[] \a data. | |
*/ | |
bool QWSDisplay::getProperty(int winId, int property, char *&data, int &len) | |
{ | |
if (d->directServerConnection()) { | |
const char *propertyData; | |
bool retval = qwsServer->d_func()->get_property(winId, property, propertyData, len); | |
if (len <= 0) { | |
data = 0; | |
} else { | |
data = new char[len]; | |
memcpy(data, propertyData, len) ; | |
} | |
return retval; | |
} | |
QWSGetPropertyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
d->sendCommand(cmd); | |
getPropertyLen = -2; | |
getPropertyData = 0; | |
#ifndef QT_NO_QWS_MULTIPROCESS | |
d->waitForPropertyReply(); | |
#endif | |
len = getPropertyLen; | |
data = getPropertyData; | |
getPropertyLen = -2; | |
getPropertyData = 0; | |
return len != -1; | |
} | |
#endif // QT_NO_QWS_PROPERTIES | |
void QWSDisplay::setAltitude(int winId, int alt, bool fixed) | |
{ | |
QWSChangeAltitudeCommand cmd; | |
#ifdef QT_DEBUG | |
memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind | |
#endif | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.altitude = QWSChangeAltitudeCommand::Altitude(alt); | |
cmd.simpleData.fixed = fixed; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->set_altitude(&cmd); | |
} else { | |
d->sendSynchronousCommand(cmd); | |
} | |
} | |
void QWSDisplay::setOpacity(int winId, int opacity) | |
{ | |
QWSSetOpacityCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.opacity = opacity; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->set_opacity(&cmd); | |
} else { | |
d->sendCommand(cmd); | |
} | |
} | |
void QWSDisplay::requestFocus(int winId, bool get) | |
{ | |
QWSRequestFocusCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.flag = get; | |
if (d->directServerConnection()) | |
qwsServer->d_func()->request_focus(&cmd); | |
else | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::setIdentity(const QString &appName) | |
{ | |
QWSIdentifyCommand cmd; | |
#ifdef QT_NO_QWS_MULTIPROCESS | |
const int id = -1; | |
#else | |
const int id = QWSDisplay::Data::clientLock ? QWSDisplay::Data::clientLock->id() : -1; | |
#endif | |
cmd.setId(appName, id); | |
if (d->directServerConnection()) | |
qwsServer->d_func()->set_identity(&cmd); | |
else | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::nameRegion(int winId, const QString& n, const QString &c) | |
{ | |
QWSRegionNameCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.setName(n, c); | |
if (d->directServerConnection()) | |
qwsServer->d_func()->name_region(&cmd); | |
else | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::requestRegion(int winId, const QString &surfaceKey, | |
const QByteArray &surfaceData, | |
const QRegion ®ion) | |
{ | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->request_region(winId, surfaceKey, | |
surfaceData, region); | |
} else { | |
QWSRegionCommand cmd; | |
cmd.setData(winId, surfaceKey, surfaceData, region); | |
d->sendSynchronousCommand(cmd); | |
} | |
} | |
void QWSDisplay::repaintRegion(int winId, int windowFlags, bool opaque, QRegion r) | |
{ | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->repaint_region(winId, windowFlags, opaque, r); | |
} else { | |
QVector<QRect> ra = r.rects(); | |
/* | |
for (int i = 0; i < ra.size(); i++) { | |
QRect r(ra[i]); | |
qDebug("rect: %d %d %d %d", r.x(), r.y(), r.right(), r.bottom()); | |
} | |
*/ | |
QWSRepaintRegionCommand cmd; | |
/* XXX QWSRegionCommand is padded out in a compiler dependent way. | |
Zeroed out to avoid valgrind reporting uninitialized memory usage. | |
*/ | |
#ifdef QT_DEBUG | |
memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind | |
#endif | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.windowFlags = windowFlags; | |
cmd.simpleData.opaque = opaque; | |
cmd.simpleData.nrectangles = ra.count(); | |
cmd.setData(reinterpret_cast<const char *>(ra.constData()), | |
ra.count() * sizeof(QRect), false); | |
d->sendSynchronousCommand(cmd); | |
} | |
} | |
void QWSDisplay::moveRegion(int winId, int dx, int dy) | |
{ | |
QWSRegionMoveCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.dx = dx; | |
cmd.simpleData.dy = dy; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->move_region(&cmd); | |
} else { | |
d->sendSynchronousCommand(cmd); | |
} | |
// d->offsetPendingExpose(winId, QPoint(cmd.simpleData.dx, cmd.simpleData.dy)); | |
} | |
void QWSDisplay::destroyRegion(int winId) | |
{ | |
QWSRegionDestroyCommand cmd; | |
cmd.simpleData.windowid = winId; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->destroy_region(&cmd); | |
} else { | |
d->sendCommand(cmd); | |
} | |
} | |
#ifndef QT_NO_QWS_INPUTMETHODS | |
void QWSDisplay::sendIMUpdate(int type, int winId, int widgetid) | |
{ | |
QWSIMUpdateCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.widgetid = widgetid; | |
cmd.simpleData.type = type; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->im_update(&cmd); | |
} else { | |
d->sendCommand(cmd); | |
} | |
} | |
void QWSDisplay::sendIMResponse(int winId, int property, const QVariant &result) | |
{ | |
QWSIMResponseCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.property = property; | |
cmd.setResult(result); | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->im_response(&cmd); | |
} else { | |
d->sendCommand(cmd); | |
} | |
} | |
void QWSDisplay::resetIM() | |
{ | |
sendIMUpdate(QWSInputMethod::Reset, -1, -1); | |
} | |
void QWSDisplay::sendIMMouseEvent(int index, bool isPress) | |
{ | |
QWSIMMouseCommand cmd; | |
cmd.simpleData.index = index; | |
cmd.simpleData.state = isPress ? QWSServer::MousePress : QWSServer::MouseRelease; | |
if (d->directServerConnection()) { | |
qwsServer->d_func()->send_im_mouse(&cmd); | |
} else { | |
d->sendCommand(cmd); | |
} | |
} | |
#endif | |
int QWSDisplay::takeId() | |
{ | |
return d->takeId(); | |
} | |
bool QWSDisplay::initLock(const QString &filename, bool create) | |
{ | |
if (!lock) { | |
lock = new QLock(filename, 'd', create); | |
if (!lock->isValid()) { | |
delete lock; | |
lock = 0; | |
return false; | |
} | |
} | |
return true; | |
} | |
void QWSDisplay::setSelectionOwner(int winId, const QTime &time) | |
{ | |
QWSSetSelectionOwnerCommand cmd; | |
cmd.simpleData.windowid = winId; | |
cmd.simpleData.hour = time.hour(); | |
cmd.simpleData.minute = time.minute(); | |
cmd.simpleData.sec = time.second(); | |
cmd.simpleData.ms = time.msec(); | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::convertSelection(int winId, int selectionProperty, const QString &mimeTypes) | |
{ | |
#ifdef QT_NO_QWS_PROPERTIES | |
Q_UNUSED(mimeTypes); | |
#else | |
// ### we need the atom/property thingy like in X here | |
addProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION); | |
setProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION, | |
int(QWSPropertyManager::PropReplace), mimeTypes.toLatin1()); | |
#endif | |
QWSConvertSelectionCommand cmd; | |
cmd.simpleData.requestor = winId; | |
cmd.simpleData.selection = selectionProperty; | |
cmd.simpleData.mimeTypes = QT_QWS_PROPERTY_CONVERTSELECTION; | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::defineCursor(int id, const QBitmap &curs, const QBitmap &mask, | |
int hotX, int hotY) | |
{ | |
const QImage cursImg = curs.toImage().convertToFormat(QImage::Format_MonoLSB); | |
const QImage maskImg = mask.toImage().convertToFormat(QImage::Format_MonoLSB); | |
QWSDefineCursorCommand cmd; | |
cmd.simpleData.width = curs.width(); | |
cmd.simpleData.height = curs.height(); | |
cmd.simpleData.hotX = hotX; | |
cmd.simpleData.hotY = hotY; | |
cmd.simpleData.id = id; | |
// must copy each scanline since there might be gaps between them | |
const int height = curs.height(); | |
const int width = curs.width(); | |
const int dst_bpl = (width + 7) / 8; | |
int dataLen = dst_bpl * height; | |
uchar *data = new uchar[dataLen*2]; | |
uchar *dst = data; | |
int src_bpl = cursImg.bytesPerLine(); | |
const uchar *cursSrc = cursImg.bits(); | |
for (int i = 0; i < height; ++i) { | |
memcpy(dst, cursSrc + i*src_bpl, dst_bpl); | |
dst += dst_bpl; | |
} | |
src_bpl = maskImg.bytesPerLine(); | |
const uchar *maskSrc = maskImg.bits(); | |
for (int i = 0; i < height; ++i) { | |
memcpy(dst, maskSrc + i*src_bpl, dst_bpl); | |
dst += dst_bpl; | |
} | |
cmd.setData(reinterpret_cast<char*>(data), dataLen*2); | |
delete [] data; | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::destroyCursor(int id) | |
{ | |
QWSDefineCursorCommand cmd; | |
cmd.simpleData.width = 0; | |
cmd.simpleData.height = 0; | |
cmd.simpleData.hotX = 0; | |
cmd.simpleData.hotY = 0; | |
cmd.simpleData.id = id; | |
cmd.setData(0, 0); | |
d->sendCommand(cmd); | |
} | |
#ifndef QT_NO_SOUND | |
void QWSDisplay::playSoundFile(const QString& f) | |
{ | |
QWSPlaySoundCommand cmd; | |
cmd.setFileName(f); | |
d->sendCommand(cmd); | |
} | |
#endif | |
#ifndef QT_NO_COP | |
void QWSDisplay::registerChannel(const QString& channel) | |
{ | |
QWSQCopRegisterChannelCommand reg; | |
reg.setChannel(channel); | |
qt_fbdpy->d->sendCommand(reg); | |
} | |
void QWSDisplay::sendMessage(const QString &channel, const QString &msg, | |
const QByteArray &data) | |
{ | |
QWSQCopSendCommand com; | |
com.setMessage(channel, msg, data); | |
qt_fbdpy->d->sendCommand(com); | |
} | |
void QWSDisplay::flushCommands() | |
{ | |
qt_fbdpy->d->flushCommands(); | |
} | |
/* | |
caller deletes result | |
*/ | |
QWSQCopMessageEvent* QWSDisplay::waitForQCopResponse() | |
{ | |
qt_fbdpy->d->waitForQCopResponse(); | |
QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(qt_fbdpy->d->dequeue()); | |
Q_ASSERT(e->type == QWSEvent::QCopMessage); | |
return e; | |
} | |
#endif | |
void QWSDisplay::sendFontCommand(int type, const QByteArray &fontName) | |
{ | |
QWSFontCommand cmd; | |
cmd.simpleData.type = type; | |
cmd.setFontName(fontName); | |
d->sendCommand(cmd); | |
} | |
void QWSDisplay::setWindowCaption(QWidget *w, const QString &c) | |
{ | |
if (w->isWindow()) { | |
nameRegion(w->internalWinId(), w->objectName(), c); | |
static_cast<QETWidget *>(w)->repaintDecoration(qApp->desktop()->rect(), true); | |
} | |
} | |
void QWSDisplay::selectCursor(QWidget *w, unsigned int cursId) | |
{ | |
if (cursId != qt_last_cursor) | |
{ | |
QWidget *top = w->window(); | |
qt_last_cursor = cursId; | |
QWSSelectCursorCommand cmd; | |
cmd.simpleData.windowid = top->internalWinId(); | |
cmd.simpleData.id = cursId; | |
d->sendCommand(cmd); | |
d->flush(); | |
} | |
} | |
void QWSDisplay::setCursorPosition(int x, int y) | |
{ | |
QWSPositionCursorCommand cmd; | |
cmd.simpleData.newX = x; | |
cmd.simpleData.newY = y; | |
d->sendCommand(cmd); | |
d->flush(); | |
} | |
void QWSDisplay::grabMouse(QWidget *w, bool grab) | |
{ | |
QWidget *top = w->window(); | |
QWSGrabMouseCommand cmd; | |
#ifdef QT_DEBUG | |
memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind | |
#endif | |
cmd.simpleData.windowid = top->winId(); | |
cmd.simpleData.grab = grab; | |
d->sendCommand(cmd); | |
d->flush(); | |
} | |
void QWSDisplay::grabKeyboard(QWidget *w, bool grab) | |
{ | |
QWidget *top = w->window(); | |
QWSGrabKeyboardCommand cmd; | |
#ifdef QT_DEBUG | |
memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind | |
#endif | |
cmd.simpleData.windowid = top->winId(); | |
cmd.simpleData.grab = grab; | |
d->sendCommand(cmd); | |
d->flush(); | |
} | |
QList<QWSWindowInfo> QWSDisplay::windowList() | |
{ | |
QList<QWSWindowInfo> ret; | |
if(d->directServerConnection()) { | |
QList<QWSInternalWindowInfo*> * qin=QWSServer::windowList(); | |
for (int i = 0; i < qin->count(); ++i) { | |
QWSInternalWindowInfo * qwi = qin->at(i); | |
QWSWindowInfo tmp; | |
tmp.winid = qwi->winid; | |
tmp.clientid = qwi->clientid; | |
tmp.name = QString(qwi->name); | |
ret.append(tmp); | |
} | |
qDeleteAll(*qin); | |
delete qin; | |
} | |
return ret; | |
} | |
int QWSDisplay::windowAt(const QPoint &p) | |
{ | |
//### currently only implemented for the server process | |
int ret = 0; | |
if(d->directServerConnection()) { | |
QWSWindow *win = qwsServer->windowAt(p); | |
if (win) | |
return win->winId(); | |
} | |
return ret; | |
} | |
void QWSDisplay::setRawMouseEventFilter(void (*filter)(QWSMouseEvent *)) | |
{ | |
if (qt_fbdpy) | |
qt_fbdpy->d->setMouseFilter(filter); | |
} | |
/*! | |
\relates QScreen | |
Here it is. \a transformation and \a screenNo | |
*/ | |
void QWSDisplay::setTransformation(int transformation, int screenNo) | |
{ | |
QWSScreenTransformCommand cmd; | |
cmd.setTransformation(screenNo, transformation); | |
QWSDisplay::instance()->d->sendCommand(cmd); | |
} | |
static bool qt_try_modal(QWidget *, QWSEvent *); | |
/***************************************************************************** | |
qt_init() - initializes Qt/FB | |
*****************************************************************************/ | |
static void qt_set_qws_resources() | |
{ | |
if (QApplication::desktopSettingsAware()) | |
QApplicationPrivate::qws_apply_settings(); | |
if (appFont) | |
QApplication::setFont(QFont(QString::fromLocal8Bit(appFont))); | |
if (appBGCol || appBTNCol || appFGCol) { | |
(void) QApplication::style(); // trigger creation of application style and system palettes | |
QColor btn; | |
QColor bg; | |
QColor fg; | |
if (appBGCol) | |
bg = QColor(appBGCol); | |
else | |
bg = QApplicationPrivate::sys_pal->color(QPalette::Window); | |
if (appFGCol) | |
fg = QColor(appFGCol); | |
else | |
fg = QApplicationPrivate::sys_pal->color(QPalette::WindowText); | |
if (appBTNCol) | |
btn = QColor(appBTNCol); | |
else | |
btn = QApplicationPrivate::sys_pal->color(QPalette::Button); | |
int h,s,v; | |
fg.getHsv(&h,&s,&v); | |
QColor base = Qt::white; | |
bool bright_mode = false; | |
if (v >= 255 - 50) { | |
base = btn.darker(150); | |
bright_mode = true; | |
} | |
QPalette pal(fg, btn, btn.lighter(), btn.darker(), btn.darker(150), fg, Qt::white, base, bg); | |
if (bright_mode) { | |
pal.setColor(QPalette::HighlightedText, base); | |
pal.setColor(QPalette::Highlight, Qt::white); | |
} else { | |
pal.setColor(QPalette::HighlightedText, Qt::white); | |
pal.setColor(QPalette::Highlight, Qt::darkBlue); | |
} | |
QColor disabled((fg.red() + btn.red()) / 2, | |
(fg.green() + btn.green())/ 2, | |
(fg.blue() + btn.blue()) / 2); | |
pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125), | |
btn.darker(), btn.darker(150), disabled, Qt::white, Qt::white, bg); | |
if (bright_mode) { | |
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base); | |
pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white); | |
} else { | |
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white); | |
pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue); | |
} | |
QApplicationPrivate::setSystemPalette(pal); | |
} | |
} | |
void QApplicationPrivate::initializeWidgetPaletteHash() | |
{ | |
} | |
/*! \internal | |
apply the settings to the application | |
*/ | |
bool QApplicationPrivate::qws_apply_settings() | |
{ | |
#ifndef QT_NO_SETTINGS | |
QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); | |
settings.beginGroup(QLatin1String("Qt")); | |
QStringList strlist; | |
int i; | |
QPalette pal(Qt::black); | |
int groupCount = 0; | |
strlist = settings.value(QLatin1String("Palette/active")).toStringList(); | |
if (strlist.count() == QPalette::NColorRoles) { | |
++groupCount; | |
for (i = 0; i < QPalette::NColorRoles; i++) | |
pal.setColor(QPalette::Active, (QPalette::ColorRole) i, | |
QColor(strlist[i])); | |
} | |
strlist = settings.value(QLatin1String("Palette/inactive")).toStringList(); | |
if (strlist.count() == QPalette::NColorRoles) { | |
++groupCount; | |
for (i = 0; i < QPalette::NColorRoles; i++) | |
pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i, | |
QColor(strlist[i])); | |
} | |
strlist = settings.value(QLatin1String("Palette/disabled")).toStringList(); | |
if (strlist.count() == QPalette::NColorRoles) { | |
++groupCount; | |
for (i = 0; i < QPalette::NColorRoles; i++) | |
pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i, | |
QColor(strlist[i])); | |
} | |
if (groupCount == QPalette::NColorGroups) | |
QApplicationPrivate::setSystemPalette(pal); | |
QString str = settings.value(QLatin1String("font")).toString(); | |
if (!str.isEmpty()) { | |
QFont font(QApplication::font()); | |
font.fromString(str); | |
QApplicationPrivate::setSystemFont(font); | |
} | |
// read library (ie. plugin) path list | |
QString libpathkey = | |
QString::fromLatin1("%1.%2/libraryPath") | |
.arg(QT_VERSION >> 16) | |
.arg((QT_VERSION & 0xff00) >> 8); | |
QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':')); | |
#ifndef QT_NO_LIBRARY | |
if (! pathlist.isEmpty()) { | |
QStringList::ConstIterator it = pathlist.constBegin(); | |
while (it != pathlist.constEnd()) | |
QApplication::addLibraryPath(*it++); | |
} | |
#endif | |
// read new QStyle | |
QString stylename = settings.value(QLatin1String("style")).toString(); | |
if (QCoreApplication::startingUp()) { | |
if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull()) | |
QApplicationPrivate::styleOverride = stylename; | |
} else { | |
QApplication::setStyle(stylename); | |
} | |
int num = | |
settings.value(QLatin1String("doubleClickInterval"), | |
QApplication::doubleClickInterval()).toInt(); | |
QApplication::setDoubleClickInterval(num); | |
num = | |
settings.value(QLatin1String("cursorFlashTime"), | |
QApplication::cursorFlashTime()).toInt(); | |
QApplication::setCursorFlashTime(num); | |
#ifndef QT_NO_WHEELEVENT | |
num = | |
settings.value(QLatin1String("wheelScrollLines"), | |
QApplication::wheelScrollLines()).toInt(); | |
QApplication::setWheelScrollLines(num); | |
#endif | |
QString colorspec = settings.value(QLatin1String("colorSpec"), | |
QVariant(QLatin1String("default"))).toString(); | |
if (colorspec == QLatin1String("normal")) | |
QApplication::setColorSpec(QApplication::NormalColor); | |
else if (colorspec == QLatin1String("custom")) | |
QApplication::setColorSpec(QApplication::CustomColor); | |
else if (colorspec == QLatin1String("many")) | |
QApplication::setColorSpec(QApplication::ManyColor); | |
else if (colorspec != QLatin1String("default")) | |
colorspec = QLatin1String("default"); | |
#ifndef QT_NO_TEXTCODEC | |
QString defaultcodec = settings.value(QLatin1String("defaultCodec"), | |
QVariant(QLatin1String("none"))).toString(); | |
if (defaultcodec != QLatin1String("none")) { | |
QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1()); | |
if (codec) | |
QTextCodec::setCodecForTr(codec); | |
} | |
#endif | |
int w = settings.value(QLatin1String("globalStrut/width")).toInt(); | |
int h = settings.value(QLatin1String("globalStrut/height")).toInt(); | |
QSize strut(w, h); | |
if (strut.isValid()) | |
QApplication::setGlobalStrut(strut); | |
QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList(); | |
QApplication::setEffectEnabled(Qt::UI_General, | |
effects.contains(QLatin1String("general"))); | |
QApplication::setEffectEnabled(Qt::UI_AnimateMenu, | |
effects.contains(QLatin1String("animatemenu"))); | |
QApplication::setEffectEnabled(Qt::UI_FadeMenu, | |
effects.contains(QLatin1String("fademenu"))); | |
QApplication::setEffectEnabled(Qt::UI_AnimateCombo, | |
effects.contains(QLatin1String("animatecombo"))); | |
QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, | |
effects.contains(QLatin1String("animatetooltip"))); | |
QApplication::setEffectEnabled(Qt::UI_FadeTooltip, | |
effects.contains(QLatin1String("fadetooltip"))); | |
QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, | |
effects.contains(QLatin1String("animatetoolbox"))); | |
settings.beginGroup(QLatin1String("Font Substitutions")); | |
QStringList fontsubs = settings.childKeys(); | |
if (!fontsubs.isEmpty()) { | |
QStringList::Iterator it = fontsubs.begin(); | |
for (; it != fontsubs.end(); ++it) { | |
QString fam = *it; | |
QStringList subs = settings.value(fam).toStringList(); | |
QFont::insertSubstitutions(fam, subs); | |
} | |
} | |
settings.endGroup(); | |
settings.endGroup(); // Qt | |
settings.beginGroup(QLatin1String("QWS Font Fallbacks")); | |
if (!settings.childKeys().isEmpty()) { | |
// from qfontdatabase_qws.cpp | |
extern void qt_applyFontDatabaseSettings(const QSettings &); | |
qt_applyFontDatabaseSettings(settings); | |
} | |
settings.endGroup(); | |
return true; | |
#else | |
return false; | |
#endif // QT_NO_SETTINGS | |
} | |
static void init_display() | |
{ | |
if (qt_fbdpy) return; // workaround server==client case | |
// Connect to FB server | |
qt_fbdpy = new QWSDisplay(); | |
// Get display parameters | |
// Set paintdevice parameters | |
// XXX initial info sent from server | |
// Misc. initialization | |
QColormap::initialize(); | |
QFont::initialize(); | |
#ifndef QT_NO_CURSOR | |
QCursorData::initialize(); | |
#endif | |
qApp->setObjectName(appName); | |
if (!QApplicationPrivate::sys_font) { | |
#ifdef QT_NO_FREETYPE | |
QFont f = QFont(QLatin1String("helvetica"), 10); | |
#else | |
QFont f = QFont(QLatin1String("DejaVu Sans"), 12); | |
#endif | |
QApplicationPrivate::setSystemFont(f); | |
} | |
qt_set_qws_resources(); | |
} | |
void qt_init_display() | |
{ | |
qt_is_gui_used = true; | |
qws_single_process = true; | |
init_display(); | |
} | |
static bool read_bool_env_var(const char *var, bool defaultvalue) | |
{ | |
// returns true if env variable is set to non-zero | |
// returns false if env var is set to zero | |
// returns defaultvalue if env var not set | |
char *x = ::getenv(var); | |
return (x && *x) ? (strcmp(x,"0") != 0) : defaultvalue; | |
} | |
static int read_int_env_var(const char *var, int defaultvalue) | |
{ | |
bool ok; | |
int r = qgetenv(var).toInt(&ok); | |
return ok ? r : defaultvalue; | |
} | |
void qt_init(QApplicationPrivate *priv, int type) | |
{ | |
#ifdef QT_NO_QWS_MULTIPROCESS | |
if (type == QApplication::GuiClient) | |
type = QApplication::GuiServer; | |
#endif | |
if (type == QApplication::GuiServer) | |
qt_is_gui_used = false; //we'll turn it on in a second | |
qws_sw_cursor = read_bool_env_var("QWS_SW_CURSOR",qws_sw_cursor); | |
qws_screen_is_interlaced = read_bool_env_var("QWS_INTERLACE",false); | |
const char *display = ::getenv("QWS_DISPLAY"); | |
if (display) | |
qws_display_spec = display; // since we setenv later! | |
//qws_savefonts = qgetenv("QWS_SAVEFONTS") != 0; | |
//qws_shared_memory = qgetenv("QWS_NOSHARED") == 0; | |
mouse_double_click_distance = read_int_env_var("QWS_DBLCLICK_DISTANCE", 5); | |
priv->inputContext = 0; | |
int flags = 0; | |
char *p; | |
int argc = priv->argc; | |
char **argv = priv->argv; | |
int j; | |
// Set application name | |
if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms | |
p = strrchr(argv[0], '/'); | |
appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); | |
} | |
// Get command line params | |
j = argc ? 1 : 0; | |
QString decoration; | |
for (int i=1; i<argc; i++) { | |
if (argv[i] && *argv[i] != '-') { | |
argv[j++] = argv[i]; | |
continue; | |
} | |
QByteArray arg = argv[i]; | |
if (arg == "-fn" || arg == "-font") { | |
if (++i < argc) | |
appFont = argv[i]; | |
} else if (arg == "-bg" || arg == "-background") { | |
if (++i < argc) | |
appBGCol = argv[i]; | |
} else if (arg == "-btn" || arg == "-button") { | |
if (++i < argc) | |
appBTNCol = argv[i]; | |
} else if (arg == "-fg" || arg == "-foreground") { | |
if (++i < argc) | |
appFGCol = argv[i]; | |
} else if (arg == "-name") { | |
if (++i < argc) | |
appName = QString::fromLocal8Bit(argv[i]); | |
} else if (arg == "-title") { | |
if (++i < argc) | |
mwTitle = argv[i]; | |
} else if (arg == "-geometry") { | |
if (++i < argc) | |
mwGeometry = argv[i]; | |
} else if (arg == "-shared") { | |
qws_shared_memory = true; | |
} else if (arg == "-noshared") { | |
qws_shared_memory = false; | |
} else if (arg == "-savefonts") { | |
qws_savefonts = true; | |
} else if (arg == "-nosavefonts") { | |
qws_savefonts = false; | |
} else if (arg == "-swcursor") { | |
qws_sw_cursor = true; | |
} else if (arg == "-noswcursor") { | |
qws_sw_cursor = false; | |
} else if (arg == "-keyboard") { | |
flags &= ~QWSServer::DisableKeyboard; | |
} else if (arg == "-nokeyboard") { | |
flags |= QWSServer::DisableKeyboard; | |
} else if (arg == "-mouse") { | |
flags &= ~QWSServer::DisableMouse; | |
} else if (arg == "-nomouse") { | |
flags |= QWSServer::DisableMouse; | |
} else if (arg == "-qws") { | |
type = QApplication::GuiServer; | |
} else if (arg == "-interlaced") { | |
qws_screen_is_interlaced = true; | |
} else if (arg == "-display") { | |
if (++i < argc) | |
qws_display_spec = argv[i]; | |
} else if (arg == "-decoration") { | |
if (++i < argc) | |
decoration = QString::fromLocal8Bit(argv[i]); | |
} else { | |
argv[j++] = argv[i]; | |
} | |
} | |
if(j < priv->argc) { | |
priv->argv[j] = 0; | |
priv->argc = j; | |
} | |
mouseInWidget = new QPointer<QWidget>; | |
const QString disp = QString::fromLatin1(qws_display_spec); | |
QRegExp regexp(QLatin1String(":(\\d+)$")); | |
if (regexp.lastIndexIn(disp) != -1) { | |
const QString capture = regexp.cap(1); | |
bool ok = false; | |
int id = capture.toInt(&ok); | |
if (ok) | |
qws_display_id = id; | |
} | |
if (type == QApplication::GuiServer) { | |
qt_appType = QApplication::Type(type); | |
qws_single_process = true; | |
QWSServer::startup(flags); | |
if (!display) // if not already set | |
qputenv("QWS_DISPLAY", qws_display_spec); | |
} | |
if(qt_is_gui_used) { | |
init_display(); | |
#ifndef QT_NO_QWS_MANAGER | |
if (decoration.isEmpty() && !qws_decoration) { | |
const QStringList keys = QDecorationFactory::keys(); | |
if (!keys.isEmpty()) | |
decoration = keys.first(); | |
} | |
if (!decoration.isEmpty()) | |
qws_decoration = QApplication::qwsSetDecoration(decoration); | |
#endif // QT_NO_QWS_MANAGER | |
#ifndef QT_NO_QWS_INPUTMETHODS | |
qApp->setInputContext(new QWSInputContext(qApp)); | |
#endif | |
} | |
/*### convert interlace style | |
if (qws_screen_is_interlaced) | |
QApplication::setStyle(new QInterlaceStyle); | |
*/ | |
} | |
/***************************************************************************** | |
qt_cleanup() - cleans up when the application is finished | |
*****************************************************************************/ | |
void qt_cleanup() | |
{ | |
QPixmapCache::clear(); | |
#ifndef QT_NO_CURSOR | |
QCursorData::cleanup(); | |
#endif | |
QFont::cleanup(); | |
QColormap::cleanup(); | |
if (qws_single_process) { | |
QWSServer::closedown(); | |
} | |
qDeleteAll(outgoing); | |
outgoing.clear(); | |
qDeleteAll(incoming); | |
incoming.clear(); | |
if (qt_is_gui_used) { | |
delete qt_fbdpy; | |
} | |
qt_fbdpy = 0; | |
#ifndef QT_NO_QWS_MANAGER | |
delete qws_decoration; | |
qws_decoration = 0; | |
#endif | |
delete mouseInWidget; | |
mouseInWidget = 0; | |
#if !defined(QT_NO_IM) | |
delete QApplicationPrivate::inputContext; | |
QApplicationPrivate::inputContext = 0; | |
#endif | |
} | |
/***************************************************************************** | |
Platform specific global and internal functions | |
*****************************************************************************/ | |
QString QApplicationPrivate::appName() const // get application name | |
{ | |
return QT_PREPEND_NAMESPACE(appName); | |
} | |
/***************************************************************************** | |
Platform specific QApplication members | |
*****************************************************************************/ | |
#define NoValue 0x0000 | |
#define XValue 0x0001 | |
#define YValue 0x0002 | |
#define WidthValue 0x0004 | |
#define HeightValue 0x0008 | |
#define AllValues 0x000F | |
#define XNegative 0x0010 | |
#define YNegative 0x0020 | |
/* Copyright notice for ReadInteger and parseGeometry | |
Copyright (c) 1985, 1986, 1987 X Consortium | |
Permission is hereby granted, free of charge, to any person obtaining | |
a copy of this software and associated documentation files (the | |
"Software"), to deal in the Software without restriction, including | |
without limitation the rights to use, copy, modify, merge, publish, | |
distribute, sublicense, and/or sell copies of the Software, and to | |
permit persons to whom the Software is furnished to do so, subject to | |
the following conditions: | |
The above copyright notice and this permission notice shall be included | |
in all copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
OTHER DEALINGS IN THE SOFTWARE. | |
Except as contained in this notice, the name of the X Consortium shall | |
not be used in advertising or otherwise to promote the sale, use or | |
other dealings in this Software without prior written authorization | |
from the X Consortium. | |
*/ | |
/* | |
* XParseGeometry parses strings of the form | |
* "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where | |
* width, height, xoffset, and yoffset are unsigned integers. | |
* Example: "=80x24+300-49" | |
* The equal sign is optional. | |
* It returns a bitmask that indicates which of the four values | |
* were actually found in the string. For each value found, | |
* the corresponding argument is updated; for each value | |
* not found, the corresponding argument is left unchanged. | |
*/ | |
static int | |
ReadInteger(char *string, char **NextString) | |
{ | |
register int Result = 0; | |
int Sign = 1; | |
if (*string == '+') | |
string++; | |
else if (*string == '-') | |
{ | |
string++; | |
Sign = -1; | |
} | |
for (; (*string >= '0') && (*string <= '9'); string++) | |
{ | |
Result = (Result * 10) + (*string - '0'); | |
} | |
*NextString = string; | |
if (Sign >= 0) | |
return Result; | |
else | |
return -Result; | |
} | |
static int parseGeometry(const char* string, | |
int* x, int* y, int* width, int* height) | |
{ | |
int mask = NoValue; | |
register char *strind; | |
unsigned int tempWidth=0, tempHeight=0; | |
int tempX=0, tempY=0; | |
char *nextCharacter; | |
if (!string || (*string == '\0')) return mask; | |
if (*string == '=') | |
string++; /* ignore possible '=' at beg of geometry spec */ | |
strind = const_cast<char *>(string); | |
if (*strind != '+' && *strind != '-' && *strind != 'x') { | |
tempWidth = ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
mask |= WidthValue; | |
} | |
if (*strind == 'x' || *strind == 'X') { | |
strind++; | |
tempHeight = ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
mask |= HeightValue; | |
} | |
if ((*strind == '+') || (*strind == '-')) { | |
if (*strind == '-') { | |
strind++; | |
tempX = -ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
mask |= XNegative; | |
} | |
else | |
{ strind++; | |
tempX = ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
} | |
mask |= XValue; | |
if ((*strind == '+') || (*strind == '-')) { | |
if (*strind == '-') { | |
strind++; | |
tempY = -ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
mask |= YNegative; | |
} | |
else | |
{ | |
strind++; | |
tempY = ReadInteger(strind, &nextCharacter); | |
if (strind == nextCharacter) | |
return 0; | |
strind = nextCharacter; | |
} | |
mask |= YValue; | |
} | |
} | |
/* If strind isn't at the end of the string then it's an invalid | |
geometry specification. */ | |
if (*strind != '\0') return 0; | |
if (mask & XValue) | |
*x = tempX; | |
if (mask & YValue) | |
*y = tempY; | |
if (mask & WidthValue) | |
*width = tempWidth; | |
if (mask & HeightValue) | |
*height = tempHeight; | |
return mask; | |
} | |
#ifdef QT3_SUPPORT | |
void QApplication::setMainWidget(QWidget *mainWidget) | |
{ | |
QApplicationPrivate::main_widget = mainWidget; | |
if (QApplicationPrivate::main_widget) // give WM command line | |
QApplicationPrivate::applyQWSSpecificCommandLineArguments(QApplicationPrivate::main_widget); | |
} | |
#endif | |
void QApplicationPrivate::applyQWSSpecificCommandLineArguments(QWidget *main_widget) | |
{ | |
static bool beenHereDoneThat = false; | |
if (beenHereDoneThat) | |
return; | |
beenHereDoneThat = true; | |
if (qApp->windowIcon().isNull() && main_widget->testAttribute(Qt::WA_SetWindowIcon)) | |
qApp->setWindowIcon(main_widget->windowIcon()); | |
if (mwTitle) // && main_widget->windowTitle().isEmpty()) | |
main_widget->setWindowTitle(QString::fromLocal8Bit(mwTitle)); | |
if (mwGeometry) { // parse geometry | |
int x = 0; | |
int y = 0; | |
int w = 0; | |
int h = 0; | |
int m = parseGeometry(mwGeometry, &x, &y, &w, &h); | |
QSize minSize = main_widget->minimumSize(); | |
QSize maxSize = main_widget->maximumSize(); | |
if ((m & XValue) == 0) | |
x = main_widget->geometry().x(); | |
if ((m & YValue) == 0) | |
y = main_widget->geometry().y(); | |
if ((m & WidthValue) == 0) | |
w = main_widget->width(); | |
if ((m & HeightValue) == 0) | |
h = main_widget->height(); | |
w = qMin(w,maxSize.width()); | |
h = qMin(h,maxSize.height()); | |
w = qMax(w,minSize.width()); | |
h = qMax(h,minSize.height()); | |
if ((m & XNegative)) { | |
x = qApp->desktop()->width() + x - w; | |
x -= (main_widget->frameGeometry().width() - main_widget->width()) / 2; | |
} else { | |
x += (main_widget->geometry().x() - main_widget->x()); | |
} | |
if ((m & YNegative)) { | |
y = qApp->desktop()->height() + y - h; | |
} else { | |
y += (main_widget->geometry().y() - main_widget->y()); | |
} | |
main_widget->setGeometry(x, y, w, h); | |
} | |
} | |
/***************************************************************************** | |
QApplication cursor stack | |
*****************************************************************************/ | |
#ifndef QT_NO_CURSOR | |
void QApplication::setOverrideCursor(const QCursor &cursor) | |
{ | |
qApp->d_func()->cursor_list.prepend(cursor); | |
QWidget *w = QWidget::mouseGrabber(); | |
if (!w && qt_last_x) | |
w = topLevelAt(*qt_last_x, *qt_last_y); | |
if (!w) | |
w = desktop(); | |
QPaintDevice::qwsDisplay()->selectCursor(w, qApp->d_func()->cursor_list.first().handle()); | |
} | |
void QApplication::restoreOverrideCursor() | |
{ | |
if (qApp->d_func()->cursor_list.isEmpty()) | |
return; | |
qApp->d_func()->cursor_list.removeFirst(); | |
QWidget *w = QWidget::mouseGrabber(); | |
if (!w && qt_last_x) | |
w = topLevelAt(*qt_last_x, *qt_last_y); | |
if (!w) | |
w = desktop(); | |
int cursor_handle = Qt::ArrowCursor; | |
if (qApp->d_func()->cursor_list.isEmpty()) { | |
qws_overrideCursor = false; | |
QWidget *upw = QApplication::widgetAt(*qt_last_x, *qt_last_y); | |
if (upw) | |
cursor_handle = upw->cursor().handle(); | |
} else { | |
cursor_handle = qApp->d_func()->cursor_list.first().handle(); | |
} | |
QPaintDevice::qwsDisplay()->selectCursor(w, cursor_handle); | |
} | |
#endif// QT_NO_CURSOR | |
/***************************************************************************** | |
Routines to find a Qt widget from a screen position | |
*****************************************************************************/ | |
/*! | |
\internal | |
*/ | |
QWidget *QApplicationPrivate::findWidget(const QObjectList& list, | |
const QPoint &pos, bool rec) | |
{ | |
QWidget *w; | |
for (int i = list.size()-1; i >= 0; --i) { | |
if (list.at(i)->isWidgetType()) { | |
w = static_cast<QWidget*>(list.at(i)); | |
if (w->isVisible() && !w->testAttribute(Qt::WA_TransparentForMouseEvents) && w->geometry().contains(pos) | |
&& (!w->d_func()->extra || w->d_func()->extra->mask.isEmpty() || w->d_func()->extra->mask.contains(pos - w->geometry().topLeft()) )) { | |
if (!rec) | |
return w; | |
QWidget *c = w->childAt(w->mapFromParent(pos)); | |
return c ? c : w; | |
} | |
} | |
} | |
return 0; | |
} | |
QWidget *QApplication::topLevelAt(const QPoint &pos) | |
{ | |
//### QWSDisplay::windowAt() is currently only implemented in the server process | |
int winId = QPaintDevice::qwsDisplay()->windowAt(pos); | |
if (winId !=0) | |
return QWidget::find(winId); | |
#if 1 | |
// fallback implementation for client processes | |
//### This is slightly wrong: we have no guarantee that the list is in | |
//### stacking order, so if the topmost window is transparent, we may | |
//### return the wrong widget | |
QWidgetList list = topLevelWidgets(); | |
for (int i = list.size()-1; i >= 0; --i) { | |
QWidget *w = list[i]; | |
if (w != QApplication::desktop() && | |
w->isVisible() && w->d_func()->localAllocatedRegion().contains(w->mapFromParent(pos)) | |
) | |
return w; | |
} | |
#endif | |
return 0; | |
} | |
void QApplication::beep() | |
{ | |
} | |
void QApplication::alert(QWidget *, int) | |
{ | |
} | |
int QApplication::qwsProcessEvent(QWSEvent* event) | |
{ | |
Q_D(QApplication); | |
QScopedLoopLevelCounter loopLevelCounter(d->threadData); | |
int oldstate = -1; | |
bool isMove = false; | |
if (event->type == QWSEvent::Mouse) { | |
QWSMouseEvent::SimpleData &mouse = event->asMouse()->simpleData; | |
isMove = mouse_x_root != mouse.x_root || mouse_y_root != mouse.y_root; | |
oldstate = mouse_state; | |
mouse_x_root = mouse.x_root; | |
mouse_y_root = mouse.y_root; | |
mouse_state = mouse.state; | |
} | |
long unused; | |
if (filterEvent(event, &unused)) // send through app filter | |
return 1; | |
if (qwsEventFilter(event)) // send through app filter | |
return 1; | |
#ifndef QT_NO_QWS_PROPERTIES | |
if (event->type == QWSEvent::PropertyNotify) { | |
QWSPropertyNotifyEvent *e = static_cast<QWSPropertyNotifyEvent*>(event); | |
if (e->simpleData.property == 424242) { // Clipboard | |
#ifndef QT_NO_CLIPBOARD | |
if (qt_clipboard) { | |
QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event)); | |
QApplication::sendEvent(qt_clipboard, &e); | |
} | |
#endif | |
} | |
} | |
#endif //QT_NO_QWS_PROPERTIES | |
#ifndef QT_NO_COP | |
else if (event->type == QWSEvent::QCopMessage) { | |
QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(event); | |
QCopChannel::sendLocally(QLatin1String(e->channel), QLatin1String(e->message), e->data); | |
return 0; | |
} | |
#endif | |
#if !defined(QT_NO_QWS_QPF2) | |
else if (event->type == QWSEvent::Font) { | |
QWSFontEvent *e = static_cast<QWSFontEvent *>(event); | |
if (e->simpleData.type == QWSFontEvent::FontRemoved) { | |
QFontCache::instance()->removeEngineForFont(e->fontName); | |
} | |
} | |
#endif | |
QPointer<QETWidget> widget = static_cast<QETWidget*>(QWidget::find(WId(event->window()))); | |
#ifdef Q_BACKINGSTORE_SUBSURFACES | |
if (!widget) { // XXX: hw: hack for accessing subsurfaces | |
extern QWSWindowSurface* qt_findWindowSurface(int); | |
QWSWindowSurface *s = qt_findWindowSurface(event->window()); | |
if (s) | |
widget = static_cast<QETWidget*>(s->window()); | |
} | |
#endif | |
#ifndef QT_NO_DIRECTPAINTER | |
if (!widget && d->directPainters) { | |
QDirectPainter *dp = d->directPainters->value(WId(event->window())); | |
if (dp == 0) { | |
} else if (event->type == QWSEvent::Region) { | |
QWSRegionEvent *e = static_cast<QWSRegionEvent*>(event); | |
QRegion reg; | |
reg.setRects(e->rectangles, e->simpleData.nrectangles); | |
qt_directpainter_region(dp, reg, e->simpleData.type); | |
return 1; | |
#ifndef QT_NO_QWSEMBEDWIDGET | |
} else if (event->type == QWSEvent::Embed) { | |
QWSEmbedEvent *e = static_cast<QWSEmbedEvent*>(event); | |
qt_directpainter_embedevent(dp, e); | |
return 1; | |
#endif // QT_NO_QWSEMBEDWIDGET | |
} | |
} | |
#endif // QT_NO_DIRECTPAINTER | |
#ifndef QT_NO_QWS_MANAGER | |
if (d->last_manager && event->type == QWSEvent::Mouse) { | |
QPoint pos(event->asMouse()->simpleData.x_root, event->asMouse()->simpleData.y_root); | |
if (!d->last_manager->cachedRegion().contains(pos)) { | |
// MouseEvent not yet delivered, so QCursor::pos() is not yet updated, sending 2 x pos | |
QMouseEvent outside(QEvent::MouseMove, pos, pos, Qt::NoButton, 0, 0); | |
QApplication::sendSpontaneousEvent(d->last_manager, &outside); | |
d->last_manager = 0; | |
qt_last_cursor = 0xffffffff; //decoration is like another window; must redo cursor | |
} | |
} | |
#endif // QT_NO_QWS_MANAGER | |
QETWidget *keywidget=0; | |
bool grabbed=false; | |
if (event->type==QWSEvent::Key || event->type == QWSEvent::IMEvent || event->type == QWSEvent::IMQuery) { | |
keywidget = static_cast<QETWidget*>(QWidget::keyboardGrabber()); | |
if (keywidget) { | |
grabbed = true; | |
} else { | |
if (QWidget *popup = QApplication::activePopupWidget()) { | |
if (popup->focusWidget()) | |
keywidget = static_cast<QETWidget*>(popup->focusWidget()); | |
else | |
keywidget = static_cast<QETWidget*>(popup); | |
} else if (QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget->isVisible()) | |
keywidget = static_cast<QETWidget*>(QApplicationPrivate::focus_widget); | |
else if (widget) | |
keywidget = static_cast<QETWidget*>(widget->window()); | |
} | |
} else if (event->type==QWSEvent::MaxWindowRect) { | |
QRect r = static_cast<QWSMaxWindowRectEvent*>(event)->simpleData.rect; | |
setMaxWindowRect(r); | |
return 0; | |
#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION | |
} else if (event->type == QWSEvent::ScreenTransformation) { | |
QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(event); | |
setScreenTransformation(pe->simpleData.screen, | |
pe->simpleData.transformation); | |
return 0; | |
#endif | |
} else if (widget && event->type==QWSEvent::Mouse) { | |
// The mouse event is to one of my top-level widgets | |
// which one? | |
const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton; | |
QPoint p(event->asMouse()->simpleData.x_root, | |
event->asMouse()->simpleData.y_root); | |
int mouseButtonState = event->asMouse()->simpleData.state & btnMask; | |
static int btnstate = 0; | |
QETWidget *w = static_cast<QETWidget*>(QWidget::mouseGrabber()); | |
if (w && !mouseButtonState && qt_pressGrab == w) | |
qt_pressGrab = 0; | |
#ifndef QT_NO_QWS_MANAGER | |
if (!w) | |
w = static_cast<QETWidget*>(QWSManager::grabbedMouse()); | |
#endif | |
if (w) { | |
// Our mouse is grabbed - send it. | |
widget = w; | |
btnstate = mouseButtonState; | |
} else { | |
static QWidget *gw = 0; | |
// Three jobs to do here: | |
// 1. find the child widget this event belongs to. | |
// 2. make sure the cursor is correct. | |
// 3. handle implicit mouse grab due to button press. | |
w = widget; // w is the widget the cursor is in. | |
//### ??? alloc_region | |
//#### why should we get events outside alloc_region ???? | |
if (1 /*widget->data->alloc_region.contains(dp) */) { | |
// Find the child widget that the cursor is in. | |
w = static_cast<QETWidget*>(widget->childAt(widget->mapFromParent(p))); | |
if (!w) | |
w = widget; | |
#ifndef QT_NO_CURSOR | |
// Update Cursor. | |
if (!gw || gw != w || qt_last_cursor == 0xffffffff) { | |
QCursor *curs = 0; | |
if (!qApp->d_func()->cursor_list.isEmpty()) | |
curs = &qApp->d_func()->cursor_list.first(); | |
else if (w->d_func()->extraData()) | |
curs = w->d_func()->extraData()->curs; | |
QWidget *pw = w; | |
// If this widget has no cursor set, try parent. | |
while (!curs) { | |
pw = pw->parentWidget(); | |
if (!pw) | |
break; | |
if (pw->d_func()->extraData()) | |
curs = pw->d_func()->extraData()->curs; | |
} | |
if (!qws_overrideCursor) { | |
if (curs) | |
QPaintDevice::qwsDisplay()->selectCursor(widget, curs->handle()); | |
else | |
QPaintDevice::qwsDisplay()->selectCursor(widget, Qt::ArrowCursor); | |
} | |
} | |
#endif | |
gw = w; | |
} else { | |
// This event is not for any of our widgets | |
gw = 0; | |
} | |
if (mouseButtonState && !btnstate) { | |
// The server has grabbed the mouse for us. | |
// Remember which of my widgets has it. | |
qt_pressGrab = w; | |
if (!widget->isActiveWindow() && | |
(!app_do_modal || QApplication::activeModalWidget() == widget) && | |
!((widget->windowFlags() & Qt::FramelessWindowHint) || (widget->windowType() == Qt::Tool))) { | |
widget->activateWindow(); | |
if (widget->raiseOnClick()) | |
widget->raise(); | |
} | |
} | |
btnstate = mouseButtonState; | |
widget = w; | |
} | |
} | |
if (!widget) { // don't know this window | |
if (!QWidget::mouseGrabber() | |
#ifndef QT_NO_QWS_MANAGER | |
&& !QWSManager::grabbedMouse() | |
#endif | |
) { | |
qt_last_cursor = 0xffffffff; // cursor can be changed by another application | |
} | |
QWidget* popup = QApplication::activePopupWidget(); | |
if (popup) { | |
/* | |
That is more than suboptimal. The real solution should | |
do some keyevent and buttonevent translation, so that | |
the popup still continues to work as the user expects. | |
Unfortunately this translation is currently only | |
possible with a known widget. I'll change that soon | |
(Matthias). | |
*/ | |
// Danger - make sure we don't lock the server | |
switch (event->type) { | |
case QWSEvent::Mouse: | |
case QWSEvent::Key: | |
do { | |
popup->close(); | |
} while ((popup = qApp->activePopupWidget())); | |
return 1; | |
} | |
} | |
if (event->type == QWSEvent::Mouse && *mouseInWidget) { | |
QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget); | |
(*mouseInWidget) = 0; | |
} | |
return -1; | |
} | |
if (app_do_modal) // modal event handling | |
if (!qt_try_modal(widget, event)) { | |
return 1; | |
} | |
if (widget->qwsEvent(event)) // send through widget filter | |
return 1; | |
switch (event->type) { | |
case QWSEvent::Mouse: { // mouse event | |
QWSMouseEvent *me = event->asMouse(); | |
QWSMouseEvent::SimpleData &mouse = me->simpleData; | |
// Translate a QWS event into separate move | |
// and press/release events | |
// Beware of reentrancy: we can enter a modal state | |
// inside translateMouseEvent | |
if (isMove) { | |
QWSMouseEvent move = *me; | |
move.simpleData.state = oldstate; | |
widget->translateMouseEvent(&move, oldstate); | |
} | |
if ((mouse.state&Qt::MouseButtonMask) != (oldstate&Qt::MouseButtonMask)) { | |
widget->translateMouseEvent(me, oldstate); | |
} | |
if (mouse.delta != 0) | |
widget->translateWheelEvent(me); | |
if (qt_button_down && (mouse_state & Qt::MouseButtonMask) == 0) | |
qt_button_down = 0; | |
break; | |
} | |
case QWSEvent::Key: // keyboard event | |
if (keywidget) // should always exist | |
keywidget->translateKeyEvent(static_cast<QWSKeyEvent*>(event), grabbed); | |
break; | |
#ifndef QT_NO_QWS_INPUTMETHODS | |
case QWSEvent::IMEvent: | |
if (keywidget) // should always exist | |
QWSInputContext::translateIMEvent(keywidget, static_cast<QWSIMEvent*>(event)); | |
break; | |
case QWSEvent::IMQuery: | |
if (keywidget) // should always exist | |
QWSInputContext::translateIMQueryEvent(keywidget, static_cast<QWSIMQueryEvent*>(event)); | |
break; | |
case QWSEvent::IMInit: | |
QWSInputContext::translateIMInitEvent(static_cast<QWSIMInitEvent*>(event)); | |
break; | |
#endif | |
case QWSEvent::Region: | |
widget->translateRegionEvent(static_cast<QWSRegionEvent*>(event)); | |
break; | |
case QWSEvent::Focus: | |
if ((static_cast<QWSFocusEvent*>(event))->simpleData.get_focus) { | |
if (widget == static_cast<QWidget *>(desktop())) | |
return true; // not interesting | |
if (activeWindow() != widget) { | |
setActiveWindow(widget); | |
if (QApplicationPrivate::active_window) | |
static_cast<QETWidget *>(QApplicationPrivate::active_window)->repaintDecoration(desktop()->rect(), false); | |
if (widget && !d->inPopupMode()) { | |
QWidget *w = widget->focusWidget(); | |
while (w && w->focusProxy()) | |
w = w->focusProxy(); | |
if (w && (w->focusPolicy() != Qt::NoFocus)) | |
w->setFocus(); | |
else | |
widget->QWidget::focusNextPrevChild(true); | |
if (!QApplicationPrivate::focus_widget) { | |
if (widget->focusWidget()) | |
widget->focusWidget()->setFocus(); | |
else | |
widget->window()->setFocus(); | |
} | |
} | |
} | |
} else { // lost focus | |
if (widget == static_cast<QWidget *>(desktop())) | |
return true; // not interesting | |
if (QApplicationPrivate::focus_widget) { | |
QETWidget *old = static_cast<QETWidget *>(QApplicationPrivate::active_window); | |
setActiveWindow(0); | |
qt_last_cursor = 0xffffffff; | |
//QApplicationPrivate::active_window = 0; | |
if (old) | |
old->repaintDecoration(desktop()->rect(), false); | |
/* activateWindow() sends focus events | |
QApplication::setFocusWidget(0); | |
*/ | |
} | |
} | |
break; | |
case QWSEvent::WindowOperation: | |
if (static_cast<QWidget *>(widget) == desktop()) | |
return true; | |
switch ((static_cast<QWSWindowOperationEvent *>(event))->simpleData.op) { | |
case QWSWindowOperationEvent::Show: | |
widget->show(); | |
break; | |
case QWSWindowOperationEvent::Hide: | |
widget->hide(); | |
break; | |
case QWSWindowOperationEvent::ShowMaximized: | |
widget->showMaximized(); | |
break; | |
case QWSWindowOperationEvent::ShowMinimized: | |
widget->showMinimized(); | |
break; | |
case QWSWindowOperationEvent::ShowNormal: | |
widget->showNormal(); | |
break; | |
case QWSWindowOperationEvent::Close: | |
widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); | |
break; | |
} | |
break; | |
#ifndef QT_NO_QWSEMBEDWIDGET | |
case QWSEvent::Embed: | |
widget->translateEmbedEvent(static_cast<QWSEmbedEvent*>(event)); | |
break; | |
#endif | |
default: | |
break; | |
} | |
return 0; | |
} | |
bool QApplication::qwsEventFilter(QWSEvent *) | |
{ | |
return false; | |
} | |
void QApplication::qwsSetCustomColors(QRgb *colorTable, int start, int numColors) | |
{ | |
if (start < 0 || start > 39) { | |
qWarning("QApplication::qwsSetCustomColors: start < 0 || start > 39"); | |
return; | |
} | |
if (start + numColors > 40) { | |
numColors = 40 - start; | |
qWarning("QApplication::qwsSetCustomColors: Too many colors"); | |
} | |
start += 216; | |
for (int i = 0; i < numColors; i++) { | |
qt_screen->set(start + i, qRed(colorTable[i]), qGreen(colorTable[i]), | |
qBlue(colorTable[i])); | |
} | |
} | |
#ifndef QT_NO_QWS_MANAGER | |
QDecoration &QApplication::qwsDecoration() | |
{ | |
return *qws_decoration; | |
} | |
void QApplication::qwsSetDecoration(QDecoration *dec) | |
{ | |
if (dec) { | |
delete qws_decoration; | |
qws_decoration = dec; | |
QWidgetList widgets = topLevelWidgets(); | |
for (int i = 0; i < widgets.size(); ++i) { | |
QWidget *w = widgets[i]; | |
if (w->isVisible() && w != desktop()) { | |
static_cast<QETWidget *>(w)->updateRegion(); | |
static_cast<QETWidget *>(w)->repaintDecoration(desktop()->rect(), false); | |
if (w->isMaximized()) | |
w->showMaximized(); | |
} | |
} | |
} | |
} | |
QDecoration* QApplication::qwsSetDecoration(const QString &decoration) | |
{ | |
QDecoration *decore = QDecorationFactory::create(decoration); | |
if (!decore) | |
return 0; | |
qwsSetDecoration(decore); | |
return decore; | |
} | |
#endif | |
bool QApplicationPrivate::modalState() | |
{ | |
return app_do_modal; | |
} | |
void QApplicationPrivate::enterModal_sys(QWidget *widget) | |
{ | |
if (!qt_modal_stack) | |
qt_modal_stack = new QWidgetList; | |
qt_modal_stack->insert(0, widget); | |
app_do_modal = true; | |
} | |
void QApplicationPrivate::leaveModal_sys(QWidget *widget) | |
{ | |
if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { | |
if (qt_modal_stack->isEmpty()) { | |
delete qt_modal_stack; | |
qt_modal_stack = 0; | |
} | |
} | |
app_do_modal = qt_modal_stack != 0; | |
} | |
static bool qt_try_modal(QWidget *widget, QWSEvent *event) | |
{ | |
QWidget * top = 0; | |
if (QApplicationPrivate::tryModalHelper(widget, &top)) | |
return true; | |
bool block_event = false; | |
bool paint_event = false; | |
switch (event->type) { | |
case QWSEvent::Focus: | |
if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus) | |
break; | |
// drop through | |
case QWSEvent::Mouse: // disallow mouse/key events | |
case QWSEvent::Key: | |
block_event = true; | |
break; | |
} | |
if (top->parentWidget() == 0 && (block_event || paint_event)) | |
top->raise(); | |
return !block_event; | |
} | |
static int openPopupCount = 0; | |
void QApplicationPrivate::openPopup(QWidget *popup) | |
{ | |
openPopupCount++; | |
if (!popupWidgets) { // create list | |
popupWidgets = new QWidgetList; | |
/* only grab if you are the first/parent popup */ | |
QPaintDevice::qwsDisplay()->grabMouse(popup,true); | |
QPaintDevice::qwsDisplay()->grabKeyboard(popup,true); | |
popupGrabOk = true; | |
} | |
popupWidgets->append(popup); // add to end of list | |
// popups are not focus-handled by the window system (the first | |
// popup grabbed the keyboard), so we have to do that manually: A | |
// new popup gets the focus | |
if (popup->focusWidget()) { | |
popup->focusWidget()->setFocus(Qt::PopupFocusReason); | |
} else if (popupWidgets->count() == 1) { // this was the first popup | |
if (QWidget *fw = QApplication::focusWidget()) { | |
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); | |
QApplication::sendEvent(fw, &e); | |
} | |
} | |
} | |
void QApplicationPrivate::closePopup(QWidget *popup) | |
{ | |
if (!popupWidgets) | |
return; | |
popupWidgets->removeAll(popup); | |
if (popup == popupOfPopupButtonFocus) { | |
popupButtonFocus = 0; | |
popupOfPopupButtonFocus = 0; | |
} | |
if (popupWidgets->count() == 0) { // this was the last popup | |
popupCloseDownMode = true; // control mouse events | |
delete popupWidgets; | |
popupWidgets = 0; | |
if (popupGrabOk) { // grabbing not disabled | |
QPaintDevice::qwsDisplay()->grabMouse(popup,false); | |
QPaintDevice::qwsDisplay()->grabKeyboard(popup,false); | |
popupGrabOk = false; | |
// XXX ungrab keyboard | |
} | |
if (active_window) { | |
if (QWidget *fw = active_window->focusWidget()) { | |
if (fw != QApplication::focusWidget()) { | |
fw->setFocus(Qt::PopupFocusReason); | |
} else { | |
QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); | |
QApplication::sendEvent(fw, &e); | |
} | |
} | |
} | |
} else { | |
// popups are not focus-handled by the window system (the | |
// first popup grabbed the keyboard), so we have to do that | |
// manually: A popup was closed, so the previous popup gets | |
// the focus. | |
QWidget* aw = popupWidgets->last(); | |
if (QWidget *fw = aw->focusWidget()) | |
fw->setFocus(Qt::PopupFocusReason); | |
} | |
} | |
/***************************************************************************** | |
Event translation; translates FB events to Qt events | |
*****************************************************************************/ | |
// | |
// Mouse event translation | |
// | |
// FB doesn't give mouse double click events, so we generate them by | |
// comparing window, time and position between two mouse press events. | |
// | |
// Needed for QCursor::pos | |
static const int AnyButton = (Qt::LeftButton | Qt::MidButton | Qt::RightButton); | |
// | |
// Wheel event translation | |
// | |
bool QETWidget::translateWheelEvent(const QWSMouseEvent *me) | |
{ | |
#ifdef QT_NO_WHEELEVENT | |
Q_UNUSED(me); | |
return false; | |
#else | |
const QWSMouseEvent::SimpleData &mouse = me->simpleData; | |
// Figure out wheeling direction: | |
// Horizontal wheel w/o Alt | |
// OR Vertical wheel w/ Alt ==> Horizontal wheeling | |
// ..all other permutations ==> Vertical wheeling | |
int axis = mouse.delta / 120; // WHEEL_DELTA? | |
Qt::Orientation orient = ((axis == 2 || axis == -2) && ((mouse.state & Qt::AltModifier) == 0)) | |
||((axis == 1 || axis == -1) && mouse.state & Qt::AltModifier) | |
? Qt::Horizontal : Qt::Vertical; | |
QPoint mousePoint = QPoint(mouse.x_root, mouse.y_root); | |
// send the event to the widget or its ancestors | |
QWidget* popup = qApp->activePopupWidget(); | |
if (popup && window() != popup) | |
popup->close(); | |
QWheelEvent we(mapFromGlobal(mousePoint), mousePoint, mouse.delta, | |
Qt::MouseButtons(mouse.state & Qt::MouseButtonMask), | |
Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask), orient); | |
if (QApplication::sendSpontaneousEvent(this, &we)) | |
return true; | |
// send the event to the widget that has the focus or its ancestors, if different | |
QWidget *w = this; | |
if (w != qApp->focusWidget() && (w = qApp->focusWidget())) { | |
QWidget* popup = qApp->activePopupWidget(); | |
if (popup && w != popup) | |
popup->hide(); | |
if (QApplication::sendSpontaneousEvent(w, &we)) | |
return true; | |
} | |
return false; | |
#endif | |
} | |
bool QETWidget::translateMouseEvent(const QWSMouseEvent *event, int prevstate) | |
{ | |
static bool manualGrab = false; | |
QPoint pos; | |
QPoint globalPos; | |
int button = 0; | |
if (sm_blockUserInput) // block user interaction during session management | |
return true; | |
const QWSMouseEvent::SimpleData &mouse = event->simpleData; | |
pos = mapFromGlobal(QPoint(mouse.x_root, mouse.y_root)); | |
// if (qt_last_x) { | |
// *qt_last_x=mouse.x_root; | |
// *qt_last_y=mouse.y_root; | |
// } | |
globalPos.rx() = mouse.x_root; | |
globalPos.ry() = mouse.y_root; | |
QEvent::Type type = QEvent::None; | |
Qt::MouseButtons buttonstate = Qt::MouseButtons(mouse.state & Qt::MouseButtonMask); | |
Qt::KeyboardModifiers keystate = Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask); | |
if (mouse.state == prevstate) { | |
// mouse move | |
type = QEvent::MouseMove; | |
} else if ((mouse.state&AnyButton) != (prevstate&AnyButton)) { | |
Qt::MouseButtons current_buttons = Qt::MouseButtons(prevstate&Qt::MouseButtonMask); | |
for (button = Qt::LeftButton; !type && button <= Qt::MidButton; button<<=1) { | |
if ((mouse.state&button) != (current_buttons&button)) { | |
// button press or release | |
current_buttons = Qt::MouseButtons(current_buttons ^ button); | |
#ifndef QT_NO_QWS_INPUTMETHODS | |
//############ We used to do a QInputContext::reset(oldFocus); | |
// when we changed the focus widget. See change 93389 for where the | |
// focus code went. The IM code was (after testing for ClickToFocus): | |
//if (mouse.state&button && w != QInputContext::microFocusWidget()) //button press | |
// QInputContext::reset(oldFocus); | |
#endif | |
if (mouse.state&button) { //button press | |
qt_button_down = childAt(pos); | |
if (!qt_button_down) | |
qt_button_down = this; | |
if (/*XXX mouseActWindow == this &&*/ | |
mouseButtonPressed == button && | |
long(mouse.time) -long(mouseButtonPressTime) | |
< QApplication::doubleClickInterval() && | |
qAbs(mouse.x_root - mouseXPos) < mouse_double_click_distance && | |
qAbs(mouse.y_root - mouseYPos) < mouse_double_click_distance ) { | |
type = QEvent::MouseButtonDblClick; | |
mouseButtonPressTime -= 2000; // no double-click next time | |
} else { | |
type = QEvent::MouseButtonPress; | |
mouseButtonPressTime = mouse.time; | |
} | |
mouseButtonPressed = button; // save event params for | |
mouseXPos = globalPos.x(); // future double click tests | |
mouseYPos = globalPos.y(); | |
} else { // mouse button released | |
if (manualGrab) { // release manual grab | |
manualGrab = false; | |
// XXX XUngrabPointer(x11Display(), CurrentTime); | |
} | |
type = QEvent::MouseButtonRelease; | |
} | |
} | |
} | |
button >>= 1; | |
} | |
//XXX mouseActWindow = winId(); // save some event params | |
if (type == 0) { // event consumed | |
return false; //EXIT in the normal case | |
} | |
if (qApp->d_func()->inPopupMode()) { // in popup mode | |
QWidget *popup = qApp->activePopupWidget(); | |
// in X11, this would be the window we are over. | |
// in QWS this is the top level popup. to allow mouse | |
// events to other widgets, need to go through qApp->QApplicationPrivate::popupWidgets. | |
QSize s(qt_screen->width(), qt_screen->height()); | |
for (int i = 0; i < QApplicationPrivate::popupWidgets->size(); ++i) { | |
QWidget *w = QApplicationPrivate::popupWidgets->at(i); | |
if ((w->windowType() == Qt::Popup) && w->d_func()->localAllocatedRegion().contains(globalPos - w->geometry().topLeft())) | |
{ | |
popup = w; | |
break; | |
} | |
} | |
pos = popup->mapFromGlobal(globalPos); | |
bool releaseAfter = false; | |
QWidget *popupChild = popup->childAt(pos); | |
QWidget *popupTarget = popupChild ? popupChild : popup; | |
if (popup != popupOfPopupButtonFocus){ | |
popupButtonFocus = 0; | |
popupOfPopupButtonFocus = 0; | |
} | |
if (!popupTarget->isEnabled()) { | |
return false; //EXIT special case | |
} | |
switch (type) { | |
case QEvent::MouseButtonPress: | |
case QEvent::MouseButtonDblClick: | |
popupButtonFocus = popupChild; | |
popupOfPopupButtonFocus = popup; | |
break; | |
case QEvent::MouseButtonRelease: | |
releaseAfter = true; | |
break; | |
default: | |
break; // nothing for mouse move | |
} | |
int oldOpenPopupCount = openPopupCount; | |
if (popupButtonFocus) { | |
QMouseEvent e(type, popupButtonFocus->mapFromGlobal(globalPos), | |
globalPos, Qt::MouseButton(button), buttonstate, keystate); | |
QApplication::sendSpontaneousEvent(popupButtonFocus, & e); | |
if (releaseAfter) { | |
popupButtonFocus = 0; | |
popupOfPopupButtonFocus = 0; | |
} | |
} else if (popupChild) { | |
QMouseEvent e(type, popupChild->mapFromGlobal(globalPos), | |
globalPos, Qt::MouseButton(button), buttonstate, keystate); | |
QApplication::sendSpontaneousEvent(popupChild, & e); | |
} else { | |
QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate); | |
QApplication::sendSpontaneousEvent(popupChild ? popupChild : popup, & e); | |
} | |
#ifndef QT_NO_CONTEXTMENU | |
if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { | |
QWidget *popupEvent = popup; | |
if(popupButtonFocus) | |
popupEvent = popupButtonFocus; | |
else if(popupChild) | |
popupEvent = popupChild; | |
QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate); | |
QApplication::sendSpontaneousEvent(popupEvent, &e); | |
} | |
#endif // QT_NO_CONTEXTMENU | |
if (releaseAfter) | |
qt_button_down = 0; | |
} else { //qApp not in popup mode | |
QWidget *widget = this; | |
QWidget *w = QWidget::mouseGrabber(); | |
if (!w && qt_button_down) | |
w = qt_button_down; | |
if (w && w != this) { | |
widget = w; | |
pos = mapToGlobal(pos); | |
pos = w->mapFromGlobal(pos); | |
} | |
if (popupCloseDownMode) { | |
popupCloseDownMode = false; | |
if ((windowType() == Qt::Popup)) // ignore replayed event | |
return true; //EXIT | |
} | |
QPointer<QWidget> leaveAfterRelease = 0; | |
if (type == QEvent::MouseButtonRelease && | |
(mouse.state & (~button) & (Qt::LeftButton | | |
Qt::MidButton | | |
Qt::RightButton)) == 0) { | |
// Button released outside the widget -> leave the widget after the | |
// release event has been delivered. | |
if (widget == qt_button_down && (pos.x() < 0 || pos.y() < 0)) | |
leaveAfterRelease = qt_button_down; | |
qt_button_down = 0; | |
} | |
int oldOpenPopupCount = openPopupCount; | |
QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate); | |
#ifndef QT_NO_QWS_MANAGER | |
if (widget->isWindow() && widget->d_func()->topData()->qwsManager | |
&& (widget->d_func()->topData()->qwsManager->region().contains(globalPos) | |
|| QWSManager::grabbedMouse() )) { | |
if ((*mouseInWidget)) { | |
QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget); | |
(*mouseInWidget) = 0; | |
} | |
QApplication::sendSpontaneousEvent(widget->d_func()->topData()->qwsManager, &e); | |
qApp->d_func()->last_manager = widget->d_func()->topData()->qwsManager; | |
} else | |
#endif | |
{ | |
if (widget != (*mouseInWidget)) { | |
QApplicationPrivate::dispatchEnterLeave(widget, *mouseInWidget); | |
(*mouseInWidget) = widget; | |
qt_last_mouse_receiver = widget; | |
} | |
QApplication::sendSpontaneousEvent(widget, &e); | |
if (leaveAfterRelease && !QWidget::mouseGrabber()) { | |
*mouseInWidget = QApplication::widgetAt(globalPos); | |
qt_last_mouse_receiver = *mouseInWidget; | |
QApplicationPrivate::dispatchEnterLeave(*mouseInWidget, leaveAfterRelease); | |
leaveAfterRelease = 0; | |
} | |
} | |
#ifndef QT_NO_CONTEXTMENU | |
if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { | |
QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate); | |
QApplication::sendSpontaneousEvent(widget, &e); | |
} | |
#endif // QT_NO_CONTEXTMENU | |
} | |
return true; | |
} | |
bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab is used in the #ifdef */ | |
{ | |
int code = -1; | |
//### Qt assumes keyboard state is state *before*, while QWS uses state after the event | |
static Qt::KeyboardModifiers oldstate; | |
Qt::KeyboardModifiers state = oldstate; | |
oldstate = event->simpleData.modifiers; | |
if (sm_blockUserInput) // block user interaction during session management | |
return true; | |
if (!isEnabled()) | |
return true; | |
QEvent::Type type = event->simpleData.is_press ? | |
QEvent::KeyPress : QEvent::KeyRelease; | |
bool autor = event->simpleData.is_auto_repeat; | |
QString text; | |
char ascii = 0; | |
if (event->simpleData.unicode) { | |
QChar ch(event->simpleData.unicode); | |
if (ch.unicode() != 0xffff) | |
text += ch; | |
ascii = ch.toLatin1(); | |
} | |
code = event->simpleData.keycode; | |
#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT) | |
if (type == QEvent::KeyPress && !grab | |
&& static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->use_compat()) { | |
// send accel events if the keyboard is not grabbed | |
QKeyEvent a(type, code, state, text, autor, int(text.length())); | |
if (static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->qt_tryAccelEvent(this, &a)) | |
return true; | |
} | |
#else | |
Q_UNUSED(grab); | |
#endif | |
if (!text.isEmpty() && testAttribute(Qt::WA_KeyCompression)) { | |
// the widget wants key compression so it gets it | |
// XXX not implemented | |
} | |
QKeyEvent e(type, code, state, text, autor, int(text.length())); | |
return QApplication::sendSpontaneousEvent(this, &e); | |
} | |
bool QETWidget::translateRegionEvent(const QWSRegionEvent *event) | |
{ | |
QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(windowSurface()); | |
Q_ASSERT(surface); | |
QRegion region; | |
region.setRects(event->rectangles, event->simpleData.nrectangles); | |
switch (event->simpleData.type) { | |
case QWSRegionEvent::Allocation: | |
region.translate(-mapToGlobal(QPoint())); | |
surface->setClipRegion(region); | |
break; | |
#ifdef QT_QWS_CLIENTBLIT | |
case QWSRegionEvent::DirectPaint: | |
surface->setDirectRegion(region, event->simpleData.id); | |
break; | |
#endif | |
default: | |
break; | |
} | |
return true; | |
} | |
#ifndef QT_NO_QWSEMBEDWIDGET | |
void QETWidget::translateEmbedEvent(const QWSEmbedEvent *event) | |
{ | |
if (event->simpleData.type | QWSEmbedEvent::Region) { | |
const QRegion region = event->region; | |
setGeometry(region.boundingRect()); | |
setVisible(!region.isEmpty()); | |
} | |
} | |
#endif // QT_NO_QWSEMBEDWIDGET | |
void QETWidget::repaintDecoration(QRegion r, bool post) | |
{ | |
Q_UNUSED(post); | |
#ifdef QT_NO_QWS_MANAGER | |
Q_UNUSED(r); | |
#else | |
//please note that qwsManager is a QObject, not a QWidget. | |
//therefore, normal ways of painting do not work. | |
// However, it does listen to paint events. | |
Q_D(QWidget); | |
if (isWindow() && d->topData()->qwsManager && isVisible()) { | |
QWSManager *manager = d->topData()->qwsManager; | |
r &= manager->region(); | |
if (!r.isEmpty()) | |
manager->repaintRegion(QDecoration::All, QDecoration::Normal); | |
} | |
#endif | |
} | |
void QETWidget::updateRegion() | |
{ | |
Q_D(QWidget); | |
QTLWExtra *topextra = d->maybeTopData(); | |
if (!topextra) | |
return; | |
QRegion myregion = d->localRequestedRegion(); | |
myregion.translate(geometry().topLeft()); | |
#ifndef QT_NO_QWS_MANAGER | |
QWSManager *manager = topextra->qwsManager; | |
if (manager) | |
myregion += manager->region(); | |
#endif | |
QRect br(myregion.boundingRect()); | |
topextra->frameStrut.setCoords(d->data.crect.x() - br.x(), | |
d->data.crect.y() - br.y(), | |
br.right() - d->data.crect.right(), | |
br.bottom() - d->data.crect.bottom()); | |
} | |
void QApplication::setCursorFlashTime(int msecs) | |
{ | |
QApplicationPrivate::cursor_flash_time = msecs; | |
} | |
int QApplication::cursorFlashTime() | |
{ | |
return QApplicationPrivate::cursor_flash_time; | |
} | |
void QApplication::setDoubleClickInterval(int ms) | |
{ | |
QApplicationPrivate::mouse_double_click_time = ms; | |
} | |
int QApplication::doubleClickInterval() | |
{ | |
return QApplicationPrivate::mouse_double_click_time; | |
} | |
void QApplication::setKeyboardInputInterval(int ms) | |
{ | |
QApplicationPrivate::keyboard_input_time = ms; | |
} | |
int QApplication::keyboardInputInterval() | |
{ | |
return QApplicationPrivate::keyboard_input_time; | |
} | |
#ifndef QT_NO_WHEELEVENT | |
void QApplication::setWheelScrollLines(int lines) | |
{ | |
QApplicationPrivate::wheel_scroll_lines = lines; | |
} | |
int QApplication::wheelScrollLines() | |
{ | |
return QApplicationPrivate::wheel_scroll_lines; | |
} | |
#endif | |
void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) | |
{ | |
switch (effect) { | |
case Qt::UI_AnimateMenu: | |
QApplicationPrivate::animate_menu = enable; | |
break; | |
case Qt::UI_FadeMenu: | |
if (enable) | |
QApplicationPrivate::animate_menu = true; | |
QApplicationPrivate::fade_menu = enable; | |
break; | |
case Qt::UI_AnimateCombo: | |
QApplicationPrivate::animate_combo = enable; | |
break; | |
case Qt::UI_AnimateTooltip: | |
QApplicationPrivate::animate_tooltip = enable; | |
break; | |
case Qt::UI_FadeTooltip: | |
if (enable) | |
QApplicationPrivate::animate_tooltip = true; | |
QApplicationPrivate::fade_tooltip = enable; | |
break; | |
case Qt::UI_AnimateToolBox: | |
QApplicationPrivate::animate_toolbox = enable; | |
break; | |
default: | |
QApplicationPrivate::animate_ui = enable; | |
break; | |
} | |
} | |
bool QApplication::isEffectEnabled(Qt::UIEffect effect) | |
{ | |
if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) | |
return false; | |
switch(effect) { | |
case Qt::UI_AnimateMenu: | |
return QApplicationPrivate::animate_menu; | |
case Qt::UI_FadeMenu: | |
return QApplicationPrivate::fade_menu; | |
case Qt::UI_AnimateCombo: | |
return QApplicationPrivate::animate_combo; | |
case Qt::UI_AnimateTooltip: | |
return QApplicationPrivate::animate_tooltip; | |
case Qt::UI_FadeTooltip: | |
return QApplicationPrivate::fade_tooltip; | |
case Qt::UI_AnimateToolBox: | |
return QApplicationPrivate::animate_toolbox; | |
default: | |
return QApplicationPrivate::animate_ui; | |
} | |
} | |
void QApplication::setArgs(int c, char **v) | |
{ | |
Q_D(QApplication); | |
d->argc = c; | |
d->argv = v; | |
} | |
void QApplicationPrivate::initializeMultitouch_sys() | |
{ } | |
void QApplicationPrivate::cleanupMultitouch_sys() | |
{ } | |
/* \internal | |
This is used to clean up the qws server | |
in case the QApplication constructor threw an exception | |
*/ | |
QWSServerCleaner::~QWSServerCleaner() | |
{ | |
if (qwsServer && qws_single_process) | |
QWSServer::closedown(); | |
} | |
QT_END_NAMESPACE |