📄 qdnd_x11.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qplatformdefs.h"#include "qapplication.h"#ifndef QT_NO_DRAGANDDROP#include "qwidget.h"#include "qpixmap.h"#include "qbitmap.h"#include "qdesktopwidget.h"#include "qevent.h"#include "qdatetime.h"#include "qiodevice.h"#include "qpointer.h"#include "qcursor.h"#include "qvariant.h"#include "qvector.h"#include "qurl.h"#include "qdebug.h"#include "qimagewriter.h"#include "qbuffer.h"#include "qtextcodec.h"#include "qdnd_p.h"#include "qt_x11_p.h"#include "qx11info_x11.h"#include "qwidget_p.h"#include "qcursor_p.h"// #define DND_DEBUG#ifdef DND_DEBUG#define DEBUG qDebug#else#define DEBUG if(0) qDebug#endif#ifdef DND_DEBUG#define DNDDEBUG qDebug()#else#define DNDDEBUG if(0) qDebug()#endifstatic int findXdndDropTransactionByWindow(Window window){ int at = -1; for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); if (t.target == window || t.proxy_target == window) { at = i; break; } } return at;}static int findXdndDropTransactionByTime(Time timestamp){ int at = -1; for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); if (t.timestamp == timestamp) { at = i; break; } } return at;}// timer used to discard old XdndDrop transactionsstatic int transaction_expiry_timer = -1;enum { XdndDropTransactionTimeout = 5000 }; // 5 secondsstatic void restartXdndDropExpiryTimer(){ if (transaction_expiry_timer != -1) QDragManager::self()->killTimer(transaction_expiry_timer); transaction_expiry_timer = QDragManager::self()->startTimer(XdndDropTransactionTimeout);}// find an ancestor with XdndAware on itstatic Window findXdndAwareParent(Window window){ Window target = 0; forever { // check if window has XdndAware Atom type = 0; int f; unsigned long n, a; unsigned char *data = 0; if (XGetWindowProperty(X11->display, window, ATOM(XdndAware), 0, 0, False, AnyPropertyType, &type, &f,&n,&a,&data) == Success) { if (data) XFree(data); if (type) { target = window; break; } } // try window's parent Window root; Window parent; Window *children; uint unused; if (!XQueryTree(X11->display, window, &root, &parent, &children, &unused)) break; if (children) XFree(children); if (window == root) break; window = parent; } return target;}// and all this stuff is copied -into- qapp_x11.cppstatic void handle_xdnd_position(QWidget *, const XEvent *, bool);static void handle_xdnd_status(QWidget * w, const XEvent * xe, bool /*passive*/);const int xdnd_version = 5;static Qt::DropAction xdndaction_to_qtaction(Atom atom){ if (atom == ATOM(XdndActionCopy) || atom == 0) return Qt::CopyAction; if (atom == ATOM(XdndActionLink)) return Qt::LinkAction; if (atom == ATOM(XdndActionMove)) return Qt::MoveAction; return Qt::CopyAction;}static int qtaction_to_xdndaction(Qt::DropAction a){ switch (a) { case Qt::CopyAction: return ATOM(XdndActionCopy); case Qt::LinkAction: return ATOM(XdndActionLink); case Qt::MoveAction: case Qt::TargetMoveAction: return ATOM(XdndActionMove); case Qt::IgnoreAction: return XNone; default: return ATOM(XdndActionCopy); }}// clean up the stuff used.static void qt_xdnd_cleanup();static void qt_xdnd_send_leave();// real variables:// xid of current drag sourcestatic Atom qt_xdnd_dragsource_xid = 0;// the types in this drop. 100 is no good, but at least it's big.const int qt_xdnd_max_type = 100;static Atom qt_xdnd_types[qt_xdnd_max_type + 1];// timer used when target wants "continuous" move messages (eg. scroll)static int heartbeat = -1;// rectangle in which the answer will be the samestatic QRect qt_xdnd_source_sameanswer;// top-level window we sent position to last.static Window qt_xdnd_current_target;// window to send events to (always valid if qt_xdnd_current_target)static Window qt_xdnd_current_proxy_target;static Time qt_xdnd_source_current_time;// widget we forwarded position to last, and local positionstatic QPointer<QWidget> qt_xdnd_current_widget;static QPoint qt_xdnd_current_position;// timestamp from the XdndPosition and XdndDropstatic Time qt_xdnd_target_current_time;// screen number containing the pointer... -1 means defaultstatic int qt_xdnd_current_screen = -1;// state of dragging... true if dragging, false if notbool qt_xdnd_dragging = false;static bool waiting_for_status = false;// used to preset each new QDragMoveEventstatic Qt::DropAction last_target_accepted_action = Qt::IgnoreAction;// Shift/Ctrl handling, and final drop statusstatic Qt::DropAction global_accepted_action = Qt::CopyAction;static Qt::DropActions possible_actions = Qt::IgnoreAction;// for embedding onlystatic QWidget* current_embedding_widget = 0;static XEvent last_enter_event;// cursorsstatic QCursor *noDropCursor = 0;static QCursor *moveCursor = 0;static QCursor *copyCursor = 0;static QCursor *linkCursor = 0;static QPixmap *defaultPm = 0;static const int default_pm_hotx = -2;static const int default_pm_hoty = -16;static const char* const default_pm[] = {"13 9 3 1",". c None"," c #000000","X c #FFFFFF","X X X X X X X"," X X X X X X ","X ......... X"," X.........X ","X ......... X"," X.........X ","X ......... X"," X X X X X X ","X X X X X X X"};class QShapedPixmapWidget : public QWidget {public: QShapedPixmapWidget(int screen = -1) : QWidget(QApplication::desktop()->screen(screen), Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint) { } void setPixmap(const QPixmap &pm) { QBitmap mask = pm.mask(); if (!mask.isNull()) { setMask(mask); } else { clearMask(); } resize(pm.width(),pm.height()); QPalette p = palette(); p.setBrush(backgroundRole(), QBrush(pm)); setPalette(p); update(); } QPoint pm_hot;};struct XdndData { QShapedPixmapWidget *deco; QWidget* desktop_proxy;};static XdndData xdnd_data = { 0, 0 };class QExtraWidget : public QWidget{ Q_DECLARE_PRIVATE(QWidget)public: inline QWExtra* extraData(); inline QTLWExtra* topData();};inline QWExtra* QExtraWidget::extraData() { return d_func()->extraData(); }inline QTLWExtra* QExtraWidget::topData() { return d_func()->topData(); }static WId xdndProxy(WId w){ Atom type = XNone; int f; unsigned long n, a; unsigned char *retval = 0; XGetWindowProperty(X11->display, w, ATOM(XdndProxy), 0, 1, False, XA_WINDOW, &type, &f,&n,&a,&retval); WId *proxy_id_ptr = (WId *)retval; WId proxy_id = 0; if (type == XA_WINDOW && proxy_id_ptr) { proxy_id = *proxy_id_ptr; XFree(proxy_id_ptr); proxy_id_ptr = 0; // Already exists. Real? X11->ignoreBadwindow(); XGetWindowProperty(X11->display, proxy_id, ATOM(XdndProxy), 0, 1, False, XA_WINDOW, &type, &f,&n,&a,&retval); proxy_id_ptr = (WId *)retval; if (X11->badwindow() || type != XA_WINDOW || !proxy_id_ptr || *proxy_id_ptr != proxy_id) // Bogus - we will overwrite. proxy_id = 0; } if (proxy_id_ptr) XFree(proxy_id_ptr); return proxy_id;}static bool xdndEnable(QWidget* w, bool on){ DNDDEBUG << "xdndEnable" << w << on; if (on) { QWidget * xdnd_widget = 0; if ((w->windowType() == Qt::Desktop)) { if (xdnd_data.desktop_proxy) // *WE* already have one. return false; // As per Xdnd4, use XdndProxy XGrabServer(X11->display); Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); WId proxy_id = xdndProxy(w->internalWinId()); if (!proxy_id) { xdnd_widget = xdnd_data.desktop_proxy = new QWidget; proxy_id = xdnd_data.desktop_proxy->internalWinId(); XChangeProperty (X11->display, w->internalWinId(), ATOM(XdndProxy), XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1); XChangeProperty (X11->display, proxy_id, ATOM(XdndProxy), XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1); } XUngrabServer(X11->display); } else { xdnd_widget = w->window(); } if (xdnd_widget) { DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->internalWinId(); Atom atm = (Atom)xdnd_version; Q_ASSERT(xdnd_widget->testAttribute(Qt::WA_WState_Created)); XChangeProperty(X11->display, xdnd_widget->internalWinId(), ATOM(XdndAware), XA_ATOM, 32, PropModeReplace, (unsigned char *)&atm, 1); return true; } else { return false; } } else { if ((w->windowType() == Qt::Desktop)) { XDeleteProperty(X11->display, w->internalWinId(), ATOM(XdndProxy)); delete xdnd_data.desktop_proxy; xdnd_data.desktop_proxy = 0; } else { DNDDEBUG << "not deleting XDndAware"; } return true; }}QByteArray QX11Data::xdndAtomToString(Atom a){ if (!a) return 0; if (a == XA_STRING || a == ATOM(UTF8_STRING)) { return "text/plain"; // some Xdnd clients are dumb } char *atom = XGetAtomName(display, a); QByteArray result = atom; XFree(atom); return result;}Atom QX11Data::xdndStringToAtom(const char *mimeType){ if (!mimeType || !*mimeType) return 0; return XInternAtom(display, mimeType, False);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -