diff -Nru qt-x11-free-3.3.4.orig/include/qdragobject.h qt-x11-free-3.3.4/include/qdragobject.h --- qt-x11-free-3.3.4.orig/include/qdragobject.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/include/qdragobject.h 2005-03-19 20:00:47.000000000 +0100 @@ -245,10 +245,11 @@ void move( const QPoint & ); void drop(); void updatePixmap(); + void updatePixmap( const QPoint& cursorPos ); private: QDragObject * object; - void updateMode( ButtonState newstate ); + bool updateMode( ButtonState newstate ); void updateCursor(); QWidget * dragSource; diff -Nru qt-x11-free-3.3.4.orig/include/qiconview.h qt-x11-free-3.3.4/include/qiconview.h --- qt-x11-free-3.3.4.orig/include/qiconview.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/include/qiconview.h 2005-03-19 20:02:20.000000000 +0100 @@ -496,6 +496,8 @@ const QPoint &relativeTo, const QIconViewItem *item ) const; QBitmap mask( QPixmap *pix ) const; + int visibleWidthSB() const; + int visibleHeightSB() const; QIconViewPrivate *d; diff -Nru qt-x11-free-3.3.4.orig/include/qprogressbar.h qt-x11-free-3.3.4/include/qprogressbar.h --- qt-x11-free-3.3.4.orig/include/qprogressbar.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/include/qprogressbar.h 2005-03-19 20:01:42.000000000 +0100 @@ -61,6 +61,7 @@ public: QProgressBar( QWidget* parent=0, const char* name=0, WFlags f=0 ); QProgressBar( int totalSteps, QWidget* parent=0, const char* name=0, WFlags f=0 ); + virtual ~QProgressBar(); int totalSteps() const; int progress() const; @@ -91,6 +92,7 @@ virtual bool setIndicator( QString & progress_str, int progress, int totalSteps ); void styleChange( QStyle& ); + bool requireRepaint( int newProgress ) const; private: int total_steps; diff -Nru qt-x11-free-3.3.4.orig/include/qvaluelist.h qt-x11-free-3.3.4/include/qvaluelist.h --- qt-x11-free-3.3.4.orig/include/qvaluelist.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/include/qvaluelist.h 2005-03-19 20:01:36.000000000 +0100 @@ -638,13 +638,11 @@ l.clear(); Q_UINT32 c; s >> c; - for( Q_UINT32 i = 0; i < c; ++i ) + for( Q_UINT32 i = 0; i < c && !s.atEnd(); ++i ) { T t; s >> t; l.append( t ); - if ( s.atEnd() ) - break; } return s; } diff -Nru qt-x11-free-3.3.4.orig/mkspecs/linux-g++/qplatformdefs.h qt-x11-free-3.3.4/mkspecs/linux-g++/qplatformdefs.h --- qt-x11-free-3.3.4.orig/mkspecs/linux-g++/qplatformdefs.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/mkspecs/linux-g++/qplatformdefs.h 2005-03-19 20:00:53.000000000 +0100 @@ -102,5 +102,6 @@ #define QT_VSNPRINTF ::vsnprintf #endif +#define QT_MITSHM #endif // QPLATFORMDEFS_H diff -Nru qt-x11-free-3.3.4.orig/src/iconview/qiconview.cpp qt-x11-free-3.3.4/src/iconview/qiconview.cpp --- qt-x11-free-3.3.4.orig/src/iconview/qiconview.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/iconview/qiconview.cpp 2005-03-19 20:02:35.000000000 +0100 @@ -236,6 +236,7 @@ QPoint dragStartPos; QFontMetrics *fm; int minLeftBearing, minRightBearing; + int rubberStartX, rubberStartY; uint mousePressed :1; uint cleared :1; @@ -255,9 +256,11 @@ uint firstSizeHint : 1; uint showTips :1; uint pressedSelected :1; + uint canStartRubber :1; uint dragging :1; uint drawActiveSelection :1; uint inMenuMode :1; + uint controlPressed :1; QIconViewToolTip *toolTip; QPixmapCache maskCache; @@ -1060,7 +1063,7 @@ if ( view ) { if ( QRect( view->contentsX(), view->contentsY(), - view->visibleWidth(), view->visibleHeight() ). + view->visibleWidthSB(), view->visibleHeightSB() ). intersects( oR ) ) view->repaintContents( oR.x() - 1, oR.y() - 1, oR.width() + 2, oR.height() + 2, FALSE ); @@ -1104,7 +1107,7 @@ if ( view ) { if ( QRect( view->contentsX(), view->contentsY(), - view->visibleWidth(), view->visibleHeight() ). + view->visibleWidthSB(), view->visibleHeightSB() ). intersects( oR ) ) view->repaintContents( oR.x() - 1, oR.y() - 1, oR.width() + 2, oR.height() + 2, FALSE ); @@ -1140,7 +1143,7 @@ if ( view ) { if ( QRect( view->contentsX(), view->contentsY(), - view->visibleWidth(), view->visibleHeight() ). + view->visibleWidthSB(), view->visibleHeightSB() ). intersects( oR ) ) view->repaintContents( oR.x() - 1, oR.y() - 1, oR.width() + 2, oR.height() + 2, FALSE ); @@ -1200,7 +1203,7 @@ if ( view ) { if ( QRect( view->contentsX(), view->contentsY(), - view->visibleWidth(), view->visibleHeight() ). + view->visibleWidthSB(), view->visibleHeightSB() ). intersects( oR ) ) view->repaintContents( oR.x() - 1, oR.y() - 1, oR.width() + 2, oR.height() + 2, FALSE ); @@ -2729,10 +2732,12 @@ d->lastItem = 0; d->count = 0; d->mousePressed = FALSE; + d->controlPressed = FALSE; d->selectionMode = Single; d->currentItem = 0; d->highlightedItem = 0; d->rubber = 0; + d->canStartRubber = FALSE; d->scrollTimer = 0; d->startDragItem = 0; d->tmpCurrentItem = 0; @@ -3294,9 +3299,18 @@ alreadyIntersected = TRUE; QIconViewItem *item = c->items.first(); for ( ; item; item = c->items.next() ) { - if ( d->selectedItems.find( item ) ) - continue; - if ( !item->intersects( nr ) ) { + if ( d->selectedItems.find( item ) ) { + if ( item->intersects( nr ) && item->isSelected() && d->controlPressed ) { + item->setSelected( FALSE ); + changed = TRUE; + rr = rr.unite( item->rect() ); + } else if ( !item->intersects( nr ) && !item->isSelected() && d->controlPressed ) { + item->setSelected( TRUE, TRUE ); + changed = TRUE; + rr = rr.unite( item->rect() ); + } else + continue; + } else if ( !item->intersects( nr ) ) { if ( item->isSelected() ) { item->setSelected( FALSE ); changed = TRUE; @@ -4487,34 +4501,25 @@ } } } else if ( ( d->selectionMode != Single || e->button() == RightButton ) - && !( e->state() & ControlButton ) ) + && !( e->state() & ControlButton ) && !( e->state() & ShiftButton ) ) selectAll( FALSE ); setCurrentItem( item ); + d->canStartRubber = FALSE; if ( e->button() == LeftButton ) { - if ( !item && ( d->selectionMode == Multi || - d->selectionMode == Extended ) ) { - d->tmpCurrentItem = d->currentItem; - d->currentItem = 0; - repaintItem( d->tmpCurrentItem ); - if ( d->rubber ) - delete d->rubber; - d->rubber = 0; - d->rubber = new QRect( e->x(), e->y(), 0, 0 ); - d->selectedItems.clear(); - if ( ( e->state() & ControlButton ) == ControlButton ) { - for ( QIconViewItem *i = firstItem(); i; i = i->nextItem() ) - if ( i->isSelected() ) - d->selectedItems.insert( i, i ); - } + if ( !item && ( d->selectionMode == Multi || d->selectionMode == Extended ) ) + { + d->canStartRubber = TRUE; + d->rubberStartX = e->x(); + d->rubberStartY = e->y(); } - d->mousePressed = TRUE; + d->controlPressed = ( ( e->state() & ControlButton ) == ControlButton ); } emit_signals: - if ( !d->rubber ) { + if ( !d->canStartRubber ) { emit mouseButtonPressed( e->button(), item, e->globalPos() ); emit pressed( item ); emit pressed( item, e->globalPos() ); @@ -4558,6 +4563,7 @@ d->mousePressed = FALSE; d->startDragItem = 0; + d->canStartRubber = FALSE; if ( d->rubber ) { QPainter p; p.begin( viewport() ); @@ -4647,7 +4653,22 @@ if ( d->tmpCurrentItem ) repaintItem( d->tmpCurrentItem ); } - } else if ( d->mousePressed && !d->currentItem && d->rubber ) { + } else if ( d->mousePressed && ((!d->currentItem && d->rubber) || d->canStartRubber) ) { + if ( d->canStartRubber ) { + d->canStartRubber = FALSE; + d->tmpCurrentItem = d->currentItem; + d->currentItem = 0; + repaintItem( d->tmpCurrentItem ); + delete d->rubber; + d->rubber = new QRect( d->rubberStartX, d->rubberStartY, 0, 0 ); + d->selectedItems.clear(); + if ( ( e->state() & ControlButton ) == ControlButton || + ( e->state() & ShiftButton ) == ShiftButton ) { + for ( QIconViewItem *i = firstItem(); i; i = i->nextItem() ) + if ( i->isSelected() ) + d->selectedItems.insert( i, i ); + } + } doAutoScroll(); } } @@ -5224,11 +5245,11 @@ d->findContainers( dir, relativeTo, searchRect); cList->first(); - while ( cList->current() && !centerMatch ) { + while ( cList->current() ) { QPtrList &list = (cList->current())->items; for ( item = list.first(); item; item = list.next() ) { if ( neighbourItem( dir, relativeTo, item ) && - searchRect.contains( item->rect().center() ) && + searchRect.intersects( item->rect() ) && item != currentItem() ) { int ml = (relativeTo - item->rect().center()).manhattanLength(); if ( centerMatch ) { @@ -5451,8 +5472,8 @@ } item->dirty = FALSE; } else { - QRegion r( QRect( 0, 0, QMAX( contentsWidth(), visibleWidth() ), - QMAX( contentsHeight(), visibleHeight() ) ) ); + QRegion r( QRect( 0, 0, QMAX( contentsWidth(), visibleWidthSB() ), + QMAX( contentsHeight(), visibleHeightSB() ) ) ); QIconViewItem *i = d->firstItem; int y = -1; @@ -5710,7 +5731,7 @@ QIconViewItem *item = begin; for (;;) { x += d->spacing + item->width(); - if ( x > visibleWidth() && item != begin ) { + if ( x > visibleWidthSB() && item != begin ) { item = item->prev; break; } @@ -5735,7 +5756,7 @@ int x; if ( item == begin ) { if ( reverse ) - x = visibleWidth() - d->spacing - item->width(); + x = visibleWidthSB() - d->spacing - item->width(); else x = d->spacing; } else { @@ -5771,7 +5792,7 @@ i += r; x = i * d->rastX + sp * d->spacing; } - if ( x > visibleWidth() && item != begin ) { + if ( x > visibleWidthSB() && item != begin ) { item = item->prev; break; } @@ -5834,7 +5855,7 @@ QIconViewItem *item = begin; for (;;) { y += d->spacing + item->height(); - if ( y > visibleHeight() && item != begin ) { + if ( y > visibleHeightSB() && item != begin ) { item = item->prev; break; } @@ -6148,7 +6169,9 @@ item->d->container2 = 0; c->items.append( item ); item = item->next; - } else if ( c->rect.intersects( item->rect() ) ) { + } else if ( c->rect.intersects( item->rect() ) && ( + ( d->arrangement == LeftToRight && item->y() >= c->rect.y() ) || + ( d->arrangement == TopToBottom && item->x() >= c->rect.x() ) ) ) { item->d->container1 = c; c->items.append( item ); c = c->n; @@ -6381,4 +6404,24 @@ #endif } +int QIconView::visibleWidthSB() const +{ + if ( vScrollBarMode() != Auto ) + return visibleWidth(); + + int offset = verticalScrollBar()->isVisible() ? 0 + : style().pixelMetric( QStyle::PM_ScrollBarExtent, verticalScrollBar() ); + return QMAX( 0, visibleWidth() - offset ); +} + +int QIconView::visibleHeightSB() const +{ + if ( hScrollBarMode() != Auto ) + return visibleHeight(); + + int offset = horizontalScrollBar()->isVisible() ? 0 + : style().pixelMetric( QStyle::PM_ScrollBarExtent, horizontalScrollBar() ); + return QMAX( 0, visibleHeight() - offset ); +} + #endif // QT_NO_ICONVIEW diff -Nru qt-x11-free-3.3.4.orig/src/iconview/qiconview.h qt-x11-free-3.3.4/src/iconview/qiconview.h --- qt-x11-free-3.3.4.orig/src/iconview/qiconview.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/iconview/qiconview.h 2005-03-19 20:02:20.000000000 +0100 @@ -496,6 +496,8 @@ const QPoint &relativeTo, const QIconViewItem *item ) const; QBitmap mask( QPixmap *pix ) const; + int visibleWidthSB() const; + int visibleHeightSB() const; QIconViewPrivate *d; diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qapplication_x11.cpp qt-x11-free-3.3.4/src/kernel/qapplication_x11.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qapplication_x11.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qapplication_x11.cpp 2005-03-19 20:02:50.000000000 +0100 @@ -3405,10 +3405,23 @@ // update the size for desktop widget int scr = XRRRootToScreen( appDpy, event->xany.window ); + + // Determine if we're at right-angles & thus DisplayWidth/DisplayHeight should be switched + XRRScreenConfiguration* xrrconfig; + xrrconfig = XRRGetScreenInfo( appDpy, event->xany.window ); + Rotation rotation; + XRRConfigCurrentConfiguration( xrrconfig, &rotation ); + XRRFreeScreenConfigInfo( xrrconfig ); + QWidget *w = desktop()->screen( scr ); QSize oldSize( w->size() ); - w->crect.setWidth( DisplayWidth( appDpy, scr ) ); - w->crect.setHeight( DisplayHeight( appDpy, scr ) ); + if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { + w->crect.setWidth( DisplayHeight( appDpy, scr ) ); + w->crect.setHeight( DisplayWidth( appDpy, scr ) ); + } else { + w->crect.setWidth( DisplayWidth( appDpy, scr ) ); + w->crect.setHeight( DisplayHeight( appDpy, scr ) ); + } if ( w->size() != oldSize ) { QResizeEvent e( w->size(), oldSize ); QApplication::sendEvent( w, &e ); @@ -3967,7 +3980,7 @@ // Keyboard event translation // -static int translateButtonState( int s ) +int qt_x11_translateButtonState( int s ) { int bst = 0; if ( s & Button1Mask ) @@ -4033,7 +4046,7 @@ pos.ry() = lastMotion.y; globalPos.rx() = lastMotion.x_root; globalPos.ry() = lastMotion.y_root; - state = translateButtonState( lastMotion.state ); + state = qt_x11_translateButtonState( lastMotion.state ); if ( qt_button_down && (state & (LeftButton | MidButton | RightButton ) ) == 0 ) @@ -4057,7 +4070,7 @@ pos.ry() = xevent->xcrossing.y; globalPos.rx() = xevent->xcrossing.x_root; globalPos.ry() = xevent->xcrossing.y_root; - state = translateButtonState( xevent->xcrossing.state ); + state = qt_x11_translateButtonState( xevent->xcrossing.state ); if ( qt_button_down && (state & (LeftButton | MidButton | RightButton ) ) == 0 ) @@ -4069,7 +4082,7 @@ pos.ry() = event->xbutton.y; globalPos.rx() = event->xbutton.x_root; globalPos.ry() = event->xbutton.y_root; - state = translateButtonState( event->xbutton.state ); + state = qt_x11_translateButtonState( event->xbutton.state ); switch ( event->xbutton.button ) { case Button1: button = LeftButton; break; case Button2: button = MidButton; break; @@ -5013,7 +5026,7 @@ XKeyEvent xkeyevent = event->xkey; // save the modifier state, we will use the keystate uint later by passing - // it to translateButtonState + // it to qt_x11_translateButtonState uint keystate = event->xkey.state; // remove the modifiers where mode_switch exists... HPUX machines seem // to have alt *AND* mode_switch both in Mod1Mask, which causes @@ -5127,7 +5140,7 @@ } #endif // !QT_NO_XIM - state = translateButtonState( keystate ); + state = qt_x11_translateButtonState( keystate ); static int directionKeyEvent = 0; if ( qt_use_rtl_extensions && type == QEvent::KeyRelease ) { @@ -5289,8 +5302,10 @@ qt_auto_repeat_data *d = (qt_auto_repeat_data *) arg; if (d->error || event->xkey.window != d->window || - event->xkey.keycode != d->keycode) + event->xkey.keycode != d->keycode) { + d->error = TRUE; return FALSE; + } if (event->type == XKeyPress) { d->error = (! d->release || event->xkey.time - d->timestamp > 10); diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qclipboard_x11.cpp qt-x11-free-3.3.4/src/kernel/qclipboard_x11.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qclipboard_x11.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qclipboard_x11.cpp 2005-03-19 20:02:30.000000000 +0100 @@ -109,6 +109,7 @@ static bool pending_clipboard_changed = FALSE; static bool pending_selection_changed = FALSE; +Q_EXPORT bool qt_qclipboard_bailout_hack = false; // event capture mechanism for qt_xclb_wait_for_event static bool waiting_for_data = FALSE; @@ -453,6 +454,15 @@ return 0; } +static bool selection_request_pending = false; + +static Bool check_selection_request_pending( Display*, XEvent* e, XPointer ) + { + if( e->type == SelectionRequest && e->xselectionrequest.owner == owner->winId()) + selection_request_pending = true; + return False; + } + bool qt_xclb_wait_for_event( Display *dpy, Window win, int type, XEvent *event, int timeout ) { @@ -504,6 +514,14 @@ do { if ( XCheckTypedWindowEvent(dpy,win,type,event) ) return TRUE; + if( qt_qclipboard_bailout_hack ) { + XEvent dummy; + selection_request_pending = false; + if ( owner != NULL ) + XCheckIfEvent(dpy,&dummy,check_selection_request_pending,NULL); + if( selection_request_pending ) + return TRUE; + } now = QTime::currentTime(); if ( started > now ) // crossed midnight diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qdesktopwidget_x11.cpp qt-x11-free-3.3.4/src/kernel/qdesktopwidget_x11.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qdesktopwidget_x11.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qdesktopwidget_x11.cpp 2005-03-19 20:01:30.000000000 +0100 @@ -44,6 +44,9 @@ // defined in qapplication_x11.cpp extern Atom qt_net_workarea; extern bool qt_net_supports(Atom atom); +#ifndef QT_NO_XRANDR +extern bool qt_use_xrandr; +#endif // function to update the workarea of the screen static bool qt_desktopwidget_workarea_dirty = TRUE; @@ -154,6 +157,22 @@ y = 0; w = WidthOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), i)); h = HeightOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), i)); + +#ifndef QT_NO_XRANDR + if (qt_use_xrandr) { + XRRScreenConfiguration* xrrconfig; + xrrconfig = XRRGetScreenInfo(QPaintDevice::x11AppDisplay(), QPaintDevice::x11AppRootWindow( i )); + Rotation rotation; + XRRConfigCurrentConfiguration(xrrconfig, &rotation); + XRRFreeScreenConfigInfo(xrrconfig); + + if (rotation & (RR_Rotate_90 | RR_Rotate_270)) { + int tmp = h; + h = w; + w = tmp; + } + } +#endif } rects[i].setRect(x, y, w, h); diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qdnd_x11.cpp qt-x11-free-3.3.4/src/kernel/qdnd_x11.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qdnd_x11.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qdnd_x11.cpp 2005-03-19 20:01:47.000000000 +0100 @@ -49,13 +49,15 @@ #include "qdragobject.h" #include "qobjectlist.h" #include "qcursor.h" +#include "qbitmap.h" +#include "qpainter.h" #include "qt_x11_p.h" // conflict resolution -// unused, may be used again later: const int XKeyPress = KeyPress; -// unused, may be used again later: const int XKeyRelease = KeyRelease; +const int XKeyPress = KeyPress; +const int XKeyRelease = KeyRelease; #undef KeyPress #undef KeyRelease @@ -79,6 +81,7 @@ extern Window qt_x11_findClientWindow( Window, Atom, bool ); extern Atom qt_wm_state; extern Time qt_x_time; +extern Time qt_x_user_time; // this stuff is copied from qclb_x11.cpp @@ -112,6 +115,8 @@ Atom qt_xdnd_type_list; const int qt_xdnd_version = 4; +extern int qt_x11_translateButtonState( int s ); + // Actions // // The Xdnd spec allows for user-defined actions. This could be implemented @@ -196,6 +201,8 @@ static int qt_xdnd_current_screen = -1; // state of dragging... true if dragging, false if not bool qt_xdnd_dragging = FALSE; +// need to check state of keyboard modifiers +static bool need_modifiers_check = FALSE; // dict of payload data, sorted by type atom static QIntDict * qt_xdnd_target_data = 0; @@ -251,20 +258,47 @@ public: QShapedPixmapWidget(int screen = -1) : QWidget(QApplication::desktop()->screen( screen ), - 0, WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM ) + 0, WStyle_Customize | WStyle_Tool | WStyle_NoBorder | WX11BypassWM ), oldpmser( 0 ), oldbmser( 0 ) { } - void setPixmap(QPixmap pm) + void setPixmap(QPixmap pm, QPoint hot) { - if ( pm.mask() ) { + int bmser = pm.mask() ? pm.mask()->serialNumber() : 0; + if( oldpmser == pm.serialNumber() && oldbmser == bmser + && oldhot == hot ) + return; + oldpmser = pm.serialNumber(); + oldbmser = bmser; + oldhot = hot; + bool hotspot_in = !(hot.x() < 0 || hot.y() < 0 || hot.x() >= pm.width() || hot.y() >= pm.height()); +// if the pixmap has hotspot in its area, make a "hole" in it at that position +// this will allow XTranslateCoordinates() to find directly the window below the cursor instead +// of finding this pixmap, and therefore there won't be needed any (slow) search for the window +// using findRealWindow() + if( hotspot_in ) { + QBitmap mask = pm.mask() ? *pm.mask() : QBitmap( pm.width(), pm.height()); + if( !pm.mask()) + mask.fill( Qt::color1 ); + QPainter p( &mask ); + p.setPen( Qt::color0 ); + p.drawPoint( hot.x(), hot.y()); + p.end(); + pm.setMask( mask ); + setMask( mask ); + } else if ( pm.mask() ) { setMask( *pm.mask() ); } else { clearMask(); } resize(pm.width(),pm.height()); setErasePixmap(pm); + erase(); } +private: + int oldpmser; + int oldbmser; + QPoint oldhot; }; static QShapedPixmapWidget * qt_xdnd_deco = 0; @@ -801,6 +835,9 @@ // l[0], qt_xdnd_dragsource_xid ); return; } + + if( l[2] != 0 ) + qt_x_user_time = l[2]; if ( qt_xdnd_source_object ) qt_xdnd_source_object->setTarget( qt_xdnd_current_widget ); @@ -851,8 +888,59 @@ void QDragManager::timerEvent( QTimerEvent* e ) { - if ( e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull() ) - move( QCursor::pos() ); + if ( e->timerId() == heartbeat ) { + if( need_modifiers_check ) { + Window root, child; + int root_x, root_y, win_x, win_y; + unsigned int mask; + XQueryPointer( qt_xdisplay(), qt_xrootwin( qt_xdnd_current_screen ), + &root, &child, &root_x, &root_y, &win_x, &win_y, &mask ); + if( updateMode( (ButtonState)qt_x11_translateButtonState( mask ))) + qt_xdnd_source_sameanswer = QRect(); // force move + } + need_modifiers_check = TRUE; + if( qt_xdnd_source_sameanswer.isNull() ) + move( QCursor::pos() ); + } +} + +static bool qt_xdnd_was_move = false; +static bool qt_xdnd_found = false; +// check whole incoming X queue for move events +// checking whole queue is done by always returning False in the predicate +// if there's another move event in the queue, and there's not a mouse button +// or keyboard or ClientMessage event before it, the current move event +// may be safely discarded +// this helps avoiding being overloaded by being flooded from many events +// from the XServer +static +Bool qt_xdnd_predicate( Display*, XEvent* ev, XPointer ) +{ + if( qt_xdnd_found ) + return False; + if( ev->type == MotionNotify ) + { + qt_xdnd_was_move = true; + qt_xdnd_found = true; + } + if( ev->type == ButtonPress || ev->type == ButtonRelease + || ev->type == XKeyPress || ev->type == XKeyRelease + || ev->type == ClientMessage ) + { + qt_xdnd_was_move = false; + qt_xdnd_found = true; + } + return False; +} + +static +bool qt_xdnd_another_movement() +{ + qt_xdnd_was_move = false; + qt_xdnd_found = false; + XEvent dummy; + XCheckIfEvent( qt_xdisplay(), &dummy, qt_xdnd_predicate, NULL ); + return qt_xdnd_was_move; } bool QDragManager::eventFilter( QObject * o, QEvent * e) @@ -877,8 +965,11 @@ if ( e->type() == QEvent::MouseMove ) { QMouseEvent* me = (QMouseEvent *)e; - updateMode(me->stateAfter()); - move( me->globalPos() ); + if( !qt_xdnd_another_movement()) { + updateMode(me->stateAfter()); + move( me->globalPos() ); + } + need_modifiers_check = FALSE; return TRUE; } else if ( e->type() == QEvent::MouseButtonRelease ) { qApp->removeEventFilter( this ); @@ -917,9 +1008,11 @@ beingCancelled = FALSE; qApp->exit_loop(); } else { - updateMode(ke->stateAfter()); - qt_xdnd_source_sameanswer = QRect(); // force move - move( QCursor::pos() ); + if( updateMode(ke->stateAfter())) { + qt_xdnd_source_sameanswer = QRect(); // force move + move( QCursor::pos() ); + } + need_modifiers_check = FALSE; } return TRUE; // Eat all key events } @@ -946,10 +1039,10 @@ static Qt::ButtonState oldstate; -void QDragManager::updateMode( ButtonState newstate ) +bool QDragManager::updateMode( ButtonState newstate ) { if ( newstate == oldstate ) - return; + return false; const int both = ShiftButton|ControlButton; if ( (newstate & both) == both ) { global_requested_action = QDropEvent::Link; @@ -973,6 +1066,7 @@ } } oldstate = newstate; + return true; } @@ -1109,7 +1203,7 @@ qt_xdnd_deco->grabMouse(); } } - updatePixmap(); + updatePixmap( globalPos ); if ( qt_xdnd_source_sameanswer.contains( globalPos ) && qt_xdnd_source_sameanswer.isValid() ) { @@ -1281,9 +1375,9 @@ drop.format = 32; drop.message_type = qt_xdnd_drop; drop.data.l[0] = object->source()->winId(); - drop.data.l[1] = 1 << 24; // flags - drop.data.l[2] = 0; // ### - drop.data.l[3] = qt_x_time; + drop.data.l[1] = 0; // flags + drop.data.l[2] = qt_x_time; + drop.data.l[3] = 0; drop.data.l[4] = 0; QWidget * w = QWidget::find( qt_xdnd_current_proxy_target ); @@ -1637,6 +1731,7 @@ qt_xdnd_source_sameanswer = QRect(); move(QCursor::pos()); heartbeat = startTimer(200); + need_modifiers_check = FALSE; #ifndef QT_NO_CURSOR qApp->setOverrideCursor( arrowCursor ); @@ -1670,7 +1765,7 @@ // qt_xdnd_source_object persists until we get an xdnd_finish message } -void QDragManager::updatePixmap() +void QDragManager::updatePixmap( const QPoint& cursorPos ) { if ( qt_xdnd_deco ) { QPixmap pm; @@ -1685,9 +1780,8 @@ defaultPm = new QPixmap(default_pm); pm = *defaultPm; } - qt_xdnd_deco->setPixmap(pm); - qt_xdnd_deco->move(QCursor::pos()-pm_hot); - qt_xdnd_deco->repaint(FALSE); + qt_xdnd_deco->setPixmap(pm, pm_hot); + qt_xdnd_deco->move(cursorPos-pm_hot); //if ( willDrop ) { qt_xdnd_deco->show(); //} else { @@ -1696,4 +1790,9 @@ } } +void QDragManager::updatePixmap() +{ + updatePixmap( QCursor::pos()); +} + #endif // QT_NO_DRAGANDDROP diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qdragobject.cpp qt-x11-free-3.3.4/src/kernel/qdragobject.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qdragobject.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qdragobject.cpp 2005-03-19 20:01:52.000000000 +0100 @@ -891,6 +891,16 @@ if(!e) return FALSE; + // when subtype is not specified, try text/plain first, otherwise this may read + // things like text/x-moz-url even though better targets are available + if( subtype.isNull()) { + QCString subtmp = "plain"; + if( decode( e, str, subtmp )) { + subtype = subtmp; + return true; + } + } + if ( e->cacheType == QMimeSource::Text ) { str = *e->cache.txt.str; subtype = *e->cache.txt.subtype; diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qdragobject.h qt-x11-free-3.3.4/src/kernel/qdragobject.h --- qt-x11-free-3.3.4.orig/src/kernel/qdragobject.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qdragobject.h 2005-03-19 20:00:47.000000000 +0100 @@ -245,10 +245,11 @@ void move( const QPoint & ); void drop(); void updatePixmap(); + void updatePixmap( const QPoint& cursorPos ); private: QDragObject * object; - void updateMode( ButtonState newstate ); + bool updateMode( ButtonState newstate ); void updateCursor(); QWidget * dragSource; diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qpixmap_x11.cpp qt-x11-free-3.3.4/src/kernel/qpixmap_x11.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qpixmap_x11.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qpixmap_x11.cpp 2005-03-19 20:00:59.000000000 +0100 @@ -37,7 +37,19 @@ // NOT REVISED +#include "qplatformdefs.h" + +#if defined(Q_OS_WIN32) && defined(QT_MITSHM) +#undef QT_MITSHM +#endif + +#ifdef QT_MITSHM + +// Use the MIT Shared Memory extension for pixmap<->image conversions +#define QT_MITSHM_CONVERSIONS + // Uncomment the next line to enable the MIT Shared Memory extension +// for QPixmap::xForm() // // WARNING: This has some problems: // @@ -45,14 +57,13 @@ // 2. Qt does not handle the ShmCompletion message, so you will // get strange effects if you xForm() repeatedly. // -// #define QT_MITSHM +// #define QT_MITSHM_XFORM -#if defined(Q_OS_WIN32) && defined(QT_MITSHM) -#undef QT_MITSHM +#else +#undef QT_MITSHM_CONVERSIONS +#undef QT_MITSHM_XFORM #endif -#include "qplatformdefs.h" - #include "qbitmap.h" #include "qpaintdevicemetrics.h" #include "qimage.h" @@ -91,7 +102,7 @@ MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster. *****************************************************************************/ -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) static bool xshminit = FALSE; static XShmSegmentInfo xshminfo; @@ -173,8 +184,100 @@ // return FALSE; // } -#endif // QT_MITSHM +#endif // QT_MITSHM_XFORM +#ifdef QT_MITSHM_CONVERSIONS + +static bool qt_mitshm_error = false; +static int qt_mitshm_errorhandler( Display*, XErrorEvent* ) +{ + qt_mitshm_error = true; + return 0; +} + +static XImage* qt_XShmCreateImage( Display* dpy, Visual* visual, unsigned int depth, + int format, int /*offset*/, char* /*data*/, unsigned int width, unsigned int height, + int /*bitmap_pad*/, int /*bytes_per_line*/, XShmSegmentInfo* shminfo ) +{ + if( width * height * depth < 100*100*32 ) + return NULL; + static int shm_inited = -1; + if( shm_inited == -1 ) { + if( XShmQueryExtension( dpy )) + shm_inited = 1; + else + shm_inited = 0; + } + if( shm_inited == 0 ) + return NULL; + XImage* xi = XShmCreateImage( dpy, visual, depth, format, NULL, shminfo, width, + height ); + if( xi == NULL ) + return NULL; + shminfo->shmid = shmget( IPC_PRIVATE, xi->bytes_per_line * xi->height, + IPC_CREAT|0600); + if( shminfo->shmid < 0 ) { + XDestroyImage( xi ); + return NULL; + } + shminfo->readOnly = False; + shminfo->shmaddr = (char*)shmat( shminfo->shmid, 0, 0 ); + if( shminfo->shmaddr == (char*)-1 ) { + XDestroyImage( xi ); + shmctl( shminfo->shmid, IPC_RMID, 0 ); + return NULL; + } + xi->data = shminfo->shmaddr; +#ifndef QT_MITSHM_RMID_IGNORES_REFCOUNT + // mark as deleted to automatically free the memory in case + // of a crash (but this doesn't work e.g. on Solaris) + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif + if( shm_inited == 1 ) { // first time + XErrorHandler old_h = XSetErrorHandler( qt_mitshm_errorhandler ); + XShmAttach( dpy, shminfo ); + shm_inited = 2; + XSync( dpy, False ); + XSetErrorHandler( old_h ); + if( qt_mitshm_error ) { // oops ... perhaps we are remote? + shm_inited = 0; + XDestroyImage( xi ); + shmdt( shminfo->shmaddr ); +#ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif + return NULL; + } + } else + XShmAttach( dpy, shminfo ); + return xi; +} + +static void qt_XShmDestroyImage( XImage* xi, XShmSegmentInfo* shminfo ) +{ + XShmDetach( QPaintDevice::x11AppDisplay(), shminfo ); + XDestroyImage( xi ); + shmdt( shminfo->shmaddr ); +#ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif +} + +static XImage* qt_XShmGetImage( const QPixmap* pix, int format, + XShmSegmentInfo* shminfo ) +{ + XImage* xi = qt_XShmCreateImage( pix->x11Display(), (Visual*)pix->x11Visual(), + pix->depth(), format, 0, 0, pix->width(), pix->height(), 32, 0, shminfo ); + if( xi == NULL ) + return NULL; + if( XShmGetImage( pix->x11Display(), pix->handle(), xi, 0, 0, AllPlanes ) == False ) { + qt_XShmDestroyImage( xi, shminfo ); + return NULL; + } + return xi; +} + +#endif // QT_MITSHM_CONVERSIONS /***************************************************************************** Internal functions @@ -624,9 +727,20 @@ d = 32; // > 8 ==> 32 XImage *xi = (XImage *)data->ximage; // any cached ximage? - if ( !xi ) // fetch data from X server - xi = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_ximage = false; + XShmSegmentInfo shminfo; +#endif + if ( !xi ) { // fetch data from X server +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmGetImage( this, mono ? XYPixmap : ZPixmap, &shminfo ); + if( xi ) { + mitshm_ximage = true; + } else +#endif + xi = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, mono ? XYPixmap : ZPixmap ); + } Q_CHECK_PTR( xi ); QImage::Endian bitOrder = QImage::IgnoreEndian; @@ -635,15 +749,31 @@ QImage::LittleEndian : QImage::BigEndian; } image.create( w, h, d, 0, bitOrder ); - if ( image.isNull() ) // could not create image + if ( image.isNull() ) { // could not create image +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); return image; + } const QPixmap* msk = mask(); const QPixmap *alf = data->alphapm; QImage alpha; if (alf) { - XImage *axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap); + XImage* axi; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_aximage = false; + XShmSegmentInfo ashminfo; + axi = qt_XShmGetImage( alf, ZPixmap, &ashminfo ); + if( axi ) { + mitshm_aximage = true; + } else +#endif + axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap); if (axi) { image.setAlphaBuffer( TRUE ); @@ -657,7 +787,12 @@ src += axi->bytes_per_line; } - qSafeXDestroyImage( axi ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + qt_XShmDestroyImage( axi, &ashminfo ); + else +#endif + qSafeXDestroyImage( axi ); } } else if (msk) { image.setAlphaBuffer( TRUE ); @@ -799,6 +934,12 @@ xi->bits_per_pixel ); #endif image.reset(); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); return image; } @@ -904,10 +1045,22 @@ delete [] carr; } if ( data->optim != BestOptim ) { // throw away image data - qSafeXDestroyImage( xi ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); ((QPixmap*)this)->data->ximage = 0; - } else // keep ximage data + } else { // keep ximage data +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) { // copy the XImage? + qt_XShmDestroyImage( xi, &shminfo ); + xi = 0; + } +#endif ((QPixmap*)this)->data->ximage = xi; + } return image; } @@ -1077,6 +1230,11 @@ bool trucol = (visual->c_class == TrueColor); int nbytes = image.numBytes(); uchar *newbits= 0; + int newbits_size = 0; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_ximage = false; + XShmSegmentInfo shminfo; +#endif if ( trucol ) { // truecolor display QRgb pix[256]; // pixel translation table @@ -1105,17 +1263,23 @@ } } - xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo ); + if( xi != NULL ) { + mitshm_ximage = true; + newbits = (uchar*)xi->data; + } + else +#endif + xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); Q_CHECK_PTR( xi ); - newbits = (uchar *)malloc( xi->bytes_per_line*h ); + if( newbits == NULL ) + newbits = (uchar *)malloc( xi->bytes_per_line*h ); Q_CHECK_PTR( newbits ); if ( !newbits ) // no memory return FALSE; int bppc = xi->bits_per_pixel; - if ( bppc > 8 && xi->byte_order == LSBFirst ) - bppc++; - bool contig_bits = n_bits(red_mask) == rbits && n_bits(green_mask) == gbits && n_bits(blue_mask) == bbits; @@ -1165,31 +1329,69 @@ init=TRUE; } - for ( uint y=0; ybytes_per_line*y; - QRgb* p = (QRgb *)src; + enum { BPP8, + BPP16_8_3_M3, BPP16_7_2_M3, BPP16_MSB, BPP16_LSB, + BPP24_MSB, BPP24_LSB, + BPP32_16_8_0, BPP32_MSB, BPP32_LSB + } mode = BPP8; -#define GET_RGB \ - int r = qRed ( *p ); \ - int g = qGreen( *p ); \ - int b = qBlue ( *p++ ); \ - r = red_shift > 0 \ - ? r << red_shift : r >> -red_shift; \ - g = green_shift > 0 \ - ? g << green_shift : g >> -green_shift; \ - b = blue_shift > 0 \ - ? b << blue_shift : b >> -blue_shift; + if ( bppc > 8 && xi->byte_order == LSBFirst ) + bppc++; + + int wordsize; + bool bigendian; + qSysInfo( &wordsize, &bigendian ); + bool same_msb_lsb = ( xi->byte_order == MSBFirst ) == ( bigendian ); + + if( bppc == 8 ) // 8 bit + mode = BPP8; + else if( bppc == 16 || bppc == 17 ) { // 16 bit MSB/LSB + if( red_shift == 8 && green_shift == 3 && blue_shift == -3 + && !d8 && same_msb_lsb ) + mode = BPP16_8_3_M3; + else if( red_shift == 7 && green_shift == 2 && blue_shift == -3 + && !d8 && same_msb_lsb ) + mode = BPP16_7_2_M3; + else + mode = bppc == 17 ? BPP16_LSB : BPP16_MSB; + } else if( bppc == 24 || bppc == 25 ) { // 24 bit MSB/LSB + mode = bppc == 25 ? BPP24_LSB : BPP24_MSB; + } else if( bppc == 32 || bppc == 33 ) { // 32 bit MSB/LSB + if( red_shift == 16 && green_shift == 8 && blue_shift == 0 + && !d8 && same_msb_lsb ) + mode = BPP32_16_8_0; + else + mode = bppc == 33 ? BPP32_LSB : BPP32_MSB; + } else + qFatal("Logic error 3"); #define GET_PIXEL \ int pixel; \ if ( d8 ) pixel = pix[*src++]; \ else { \ - GET_RGB \ - pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask) \ + int r = qRed ( *p ); \ + int g = qGreen( *p ); \ + int b = qBlue ( *p++ ); \ + r = red_shift > 0 \ + ? r << red_shift : r >> -red_shift; \ + g = green_shift > 0 \ + ? g << green_shift : g >> -green_shift; \ + b = blue_shift > 0 \ + ? b << blue_shift : b >> -blue_shift; \ + pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \ | ~(blue_mask | green_mask | red_mask); \ } +// optimized case - no d8 case, shift only once instead of twice, mask only once instead of twice, +// use direct values instead of variables, and use only one statement +// (*p >> 16), (*p >> 8 ) and (*p) are qRed(),qGreen() and qBlue() without masking +// shifts have to be passed including the shift operator (e.g. '>>3'), because of the direction +#define GET_PIXEL_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask) \ + int pixel = ((( *p >> 16 ) red_shift ) & red_mask ) \ + | ((( *p >> 8 ) green_shift ) & green_mask ) \ + | ((( *p ) blue_shift ) & blue_mask ); \ + ++p; + #define GET_PIXEL_DITHER_TC \ int r = qRed ( *p ); \ int g = qGreen( *p ); \ @@ -1210,91 +1412,177 @@ ? g << green_shift : g >> -green_shift; \ b = blue_shift > 0 \ ? b << blue_shift : b >> -blue_shift; \ - int pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask); + int pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask); - if ( dither_tc ) { - uint x; - switch ( bppc ) { - case 16: // 16 bit MSB - for ( x=0; x> 8); - *dst++ = pixel; - } +// again, optimized case +// can't be optimized that much :( +#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \ + rbits,gbits,bbits) \ + const int thres = D[x%16][y%16]; \ + int r = qRed ( *p ); \ + if ( r <= (255-(1<<(8-rbits))) && ((r< thres) \ + r += (1<<(8-rbits)); \ + int g = qGreen( *p ); \ + if ( g <= (255-(1<<(8-gbits))) && ((g< thres) \ + g += (1<<(8-gbits)); \ + int b = qBlue ( *p++ ); \ + if ( b <= (255-(1<<(8-bbits))) && ((b< thres) \ + b += (1<<(8-bbits)); \ + int pixel = (( r red_shift ) & red_mask ) \ + | (( g green_shift ) & green_mask ) \ + | (( b blue_shift ) & blue_mask ); + +#define CYCLE(body) \ + for ( uint y=0; ybytes_per_line*y; \ + QRgb* p = (QRgb *)src; \ + body \ + } + + if ( dither_tc ) { + switch ( mode ) { + case BPP16_8_3_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0xf800,0x7e0,0x1f,5,6,5) + *dst16++ = pixel; + } + ) break; - case 17: // 16 bit LSB - for ( x=0; x> 8; - } + case BPP16_7_2_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0x7c00,0x3e0,0x1f,5,5,5) + *dst16++ = pixel; + } + ) + break; + case BPP16_MSB: // 16 bit MSB + CYCLE( + for ( uint x=0; x> 8); + *dst++ = pixel; + } + ) + break; + case BPP16_LSB: // 16 bit LSB + CYCLE( + for ( uint x=0; x> 8; + } + ) break; default: qFatal("Logic error"); } - } else { - uint x; - switch ( bppc ) { - case 8: // 8 bit - for ( x=0; x> 8); - *dst++ = pixel; - } + case BPP16_8_3_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0xf800,0x7e0,0x1f) + *dst16++ = pixel; + } + ) break; - case 17: // 16 bit LSB - for ( x=0; x> 8; - } + case BPP16_7_2_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0x7c00,0x3e0,0x1f) + *dst16++ = pixel; + } + ) break; - case 24: // 24 bit MSB - for ( x=0; x> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } + case BPP16_MSB: // 16 bit MSB + CYCLE( + for ( uint x=0; x> 8); + *dst++ = pixel; + } + ) break; - case 25: // 24 bit LSB - for ( x=0; x> 8; - *dst++ = pixel >> 16; - } + case BPP16_LSB: // 16 bit LSB + CYCLE( + for ( uint x=0; x> 8; + } + ) break; - case 32: // 32 bit MSB - for ( x=0; x> 24; - *dst++ = pixel >> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } + case BPP24_MSB: // 24 bit MSB + CYCLE( + for ( uint x=0; x> 16; + *dst++ = pixel >> 8; + *dst++ = pixel; + } + ) break; - case 33: // 32 bit LSB - for ( x=0; x> 8; - *dst++ = pixel >> 16; - *dst++ = pixel >> 24; - } + case BPP24_LSB: // 24 bit LSB + CYCLE( + for ( uint x=0; x> 8; + *dst++ = pixel >> 16; + } + ) break; - default: - qFatal("Logic error 2"); - } - } - } - xi->data = (char *)newbits; + case BPP32_16_8_0: + CYCLE( + memcpy( dst, p, w * 4 ); + ) + break; + case BPP32_MSB: // 32 bit MSB + CYCLE( + for ( uint x=0; x> 24; + *dst++ = pixel >> 16; + *dst++ = pixel >> 8; + *dst++ = pixel; + } + ) + break; + case BPP32_LSB: // 32 bit LSB + CYCLE( + for ( uint x=0; x> 8; + *dst++ = pixel >> 16; + *dst++ = pixel >> 24; + } + ) + break; + default: + qFatal("Logic error 2"); + } + } + xi->data = (char *)newbits; } if ( d == 8 && !trucol ) { // 8 bit pixmap @@ -1313,6 +1601,7 @@ } newbits = (uchar *)malloc( nbytes ); // copy image into newbits + newbits_size = nbytes; Q_CHECK_PTR( newbits ); if ( !newbits ) // no memory return FALSE; @@ -1430,11 +1719,18 @@ } if ( !xi ) { // X image not created - xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo ); + if( xi != NULL ) + mitshm_ximage = true; + else +#endif + xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); if ( xi->bits_per_pixel == 16 ) { // convert 8 bpp ==> 16 bpp ushort *p2; int p2inc = xi->bytes_per_line/sizeof(ushort); ushort *newerbits = (ushort *)malloc( xi->bytes_per_line * h ); + newbits_size = xi->bytes_per_line * h; Q_CHECK_PTR( newerbits ); if ( !newerbits ) // no memory return FALSE; @@ -1452,7 +1748,15 @@ "(bpp=%d)", xi->bits_per_pixel ); #endif } - xi->data = (char *)newbits; +#ifdef QT_MITSHM_CONVERSIONS + if( newbits_size > 0 && mitshm_ximage ) { // need to copy to shared memory + memcpy( xi->data, newbits, newbits_size ); + free( newbits ); + newbits = (uchar*)xi->data; + } + else +#endif + xi->data = (char *)newbits; } if ( hd && (width() != (int)w || height() != (int)h || this->depth() != dd) ) { @@ -1485,19 +1789,24 @@ } - XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), - xi, 0, 0, 0, 0, w, h ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + XShmPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), + xi, 0, 0, 0, 0, w, h, False ); + else +#endif + XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), + xi, 0, 0, 0, 0, w, h ); - if ( data->optim != BestOptim ) { // throw away image - qSafeXDestroyImage( xi ); - data->ximage = 0; - } else { // keep ximage that we created - data->ximage = xi; - } data->w = w; data->h = h; data->d = dd; + XImage* axi = NULL; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_aximage = false; + XShmSegmentInfo ashminfo; +#endif if ( image.hasAlphaBuffer() ) { QBitmap m; m = image.createAlphaMask( conversion_flags ); @@ -1533,38 +1842,90 @@ data->alphapm->rendhd = (HANDLE) XftDrawCreateAlpha( x11Display(), data->alphapm->hd, 8 ); - XImage *axi = XCreateImage(x11Display(), (Visual *) x11Visual(), - 8, ZPixmap, 0, 0, w, h, 8, 0); +#ifdef QT_MITSHM_CONVERSIONS + axi = qt_XShmCreateImage( x11Display(), (Visual*)x11Visual(), + 8, ZPixmap, 0, 0, w, h, 8, 0, &ashminfo ); + if( axi != NULL ) + mitshm_aximage = true; + else +#endif + axi = XCreateImage(x11Display(), (Visual *) x11Visual(), + 8, ZPixmap, 0, 0, w, h, 8, 0); if (axi) { - // the data is deleted by qSafeXDestroyImage - axi->data = (char *) malloc(h * axi->bytes_per_line); - Q_CHECK_PTR( axi->data ); + if( axi->data==NULL ) { + // the data is deleted by qSafeXDestroyImage + axi->data = (char *) malloc(h * axi->bytes_per_line); + Q_CHECK_PTR( axi->data ); + } char *aptr = axi->data; if (image.depth() == 32) { const int *iptr = (const int *) image.bits(); - int max = w * h; - while (max--) - *aptr++ = *iptr++ >> 24; // squirt + if( axi->bytes_per_line == (int)w ) { + int max = w * h; + while (max--) + *aptr++ = *iptr++ >> 24; // squirt + } else { + for (uint i = 0; i < h; ++i ) { + for (uint j = 0; j < w; ++j ) + *aptr++ = *iptr++ >> 24; // squirt + aptr += ( axi->bytes_per_line - w ); + } + } } else if (image.depth() == 8) { const QRgb * const rgb = image.colorTable(); for (uint y = 0; y < h; ++y) { const uchar *iptr = image.scanLine(y); for (uint x = 0; x < w; ++x) *aptr++ = qAlpha(rgb[*iptr++]); + aptr += ( axi->bytes_per_line - w ); } } GC gc = XCreateGC(x11Display(), data->alphapm->hd, 0, 0); - XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + XShmPutImage( dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h, False ); + else +#endif + XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h); XFreeGC(x11Display(), gc); - qSafeXDestroyImage(axi); } } #endif // QT_NO_XFTFREETYPE } +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage || mitshm_aximage ) + XSync( x11Display(), False ); // wait until processed +#endif + + if ( data->optim != BestOptim ) { // throw away image +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); + data->ximage = 0; + } else { // keep ximage that we created +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) { // copy the XImage? + qt_XShmDestroyImage( xi, &shminfo ); + xi = 0; + } +#endif + data->ximage = xi; + } + if( axi ) { +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + qt_XShmDestroyImage( axi, &ashminfo ); + else +#endif + qSafeXDestroyImage(axi); + } return TRUE; } @@ -1721,7 +2082,7 @@ return pm; } -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) static bool try_once = TRUE; if (try_once) { try_once = FALSE; @@ -1754,7 +2115,7 @@ dbpl = ((w*bpp+31)/32)*4; dbytes = dbpl*h; -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) { dptr = (uchar *)xshmimg->data; uchar fillbyte = bpp == 8 ? white.pixel() : 0xff; @@ -1770,7 +2131,7 @@ memset( dptr, Qt::white.pixel( x11Screen() ), dbytes ); else memset( dptr, 0xff, dbytes ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) } #endif @@ -1801,7 +2162,7 @@ } else { xbpl = (w*bpp)/8; p_inc = dbpl - xbpl; -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) p_inc = xshmimg->bytes_per_line - xbpl; #endif @@ -1838,7 +2199,7 @@ QPixmap pm( w, h ); pm.data->uninit = FALSE; pm.x11SetScreen( x11Screen() ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) { XCopyArea( dpy, xshmpm, pm.handle(), gc, 0, 0, w, h, 0, 0 ); } else { @@ -1847,7 +2208,7 @@ ZPixmap, 0, (char *)dptr, w, h, 32, 0 ); XPutImage( dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h); qSafeXDestroyImage( xi ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) } #endif diff -Nru qt-x11-free-3.3.4.orig/src/kernel/qpngio.cpp qt-x11-free-3.3.4/src/kernel/qpngio.cpp --- qt-x11-free-3.3.4.orig/src/kernel/qpngio.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/kernel/qpngio.cpp 2005-03-19 20:02:45.000000000 +0100 @@ -110,10 +110,18 @@ static void setup_qt( QImage& image, png_structp png_ptr, png_infop info_ptr, float screen_gamma=0.0 ) { - if ( screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) ) { + if ( 0.0 == screen_gamma ) + // PNG docs say this is a good guess for a PC monitor + // in a dark room + screen_gamma = 2.2; + if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) ) { + // the file has a gAMA attribute double file_gamma; - png_get_gAMA(png_ptr, info_ptr, &file_gamma); - png_set_gamma( png_ptr, screen_gamma, file_gamma ); + if ( png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma( png_ptr, screen_gamma, file_gamma ); + } else { + // no file gamma, use a reasonable default + png_set_gamma( png_ptr, screen_gamma, 0.45455 ); } png_uint_32 width; diff -Nru qt-x11-free-3.3.4.orig/src/tools/qvaluelist.h qt-x11-free-3.3.4/src/tools/qvaluelist.h --- qt-x11-free-3.3.4.orig/src/tools/qvaluelist.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/tools/qvaluelist.h 2005-03-19 20:01:36.000000000 +0100 @@ -638,13 +638,11 @@ l.clear(); Q_UINT32 c; s >> c; - for( Q_UINT32 i = 0; i < c; ++i ) + for( Q_UINT32 i = 0; i < c && !s.atEnd(); ++i ) { T t; s >> t; l.append( t ); - if ( s.atEnd() ) - break; } return s; } diff -Nru qt-x11-free-3.3.4.orig/src/widgets/qpopupmenu.cpp qt-x11-free-3.3.4/src/widgets/qpopupmenu.cpp --- qt-x11-free-3.3.4.orig/src/widgets/qpopupmenu.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/widgets/qpopupmenu.cpp 2005-03-19 20:03:02.000000000 +0100 @@ -253,6 +253,8 @@ } scroll; QSize calcSize; QRegion mouseMoveBuffer; + uint hasmouse : 1; + QPoint ignoremousepos; }; static QPopupMenu* active_popup_menu = 0; @@ -272,6 +274,7 @@ d->scroll.scrollableSize = d->scroll.topScrollableIndex = 0; d->scroll.scrollable = QPopupMenuPrivate::Scroll::ScrollNone; d->scroll.scrolltimer = 0; + d->hasmouse = 0; isPopupMenu = TRUE; #ifndef QT_NO_ACCEL autoaccel = 0; @@ -1354,6 +1357,7 @@ popupActive = -1; if(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this)) d->mouseMoveBuffer = QRegion(); + d->ignoremousepos = QCursor::pos(); } /*! @@ -1701,6 +1705,11 @@ void QPopupMenu::mouseMoveEvent( QMouseEvent *e ) { + if( e->globalPos() == d->ignoremousepos ) { + return; + } + d->ignoremousepos = QPoint(); + motion++; if ( parentMenu && parentMenu->isPopupMenu ) { @@ -1741,6 +1750,11 @@ int item = itemAtPos( e->pos() ); if ( item == -1 ) { // no valid item + if( !d->hasmouse ) { + tryMenuBar( e ); + return; + } + d->hasmouse = 0; int lastActItem = actItem; actItem = -1; if ( lastActItem >= 0 ) @@ -1752,6 +1766,7 @@ } } else { // mouse on valid item // but did not register mouse press + d->hasmouse = 1; if ( (e->state() & Qt::MouseButtonMask) && !mouseBtDn ) mouseBtDn = TRUE; // so mouseReleaseEvent will pop down @@ -2160,6 +2175,7 @@ */ void QPopupMenu::leaveEvent( QEvent * ) { + d->hasmouse = 0; if ( testWFlags( WStyle_Tool ) && style().styleHint(QStyle::SH_PopupMenu_MouseTracking, this) ) { int lastActItem = actItem; actItem = -1; @@ -2530,7 +2546,7 @@ constPolish(); QPopupMenu* that = (QPopupMenu*) this; //We do not need a resize here, just the sizeHint.. - return that->updateSize(FALSE, FALSE).expandedTo( QApplication::globalStrut() ); + return that->updateSize(FALSE).expandedTo( QApplication::globalStrut() ); } diff -Nru qt-x11-free-3.3.4.orig/src/widgets/qprogressbar.cpp qt-x11-free-3.3.4/src/widgets/qprogressbar.cpp --- qt-x11-free-3.3.4.orig/src/widgets/qprogressbar.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/widgets/qprogressbar.cpp 2005-03-19 20:01:42.000000000 +0100 @@ -47,6 +47,14 @@ #endif #include +class QProgressBarPrivate +{ + public: + QProgressBarPrivate() : last_painted_progress( 0 ) { } + + int last_painted_progress; +}; + /*! \class QProgressBar qprogressbar.h \brief The QProgressBar widget provides a horizontal progress bar. @@ -99,7 +107,7 @@ center_indicator( TRUE ), auto_indicator( TRUE ), percentage_visible( TRUE ), - d( 0 ) + d( new QProgressBarPrivate ) { setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); initFrame(); @@ -130,12 +138,20 @@ center_indicator( TRUE ), auto_indicator( TRUE ), percentage_visible( TRUE ), - d( 0 ) + d( new QProgressBarPrivate ) { setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); initFrame(); } +/*! + Destroys the object and frees any allocated ressources. +*/ + +QProgressBar::~QProgressBar() +{ + delete d; +} /*! Reset the progress bar. The progress bar "rewinds" and shows no @@ -188,11 +204,16 @@ progress < 0 || ( ( progress > total_steps ) && total_steps ) ) return; + const bool needRepaint = isVisible() && requireRepaint( progress ); + progress_val = progress; setIndicator( progress_str, progress_val, total_steps ); - repaint( FALSE ); + if ( needRepaint ) { + repaint( FALSE ); + d->last_painted_progress = progress; + } #if defined(QT_ACCESSIBILITY_SUPPORT) QAccessible::updateAccessibility( this, 0, QAccessible::ValueChanged ); @@ -318,6 +339,31 @@ QFrame::styleChange( old ); } +/*! + This method returns whether changing the progress to the \a newValue + would require a repaint of the progress bar. This allows efficient + repainting. +*/ +bool QProgressBar::requireRepaint( int newProgress ) const +{ + if ( newProgress == progress_val || + newProgress == d->last_painted_progress ) { + return false; + } + + const int width = contentsRect().width(); + if ( width == 0 ) { + return false; + } + + float progressPerPixel = 1.0; + if ( total_steps > width ) { + progressPerPixel = float( total_steps ) / float( width ); + } + + const int delta = d->last_painted_progress - newProgress; + return QABS( delta ) >= progressPerPixel; +} /*! This method is called to generate the text displayed in the center diff -Nru qt-x11-free-3.3.4.orig/src/widgets/qprogressbar.h qt-x11-free-3.3.4/src/widgets/qprogressbar.h --- qt-x11-free-3.3.4.orig/src/widgets/qprogressbar.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/widgets/qprogressbar.h 2005-03-19 20:01:42.000000000 +0100 @@ -61,6 +61,7 @@ public: QProgressBar( QWidget* parent=0, const char* name=0, WFlags f=0 ); QProgressBar( int totalSteps, QWidget* parent=0, const char* name=0, WFlags f=0 ); + virtual ~QProgressBar(); int totalSteps() const; int progress() const; @@ -91,6 +92,7 @@ virtual bool setIndicator( QString & progress_str, int progress, int totalSteps ); void styleChange( QStyle& ); + bool requireRepaint( int newProgress ) const; private: int total_steps; diff -Nru qt-x11-free-3.3.4.orig/src/widgets/qscrollview.cpp qt-x11-free-3.3.4/src/widgets/qscrollview.cpp --- qt-x11-free-3.3.4.orig/src/widgets/qscrollview.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/widgets/qscrollview.cpp 2005-03-19 20:03:06.000000000 +0100 @@ -1180,7 +1180,7 @@ void QScrollView::wheelEvent( QWheelEvent *e ) { QWheelEvent ce( viewport()->mapFromGlobal( e->globalPos() ), - e->globalPos(), e->delta(), e->state()); + e->globalPos(), e->delta(), e->state(), e->orientation() ); viewportWheelEvent(&ce); if ( !ce.isAccepted() ) { if ( e->orientation() == Horizontal && horizontalScrollBar() ) @@ -1551,6 +1551,9 @@ case QEvent::LayoutHint: d->autoResizeHint(this); break; + case QEvent::WindowActivate: + case QEvent::WindowDeactivate: + return TRUE; default: break; } @@ -1863,7 +1866,7 @@ the event itself. */ QWheelEvent ce( viewportToContents(e->pos()), - e->globalPos(), e->delta(), e->state()); + e->globalPos(), e->delta(), e->state(), e->orientation()); contentsWheelEvent(&ce); if ( ce.isAccepted() ) e->accept(); diff -Nru qt-x11-free-3.3.4.orig/src/widgets/qtoolbar.cpp qt-x11-free-3.3.4/src/widgets/qtoolbar.cpp --- qt-x11-free-3.3.4.orig/src/widgets/qtoolbar.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/src/widgets/qtoolbar.cpp 2005-03-19 20:02:41.000000000 +0100 @@ -648,7 +648,7 @@ QString s = b->textLabel(); if ( s.isEmpty() ) s = b->text(); - if ( b->popup() && b->popupDelay() == 0 ) + if ( b->popup() && b->popupDelay() <= 0 ) id = d->extensionPopup->insertItem( b->iconSet(), s, b->popup() ); else id = d->extensionPopup->insertItem( b->iconSet(), s, b, SLOT( emulateClick() ) ) ; diff -Nru qt-x11-free-3.3.4.orig/tools/designer/designer/hierarchyview.cpp qt-x11-free-3.3.4/tools/designer/designer/hierarchyview.cpp --- qt-x11-free-3.3.4.orig/tools/designer/designer/hierarchyview.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/tools/designer/designer/hierarchyview.cpp 2005-03-19 20:01:25.000000000 +0100 @@ -605,6 +605,7 @@ formWindow->mainWindow()->setupTabWidgetHierarchyMenu( this, SLOT( addTabPage() ), SLOT( removeTabPage() ) ); + tabWidgetMenu->setItemEnabled(MainWindow::POPUP_REMOVE_PAGE_ID, ((QDesignerTabWidget*)w )->count() > 1); tabWidgetMenu->popup( p ); } } diff -Nru qt-x11-free-3.3.4.orig/tools/designer/designer/mainwindow.cpp qt-x11-free-3.3.4/tools/designer/designer/mainwindow.cpp --- qt-x11-free-3.3.4.orig/tools/designer/designer/mainwindow.cpp 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/tools/designer/designer/mainwindow.cpp 2005-03-19 20:01:25.000000000 +0100 @@ -2457,8 +2457,8 @@ { QPopupMenu *menu = new QPopupMenu( parent ); - menu->insertItem( tr( "Add Page" ), parent, addSlot ); - menu->insertItem( tr( "Delete Page" ), parent, removeSlot ); + menu->insertItem( tr( "Add Page" ), parent, addSlot, 0, POPUP_REMOVE_PAGE_ID+1 ); + menu->insertItem( tr( "Delete Page" ), parent, removeSlot, 0, POPUP_REMOVE_PAGE_ID ); menu->insertSeparator(); actionEditCut->addTo( menu ); actionEditCopy->addTo( menu ); diff -Nru qt-x11-free-3.3.4.orig/tools/designer/designer/mainwindow.h qt-x11-free-3.3.4/tools/designer/designer/mainwindow.h --- qt-x11-free-3.3.4.orig/tools/designer/designer/mainwindow.h 2005-03-19 19:57:36.000000000 +0100 +++ qt-x11-free-3.3.4/tools/designer/designer/mainwindow.h 2005-03-19 20:01:25.000000000 +0100 @@ -107,6 +107,7 @@ QPopupMenu *setupNormalHierarchyMenu( QWidget *parent ); QPopupMenu *setupTabWidgetHierarchyMenu( QWidget *parent, const char *addSlot, const char *removeSlot ); + static const int POPUP_REMOVE_PAGE_ID = 1; FormWindow *openFormWindow( const QString &fn, bool validFileName = TRUE, FormFile *ff = 0 ); bool isCustomWidgetUsed( MetaDataBase::CustomWidget *w );