tags:

views:

178

answers:

2

Hello.

A long time ago I tried to find method how to stick QDialog window to screen borders for my small projects like Skype windows do it, but I failed. May be I was looking this code not in the right place, so now I'm looking the solution here, on stack! :)

So, does any one have a deal with some kind of such code, links, samples?

In my opinion, we have to reimplement QDialog moveEvent function, like below, but that code does not working:

void    CDialog::moveEvent(QMoveEvent * event) {

    QRect wndRect;
    int leftTaskbar = 0, rightTaskbar = 0, topTaskbar = 0, bottomTaskbar = 0;
//  int top = 0, left = 0, right = 0, bottom = 0;

    wndRect = this->frameGeometry();

    // Screen resolution
    int screenWidth =   QApplication::desktop()->width();
    int screenHeight =  QApplication::desktop()->height();

    int wndWidth = wndRect.right() - wndRect.left();
    int wndHeight = wndRect.bottom() - wndRect.top();

    int posX = event->pos().x();
    int posY = event->pos().y();

    // Snap to screen border
    // Left border
    if (posX >= -m_nXOffset + leftTaskbar &&
        posX <= leftTaskbar + m_nXOffset) {
        //left = leftTaskbar;
        this->move(leftTaskbar, posY);
        return;
    }

    // Top border
    if (posY >= -m_nYOffset &&
        posY <= topTaskbar + m_nYOffset) {
        //top = topTaskbar;
        this->move(posX, topTaskbar);
        return;
    }

    // Right border
    if (posX + wndWidth <= screenWidth - rightTaskbar + m_nXOffset &&
        posX + wndWidth >= screenWidth - rightTaskbar - m_nXOffset) {
        //right = screenWidth - rightTaskbar - wndWidth;
        this->move(screenWidth - rightTaskbar - wndWidth, posY);
        return;
    }

    // Bottom border
    if (posY + wndHeight <= screenHeight - bottomTaskbar + m_nYOffset &&
        posY + wndHeight >= screenHeight - bottomTaskbar - m_nYOffset) {
        //bottom = screenHeight - bottomTaskbar - wndHeight;
        this->move(posX, screenHeight - bottomTaskbar - wndHeight);
        return;
    }

    QDialog::moveEvent(event);
}

Thanks.

+1  A: 

As you thought you can achieve this in the moveEvent function. I guess the following code do the trick but since I have nothing to test here I will write some pseudo code:

First get the available screen area:

const QRect screen = QApplication::availableGeometry(this);
// This get the screen rect where you can drag a dialog

Then get the position of your dialog relative to the desktop (if your dialog is a child of an other widget, you need to transform coordinates from widget relative to desktop relative):

const QRect dialog = geometry();
// Do here transformation

Now test if dialog is near screen border

if( abs(dialog.left()-screen.left() < OFFSET )
    move(screen.left(), dialog.top();
else if( abs(dialog.top()-screen.top() < OFFSET )
    move(dialog.left(), screen.top() )
// etc. for the 2 other cases

Let me know if it works

Patrice Bernassola
@Patrice Bernassola: Thanks for reply. I think, that I have to update my sample, because it's more ready for testing/editing... As I'm a long time linux user, in KDE there is a global solutions for that case: all windows/dialogs can be sticked to windows borders, so may be it's good idea to look in KDE sources...
mosg
+1  A: 

In the pos property description from the QWidget documentation, there is the following warning about moving a window inside the move event handling method.

Warning: Calling move() or setGeometry() inside moveEvent() can lead to infinite recursion.

That said, there is no proper way to stick the dialog window inside the screen border.

Note : The behavior you observed in KDE comes from the Window Manager. Actually, the Window Manager is the one that arranges the application windows (like dialog boxes) to show them on the screen. The KDE Window Manager has an option to make all application windows (called client) stick to the border.

Lohrun
@Lohrun Thank for reply. I'll try your solution tomorrow, but at original post there was a code...
mosg
Code that doesn't work actually... I was able to restore the position of the widget so that it could stick with screen border. But in some corner cases, the event processing started to loop indefinitely. I can restore the code but you should now that it won't work in some case.
Lohrun
@Lohrun Yes, I checked it to, and it's only works fine with the top border, and not with the others. It's sad, but it means the we are on the right way to solve this issue...
mosg