📄 drag.cpp
字号:
/* This file is part of the KDE libraries Copyright (C) 1997 Torben Weis (weis@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * $Id: drag.cpp,v 1.1 2003/09/08 19:42:03 jasonk Exp $ * * $Log: drag.cpp,v $ * Revision 1.1 2003/09/08 19:42:03 jasonk * Addition of packages directory and associated files. * * Revision 1.1.1.1 2003/08/07 21:18:32 jasonk * Initial import of PIXIL into new cvs repository. * * Revision 1.1.1.1 2003/06/23 22:04:23 jasonk * * * Revision 1.1.1.1 2000/07/07 16:10:58 jasonk * Initial import of ViewML * * Revision 1.24 1999/01/18 10:56:11 kulow * .moc files are back in kdelibs. Built fine here using automake 1.3 * * Revision 1.23 1999/01/15 09:30:29 kulow * it's official - kdelibs builds with srcdir != builddir. For this I * automocifized it, the generated rules are easier to maintain than * selfwritten rules. I have to fight with some bugs of this tool, but * generally it's better than keeping them updated by hand. * * Revision 1.22 1998/08/22 20:02:32 kulow * make kdecore have nicer output, when compiled with -Weffc++ :) * * Revision 1.21 1998/06/19 18:18:04 kalle * Cleaned up debugging messages * * This was my last change before KDE 1.0. * * Revision 1.20 1998/06/16 06:03:12 kalle * Implemented copy constructors and assignment operators or disabled them * * Revision 1.19 1998/03/09 20:21:52 kulow * just remove the dragZone from the dragZoneList, if kapp is still exist. * If this happens in the end of the application, big problems accour (the * reason, for many segfaults of applications at exit) * * Revision 1.18 1998/01/18 14:38:28 kulow * reverted the changes, Jacek commited. * Only the RCS comments were affected, but to keep them consistent, I * thought, it's better to revert them. * I checked twice, that only comments are affected ;) * * Revision 1.16 1997/11/04 11:00:30 kulow * fixed some free mismatch errors * * Revision 1.15 1997/10/21 20:44:40 kulow * removed all NULLs and replaced it with 0L or "". * There are some left in mediatool, but this is not C++ * * Revision 1.14 1997/10/16 11:14:26 torben * Kalle: Copyright headers * kdoctoolbar removed * * Revision 1.13 1997/10/12 11:05:32 kulow * don't export debugWin. kmenuedit used the same name * * Revision 1.12 1997/10/04 14:51:31 kulow * added some prototypes in case the shape.h is not found. I'm not sure, * if this works, but it helps for compiling * * Revision 1.11 1997/09/18 12:47:15 kulow * uups. The error message is not valid for the cpp file * * Revision 1.10 1997/09/18 12:16:03 kulow * corrected some header dependencies. Removed most of them in drag.h and put * them in drag.cpp. Now it should compile even under SunOS 4.4.1 ;) * * Revision 1.9 1997/08/31 08:03:47 kdecvs * Heureka: Fritz fixed the dragging of icons on the root window (Kalle) * * Revision 1.8 1997/07/31 19:52:31 kalle * Root-drop bug hopefully fixed (courtesy of Fritz Elfert of ISDN4Linux fame) * * Revision 1.7 1997/05/09 15:10:10 kulow * Coolo: patched ltconfig for FreeBSD * removed some stupid warnings * * Revision 1.6 1997/05/09 08:23:40 kulow * Coolo: included X11 headers again in drag.cpp (my fault) * * Revision 1.5 1997/05/08 22:53:15 kalle * Kalle: * KPixmap gone for good * Eliminated static objects from KApplication and HTML-Widget * * Revision 1.4 1997/05/08 21:09:44 kulow * Coolo: I forgot to include Torben's changes * * Revision 1.4 1997/03/10 19:59:12 kalle * Merged changes from 0.6.3 * * Revision 1.3 1997/01/15 20:01:58 kalle * merged changes from 0.52 * * Revision 1.2 1996/12/07 22:21:18 kalle * RCS header, include kapp.h * * * Drag 'n Drop implementation, taken from kfm * * Author: Torben Weis */#include "drag.h"#include <stdio.h>#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#ifdef STDC_HEADERS#include <stdlib.h>#endif#include <qlist.h>#include <qcursor.h>#include <qbitmap.h>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif #include "kapp.h"#include <X11/Xlib.h>#include <X11/Xatom.h>#include <X11/Xutil.h>#include <X11/Xos.h>#ifdef HAVE_X11_EXTENSTIONS_SHAPE_H#include <X11/extensions/shape.h>#elseextern "C" {void XShapeCombineMask(Display*, Window, int, int, int, Pixmap, int);#define ShapeBounding 0 #define ShapeSet 0 }#endifstatic Window debugWin = 0;KDNDDropZone::KDNDDropZone( QWidget* _parent, int _accept ) : QObject(){ widget = _parent; acceptType = _accept; kapp->addDropZone( this );}QWidget* KDNDDropZone::getWidget(){ return widget;}QStrList & KDNDDropZone::getURLList(){ return urlList;}void KDNDDropZone::parseURLList(){ urlList.clear(); if ( dndType != DndURL ) return; QString s = dndData; s.detach(); int i; while ( ( i = s.find( "\n" ) ) != -1 ) { QString t = s.left( i ); urlList.append( t.data() ); s = s.mid( i + 1, s.length() ); } urlList.append( s.data() );}void KDNDDropZone::drop( char *_data, int _size, int _type, int _x, int _y ){ dndSize = _size; dndType = _type; dndData = _data; dndX = _x; dndY = _y; parseURLList(); emit dropAction( this );}void KDNDDropZone::enter( char *_data, int _size, int _type, int _x, int _y ){ dndSize = _size; dndType = _type; dndData = _data; dndX = _x; dndY = _y; parseURLList(); emit dropEnter( this );}void KDNDDropZone::leave(){ emit dropLeave( this );}KDNDDropZone::~KDNDDropZone(){ if (kapp) kapp->removeDropZone( this );}void KDNDWidget::startDrag( KDNDIcon *_icon, char *_data, int _size, int _type, int _dx, int _dy ){ if ( dndData != 0 ) delete [] dndData ; drag = true; dndData = new char[ _size + 1 ]; memcpy( dndData, _data, _size ); dndData[ _size ] = 0; dndSize = _size + 1; dndType = _type; dndIcon = _icon; dndOffsetX = _dx; dndOffsetY = _dy; dndIcon->raise(); dndLastWindow = (Window)0; Window root = DefaultRootWindow( kapp->getDisplay() ); XChangeProperty( kapp->getDisplay(), root, kapp->getDndSelectionAtom(), XA_STRING, 8, PropModeReplace, (const unsigned char*)dndData, dndSize); /* I commented this out, like mentioned by Paul Kendal (coolo) // Commenting this out will only work with click on focus window managers // grabMouse(); XGrabPointer(kapp->getDisplay(),root,False, ButtonMotionMask|ButtonPressMask|ButtonReleaseMask, GrabModeSync,GrabModeAsync,root, None, CurrentTime);*/ // KDNDApplication::setOverrideCursor( waitCursor );}Window KDNDWidget::findRootWindow( QPoint & p ){ int x,y; Window root = DefaultRootWindow( kapp->getDisplay() ); Window win; XTranslateCoordinates( kapp->getDisplay(), root, root, p.x(), p.y(), &x, &y, &win ); /* Window root; Window parent; Window *children; unsigned int cchildren; int win = -1; int win_x,win_y,win_h,win_w; root = DefaultRootWindow( kapp->getDisplay() ); XQueryTree( kapp->getDisplay(), root, &root, &parent, &children, &cchildren ); XWindowAttributes *attribs = new XWindowAttributes; for ( int i = 0; i < cchildren; i++ ) { int x,y; unsigned int w,h,b,d; XGetGeometry( kapp->getDisplay(), children[i], &root, &x, &y, &w, &h, &b, &d ); QRect r( x,y,w,h ); if ( r.contains( p ) && children[i] != dndIcon->winId() ) { XGetWindowAttributes( kapp->getDisplay(), children[i], attribs ); if ( attribs->map_state != 0 ) { win = children[i]; win_x = x; win_y = y; win_h = h; win_w = w; } } } delete attribs; */ return win;}/** * @oldErrorHandler stores the original error handler. */staticint (* oldErrorHandler)(Display *, XErrorEvent *) = 0L;/** * Errorhandler to be used during DND */staticint myErrorHandler(Display *d, XErrorEvent *e){ char msg[80]; XGetErrorText(d, e->error_code, msg, 80); // fprintf(stderr, "Ignored Error: %s\n", msg); // fprintf(stderr, "Request: Maj=%d Min=%di, Serial=%08lx\n", // e->request_code, e->minor_code, e->serial); return 0;}void KDNDWidget::mouseReleaseEvent( QMouseEvent * _mouse ){ if ( !drag ) { dndMouseReleaseEvent( _mouse ); return; } // KDNDApplication::restoreOverrideCursor(); dndIcon->move( -200, -200 ); // printf("************************************************************\n");// printf("*** id = %i ****\n", dndIcon->winId());// printf("************************************************************\n"); debugWin = dndIcon->winId(); QPoint p = mapToGlobal( _mouse->pos() ); Window root; root = DefaultRootWindow( kapp->getDisplay() ); Window win = findRootWindow( p );// printf("************************************************************\n");// printf("*** win = %ld **** dndLastWindow = %ld ****\n", win, dndLastWindow );// printf("************************************************************\n"); drag = false;/* I commented this out, since it works without (coolo) // Commenting this out will only work with click on focus window managers // releaseMouse(); XUngrabPointer(kapp->getDisplay(),CurrentTime);*/// printf("Ungarbbed\n"); // If we found a destination for the drop if ( win != 0 ) // if ( dndLastWindow != 0 ) { XWindowAttributes Wattr; XGetWindowAttributes(kapp->getDisplay(), win, &Wattr); if (Wattr.map_state != IsUnmapped) { // printf("Sending event\n"); XEvent Event; Event.xclient.type = ClientMessage; Event.xclient.display = kapp->getDisplay(); Event.xclient.message_type = kapp->getDndProtocolAtom(); Event.xclient.format = 32; Event.xclient.window = dndLastWindow; Event.xclient.data.l[0] = dndType; Event.xclient.data.l[1] = 0; Event.xclient.data.l[2] = 0; Event.xclient.data.l[3] = p.x(); Event.xclient.data.l[4] = p.y(); // Switch to "friendly" error handler. if (oldErrorHandler == 0L) oldErrorHandler = XSetErrorHandler(myErrorHandler);// printf("1\n"); XSendEvent( kapp->getDisplay(), dndLastWindow, True, NoEventMask, &Event ); // printf("2\n"); XSync( kapp->getDisplay(), FALSE ); // printf("3\n"); (void) XSetErrorHandler(oldErrorHandler); oldErrorHandler = 0L; } delete [] dndData; dndData = 0L; } else {// printf("Root Drop Event\n"); rootDropEvent( p.x(), p.y() ); } delete dndIcon; dndIcon = 0L; dragEndEvent();}void KDNDWidget::mouseMoveEvent( QMouseEvent * _mouse ){ if ( !drag ) { dndMouseMoveEvent( _mouse ); return; } // dndIcon->hide(); // QPoint p = mapToGlobal( _mouse->pos() ); QPoint p = QCursor::pos(); /* Window root; root = DefaultRootWindow( kapp->getDisplay() ); Window win = findRootWindow( p ); printf("Window = '%x' %i %i\n",win,dndOffsetX,dndOffsetY); printf("x=%i y=%i\n",p.x(),p.y()); */ QPoint p2( p.x(), p.y() ); p2.setX( p2.x() + dndOffsetX ); p2.setY( p2.y() + dndOffsetY ); dndIcon->move( p2 ); // dndIcon->show();}void KDNDWidget::rootDropEvent( int _x, int _y ){ Window root; Window parent; Window *children; unsigned int cchildren; // printf("Root Window\n"); root = DefaultRootWindow( kapp->getDisplay() );// printf("Query root tree\n"); // Switch to "friendly" error handler. if (oldErrorHandler == 0L) oldErrorHandler = XSetErrorHandler(myErrorHandler); XQueryTree( kapp->getDisplay(), root, &root, &parent, &children, &cchildren ); for ( uint i = 0; i < cchildren; i++ ) { if ( children[i] == debugWin ) {}// printf("******************** root id = %ld *********************\n",children[i] ); else { XEvent Event; XWindowAttributes Wattr; XGetWindowAttributes(kapp->getDisplay(), children[i], &Wattr); if (Wattr.map_state == IsUnmapped) continue; Event.xclient.type = ClientMessage; Event.xclient.display = kapp->getDisplay(); Event.xclient.message_type = kapp->getDndRootProtocolAtom(); Event.xclient.format = 32; Event.xclient.window = children[ i ]; Event.xclient.data.l[0] = dndType; Event.xclient.data.l[1] = (long) time( 0L ); Event.xclient.data.l[2] = 0; Event.xclient.data.l[3] = _x; Event.xclient.data.l[4] = _y; XSendEvent( kapp->getDisplay(), children[ i ], True, NoEventMask, &Event); XSync( kapp->getDisplay(), FALSE ); } } (void)XSetErrorHandler(oldErrorHandler); oldErrorHandler = 0L;// printf("Done\n"); // Clean up. rootDropEvent();}void KDNDWidget::rootDropEvent(){ if ( dndIcon != 0L ) delete dndIcon; dndIcon = 0L; if ( dndData != 0L ) delete [] dndData; dndData = 0L;}KDNDWidget::~KDNDWidget(){ if ( dndData != 0L ) delete [] dndData;}KDNDIcon::KDNDIcon( QPixmap &_pixmap, int _x, int _y ) : QWidget( 0L, 0L, WStyle_Customize | WStyle_Tool | WStyle_NoBorder ){ pixmap = _pixmap; setGeometry( _x, _y, _pixmap.width(), _pixmap.height() ); show();}KDNDIcon::KDNDIcon( const KDNDIcon& icon ) : QWidget(){ pixmap = icon.pixmap; // implicitly ref-counted}KDNDIcon& KDNDIcon::operator= ( const KDNDIcon& icon ){ if( this != &icon ) pixmap = icon.pixmap; return *this;}void KDNDIcon::paintEvent( QPaintEvent * ) { bitBlt( this, 0,0, &pixmap );}void KDNDIcon::resizeEvent( QResizeEvent * ){ if ( pixmap.mask() != 0L ) XShapeCombineMask( x11Display(), winId(), ShapeBounding, 0, 0, pixmap.mask()->handle(), ShapeSet );}KDNDIcon::~KDNDIcon(){}#include "drag.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -