blob: c80c430d6716a82c2146efafe95f77147673eca0 [file] [log] [blame]
/****************************************************************************
**
** 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 &region)
{
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