PDA

View Full Version : Gtk+: Moving a window without decoration with the mouse



tommie-lie
August 27th, 2005, 05:30 PM
Hi,

Some of you may know Windows applications with windows that don't have any border, but you can "grab" them by clicking somehwere in the window. For instance, winamp behaves this way, along with other multimedia applications.

I want to create such a window with Gtk+ (Gtkmm, to be exact) under Linux. I can remove the window decoration without any problem Gtk::window->set_decorated(false) does the job. However, moving the window does not work as I would expect it. Is attached two event handlers, one for the mouse button click event and one for the pointer motion event. The handlers look like this:

bool MainWindow::on_button_press_event(GdkEventButton *button)
{
if (button->button == 1) {
// set initial mouse position (relative to the widget)
this->last_x = button->x;
this->last_y = button->y;
return true;
}
return false;
}

bool MainWindow::on_motion_notify_event(GdkEventMotion *motion)
{
if ((motion->state & Gdk::BUTTON1_MASK) == Gdk::BUTTON1_MASK) {
int cur_pos_x, cur_pos_y;

this->get_position(cur_pos_x, cur_pos_y);
this->move(cur_pos_x + (motion->x - this->last_x), cur_pos_y + (motion->y - this->last_y));

return false;
}
return false;
}On pointer movement, I simply check if the first mouse button is pressed and, if this is the case, calculate the pointer movement difference and move the window by this difference. I would expect this to work fine, as I did such things under Windows with the exact same approach, but it does not. If I move the mouse slowly, the window seems to follow, but the longer I drag the window, the more unstable becomes the movement of the window (kind of "loses track"). If I move the mouse fast, the window becomes unstable almost immediately. This "instability" in movement goes that far that the window seems to become crazy, gonig backwards and jumps to weird positions where my mouse never was.

I hope some of you find some fatal mistake of mine or something else that I overlooked.

Thanks in advance
Thomas

Tiede
August 27th, 2005, 05:35 PM
There is already such a feature in GTK+.. The Alt button. Hold it donwn, left click anywehre on the window and drag...

doclivingston
August 27th, 2005, 06:07 PM
Some additional information that may be helpful, in addition to what Tiede said:

* The modifier (which is Alt by default) can be changed in gconf - the key is /apps/metacity/general/mouse_button_modifier.
* Using that modifier with the left mouse button lets you move windows, the right mouse button gives you the "window menu" and the third (middle) button is resize.


The problem with your code is probably that window->x (and y) are relative to the window, which you are moving. Try using x_root and y_root instead, they are relative to the screen.

tommie-lie
August 29th, 2005, 01:50 PM
There is already such a feature in GTK+.. The Alt button. Hold it donwn, left click anywehre on the window and drag...This is not a Gtk+ feature, but a feature of metacity, and I am well aware of such things. I also know what you want me to tell with that: Don't change standard behaviour of windows or you will burn in hell! ;-)
But the project I am working on is an application that already exists for windows and that I want to make for Linux, and the Windows users are accustomed to this behaviour. Then, I want to use such a feature in another project that I plan to write if I find the time, without regard on "usability standards" of any kind.
And the third reason is curiosity ;-) It works like this on Windows (using the native API, not Gtk, though), it works somehow for Zinf, it should work as I do it, but for some reason it does not, and I want to know where my mistake is ;-)
Mentioning Zinf... I looked up their code and as far as I can see, they don't do something that I don't, except for not using Gtkmm.
However, if you can tell me how I can tell the WM to do the movement for me, just as it would do when the users presses Alt while dragging the window, that would be great.


Try using x_root and y_root instead, they are relative to the screen.Thanks, but using *_root does not work, either.

I logged the coordinates of the window as they should be and as they are after the call to move() to stdout like this:

this->get_position(wCur_x, wCur_y);
std::cout << wCur_x + delta_x << " - " << wCur_y + delta_y << "\n";

this->move(wCur_x + delta_x, wCur_y + delta_y);

this->get_position(wCur_x, wCur_y);
std::cout << wCur_x << " - " << wCur_y << "\n";

std::cout << "----------\n";(With delta_* being the amount of pixels I wnat to move the window)
And found this interesting behaviour:
4 - 54
3 - 53
----------
4 - 54
4 - 54
----------
5 - 55
4 - 54
----------
4 - 54
4 - 54
----------
5 - 55
4 - 54
----------
It seems as if the call to move() does not always work, as the calculated position before setting it sometimes differ from the actual position after the call to move().
Maybe this is part of the problem?