[a5] drag your window with ALLEGRO_NOFRAME
Mark Oates

So, I'm just having some fun here trying to make a window dragable without a frame. Basically, I came up with this simple little technique that actually works, but it's buggy. I can't identify exactly what causes window to go crazy all over the screen and then fly off somewhere.

#SelectExpand
1 case ALLEGRO_EVENT_MOUSE_AXES: 2 if (mouse.dragging) 3 { 4 int x, y; 5 al_get_window_position(display, &x, &y); 6 al_set_window_position(display, x+al_event.mouse.dx, y+al_event.mouse.dy); 7 al_set_mouse_xy(al_event.mouse.x - al_event.mouse.dx, al_event.mouse.y - al_event.mouse.dy); 8 } 9 break; 10 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 11 mouse.start_drag(al_event.mouse.x, al_event.mouse.y); 12 break; 13 case ALLEGRO_EVENT_MOUSE_BUTTON_UP: 14 mouse.end_drag(); 15 break;

{"name":"601614","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/5\/0530a1dd5f460554bbb00a122c097603.png","w":1200,"h":900,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/5\/0530a1dd5f460554bbb00a122c097603"}601614

I'm surprised it works as well as it does, but it doesn't retain the position of the mouse inside the window (as well as sometimes just flipping out all together.) In the screenshot, the window has been dragged around a bit and you'll notice the red cross hair (drag start) and green cross hair (current mouse position) have different locations. The actual mouse cursor is not visible in the screenshot. This isn't a regular transformation - sometimes they'll still overlap when dragging, and sometimes they won't. Sometimes the window will flip out on a drag with slow mouse movement, other times it's with quick mouse movements.

I tried some other methods like setting al_set_mouse_xy() to the same mouse position when the drag began, but that would only aggravate the window flip outs more. Don't know why.

Here's a complete example (with a few extra lines of code that aren't used) if you wanna try it out. I've attached an MSVC build for Windows, too. Click-drag to drag the window. Press an any key to quit. You may have to hard-close it if it flies off the screen.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_font.h> 3#include <allegro5/allegro_ttf.h> 4#include <allegro5/allegro_primitives.h> 5#include <allegro5/allegro_image.h> 6#include <allegro5/allegro_color.h> 7#include <allegro5/allegro_audio.h> 8#include <allegro5/allegro_vorbis.h> 9#include <allegro5/allegro_native_dialog.h> 10#include <allegro5/allegro_opengl.h> 11 12 13#include <iostream> 14using std::cout; 15using std::endl; 16 17 18 19 20 21 22class Mouse 23{ 24public: 25 bool dragging; 26 int drag_start_x; 27 int drag_start_y; 28 int drag_offset_x; 29 int drag_offset_y; 30 31 int x; 32 int y; 33 34 Mouse():dragging(false), drag_start_x(0), drag_start_y(0) {} 35 36 void start_drag(int x, int y) 37 { 38 drag_start_x = x; 39 drag_start_y = y; 40 this->x = x; 41 this->y = y; 42 dragging = true; 43 cout << "starting drag" << endl; 44 } 45 46 void move_offset(int x, int y) 47 { 48 drag_offset_x = x; 49 drag_offset_y = y; 50 } 51 52 void end_drag() 53 { 54 dragging = false; 55 drag_start_x = 0; 56 drag_start_y = 0; 57 cout << "ending drag" << endl; 58 } 59}; 60 61 62 63 64 65 66 67int main(int argc, char *argv[]) 68{ 69 ALLEGRO_DISPLAY *display; 70 ALLEGRO_EVENT_QUEUE *queue; 71 72 al_init(); 73 74 al_set_new_display_flags(ALLEGRO_NOFRAME); 75 display = al_create_display(800, 600); 76 77 al_install_keyboard(); 78 al_install_mouse(); 79 al_install_joystick(); 80 81 /* setup event queue */ 82 83 queue = al_create_event_queue(); 84 85 ALLEGRO_EVENT_SOURCE *display_source = al_get_display_event_source(display); 86 al_register_event_source(queue, display_source); 87 88 ALLEGRO_EVENT_SOURCE *keyboard_event_source = al_get_keyboard_event_source(); 89 al_register_event_source(queue, keyboard_event_source); 90 91 ALLEGRO_EVENT_SOURCE *mouse_event_source = al_get_mouse_event_source(); 92 al_register_event_source(queue, mouse_event_source); 93 94 ALLEGRO_TIMER *timer = al_install_timer(ALLEGRO_BPS_TO_SECS(60)); 95 ALLEGRO_EVENT_SOURCE *timer_event_source = al_get_timer_event_source(timer); 96 al_register_event_source(queue, timer_event_source); 97 98 al_start_timer(timer); 99 100 bool game_over = false; 101 102 103 Mouse mouse; 104 105 while(!game_over) 106 { 107 ALLEGRO_EVENT al_event; 108 al_wait_for_event(queue, &al_event); 109 110 switch(al_event.type) 111 { 112 case ALLEGRO_EVENT_MOUSE_AXES: 113 if (mouse.dragging) 114 { 115 int x, y; 116 al_get_window_position(display, &x, &y); 117 al_set_window_position(display, x+al_event.mouse.dx, y+al_event.mouse.dy); 118 al_set_mouse_xy(al_event.mouse.x - al_event.mouse.dx, al_event.mouse.y - al_event.mouse.dy); 119 mouse.x = al_event.mouse.x - al_event.mouse.dx; 120 mouse.y = al_event.mouse.y - al_event.mouse.dy; 121 } 122 break; 123 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: 124 mouse.start_drag(al_event.mouse.x, al_event.mouse.y); 125 break; 126 case ALLEGRO_EVENT_MOUSE_BUTTON_UP: 127 mouse.end_drag(); 128 break; 129 case ALLEGRO_EVENT_KEY_DOWN: 130 game_over = true; 131 break; 132 case ALLEGRO_EVENT_TIMER: 133 al_clear_to_color(al_color_name("black")); 134 if (mouse.dragging) 135 { 136 al_draw_line(mouse.drag_start_x-10, mouse.drag_start_y, mouse.drag_start_x+10, mouse.drag_start_y, al_color_name("red"), 1.0); 137 al_draw_line(mouse.drag_start_x, mouse.drag_start_y-10, mouse.drag_start_x, mouse.drag_start_y+10, al_color_name("red"), 1.0); 138 al_draw_line(mouse.x-10, mouse.y, mouse.x+10, mouse.y, al_color_name("green"), 1.0); 139 al_draw_line(mouse.x, mouse.y-10, mouse.x, mouse.y+10, al_color_name("green"), 1.0); 140 } 141 al_flip_display(); 142 break; 143 default: 144 break; 145 } 146 } 147 148 149 150 return 0; 151}

Elias

Did you look at how ex_noframe does it? It seems to work quite well at least under Linux. [edit: yours doesn't seem to work at all in linux, on the other hand]

Mark Oates
Elias said:

Did you look at how ex_noframe does it?

oooahhhmmmmm... let's see...

al_get_mouse_cursor_position();

I was looking for a function that did that... I was so close. :D

[edit]Any chance we'll get support for a frameless window with an alpha channel? ;)

Elias

Any chance we'll get support for a frameless window with an alpha channel?

Yes, I want that. I think in the API we basically support it already, just nobody has sent a patch implementing it for any platform yet.

BAF

As far as the flip-outs go, my best guess would be when you move the window, more mouse movement events are fired, giving you wonky coordinates, causing it to go apeshit.

wiseguy

A frameless window with alpha would be nice, as I've set my base gui to allow for rectangular, triangular, and circular/elliptical windows but have only implemented the rectangular at the moment.

WG

Evert

Any chance we'll get support for a frameless window with an alpha channel? ;)

Only with the caveat that we may not be able to provide that functionality on all supported platforms (I don't think we can, someone correct me if I'm wrong).

Mark Oates

Probably work on Mac, Windows, and Linux, I imagine.

Elias

Should be easy for Linux/X11 (if supported by your window manager, which is probably only the case with a compositing window manager... but who is still using something else). We won't provide it for ios4 of course since even with the added multi-tasking it's one app at the screen at a time. I have no idea about Windows or OSX.

Evert

Probably work on Mac

That'll depend on the version of OS X that is running, I imagine.

Mark Oates
Elias said:

I have no idea about Windows or OSX

I'm sure it can be done in Windows. I remember almost 10 years ago I did figured it out, and that was in Visual Basic.

Thomas Fjellstrom

I'm sure it can be done in Windows. I remember almost 10 years ago I did figured it out, and that was in Visual Basic.

Back then it was more likely just a window mask rather than an alpha channel.

Mark Oates

True. I remember it being 1 or 0 transparency.

Thread #604376. Printed from Allegro.cc