Bug 145802

Summary: mail and new-window cursors confused if both appear on the same page
Product: [Applications] konqueror Reporter: Jonathan Marten <jjm>
Component: generalAssignee: Konqueror Developers <konq-bugs>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Compiled Sources   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: Test case for cursor shapes
Patch to fix

Description Jonathan Marten 2007-05-22 16:03:01 UTC
Version:            (using KDE KDE 3.5.7)
Installed from:    Compiled From Sources
Compiler:          gcc version 4.1.1 (Gentoo 4.1.1-r3) 
OS:                Linux

There is a new feature in KDE 3.5.7: show the "new window" icon next to the cursor if a link will open in a new window (commit 653022).  This is a nice feature, but if there is a mail link and a new-window link on the same page, their cursors are not kept distinct - the first link hovered over shows its correct cursor (mail or new-window as appropriate), but the same cursor is then shown for any other links.

Test case is attached.  Load the page and hover over the second link, the new-window cursor is shown.  Now hover over the third link, it also shows the new-window cursor.

Load the page in a new window and hover over the third link, the mail-cursor is shown.  Hover over the second link, the mail-cursor is shown there too.

Suspect that the cause of the problem is:

kdelibs/khtml/khtmlview.cpp  KHTMLView::viewportMouseMoveEvent

    if ( ( mailtoCursor || newWindowCursor ) && isVisible() && hasFocus() ) {
#ifdef Q_WS_X11
        if( !d->cursor_icon_widget ) {
            QPixmap icon_pixmap = KGlobal::iconLoader()->loadIcon( mailtoCursor ? "mail_generic" : "window_new", KIcon::Small, 0, KIcon::DefaultState, 0, true );
            d->cursor_icon_widget = new QWidget( NULL, NULL, WX11BypassWM );

The first time a custom cursor is needed, d->cursor_icon_widget is 0 and the cursor is created as intended.  From then on, d->cursor_icon_widget is non-0 so the cursor shape is never changed.

This same problem also happens with trunk.
Comment 1 Jonathan Marten 2007-05-22 16:03:54 UTC
Created attachment 20667 [details]
Test case for cursor shapes
Comment 2 Jonathan Marten 2007-05-22 16:13:29 UTC
Created attachment 20669 [details]
Patch to fix

Possible fix: check the serial number of the loaded icon against the current
cursor, if one already exists.	If they are not the same, delete the cursor
widget and recreate it with the correct icon.
Comment 3 Jonathan Marten 2007-06-03 18:11:47 UTC
SVN commit 671045 by marten:

Fix confused cursor shapes if mail and new-window links appear on the same page.

Use an enum instead of two bool flags, to allow for possible addition of other
cursor shapes in the future
(see, for example, https://addons.mozilla.org/en-US/firefox/addon/2771)

CCBUG:145802


 M  +26 -8     khtmlview.cpp  
 M  +2 -0      khtmlview.h  


--- trunk/KDE/kdelibs/khtml/khtmlview.cpp #671044:671045
@@ -1217,8 +1217,7 @@
     khtml::RenderObject* r = target ? target->renderer() : 0;
     khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0;
     QCursor c;
-    bool mailtoCursor = false;
-    bool newWindowCursor = false;
+    LinkCursor linkCursor = LINK_NORMAL;
     switch ( style ? style->cursor() : CURSOR_AUTO) {
     case CURSOR_AUTO:
         if ( r && r->isText() )
@@ -1226,9 +1225,10 @@
         if ( mev.url.length() && m_part->settings()->changeCursor() ) {
             c = m_part->urlCursor();
 	    if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
-                mailtoCursor = true;
+              linkCursor = LINK_MAILTO;
             else
-               newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
+              if ( targetOpensNewWindow( m_part, mev.target.string() ) )
+	        linkCursor = LINK_NEWWINDOW;
         }
 
         if (r && r->isFrameSet() && !static_cast<RenderFrameSet*>(r)->noResize())
@@ -1241,9 +1241,10 @@
     case CURSOR_POINTER:
         c = m_part->urlCursor();
 	if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0)
-            mailtoCursor = true;
+          linkCursor = LINK_MAILTO;
         else
-            newWindowCursor = targetOpensNewWindow( m_part, mev.target.string() );
+          if ( targetOpensNewWindow( m_part, mev.target.string() ) )
+	    linkCursor = LINK_NEWWINDOW;
         break;
     case CURSOR_PROGRESS:
         c = QCursor(Qt::BusyCursor); // working_cursor
@@ -1290,10 +1291,27 @@
         }
     }
 
-    if ( (mailtoCursor || newWindowCursor) && isVisible() && hasFocus() ) {
+    if ( linkCursor!=LINK_NORMAL && isVisible() && hasFocus() ) {
 #ifdef Q_WS_X11
+	QString cursorIcon;
+	switch (linkCursor)
+	{
+          case LINK_MAILTO:     cursorIcon = "mail";       break;
+          case LINK_NEWWINDOW:  cursorIcon = "window-new"; break;
+          default:              cursorIcon = "error";      break;
+	}
+        QPixmap icon_pixmap = KHTMLFactory::iconLoader()->loadIcon( cursorIcon, K3Icon::Small, 0, K3Icon::DefaultState, 0, true );
+	if (d->cursor_icon_widget)
+	{
+	    const QPixmap *pm = d->cursor_icon_widget->backgroundPixmap();
+	    if (!pm || pm->serialNumber()!=icon_pixmap.serialNumber())
+	    {
+		delete d->cursor_icon_widget;
+		d->cursor_icon_widget = NULL;
+	    }
+	}
+
         if( !d->cursor_icon_widget ) {
-            QPixmap icon_pixmap = KHTMLFactory::iconLoader()->loadIcon( mailtoCursor ? "mail" : "window-new", K3Icon::Small, 0, K3Icon::DefaultState, 0, true );
 #ifdef Q_WS_X11
             d->cursor_icon_widget = new QWidget( 0, Qt::WX11BypassWM );
             XSetWindowAttributes attr;
--- trunk/KDE/kdelibs/khtml/khtmlview.h #671044:671045
@@ -715,6 +715,8 @@
     // ------------------------------------- member variables ------------------------------------
  private:
 
+    enum LinkCursor { LINK_NORMAL, LINK_MAILTO, LINK_NEWWINDOW };
+
     void setWidgetVisible(::khtml::RenderWidget*, bool visible);
 
 
Comment 4 Jonathan Marten 2007-06-04 13:03:36 UTC
Committed to 3.5 branch as 671262.