Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Change adapter un runtime

This thread is locked; no one can reply to it. rss feed Print
Change adapter un runtime
Silver Sthan
Member #4,585
April 2004
avatar

Is it possible to change the adapter of the display during runtime ?

I have a dual screen and I want to switch between the two monitors, when I use :

// FullScreen
al_set_display_flag(_windowDisplay, ALLEGRO_WINDOWED, false);
al_set_display_flag(_windowDisplay, ALLEGRO_FULLSCREEN_WINDOW, true);

// Windowed
al_set_display_flag(_windowDisplay, ALLEGRO_FULLSCREEN_WINDOW, false);
al_set_display_flag(_windowDisplay, ALLEGRO_WINDOWED, true);

in "ALLEGRO_FULLSCREEN_WINDOW", the window stay in the first defined monitor, even if I force it with "set_new_display_adapter(another_monitor)".

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Silver Sthan
Member #4,585
April 2004
avatar

I want a behavior like a "normal" window :
{"name":"514852dualscreen.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/f\/8f77e1457a68859f9105b9374a9e6d7a.png","w":640,"h":360,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/8\/f\/8f77e1457a68859f9105b9374a9e6d7a"}514852dualscreen.png

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I don't think that Allegro detects which monitor it is over when going to fullscreen. The adapter you create the window on is the adapter it will be fullscreen on when you change the window. I can test this at home tonight, but I think that's how it works.

Allegro could probably be patched to fix this, but I don't know how much work it would be.

I don't think that (currently) you can 'go fullscreen' on any adapter but the original one it was created on.

Silver Sthan
Member #4,585
April 2004
avatar

There is an easy trick for that, just get the window position in the desktop,

If the window Position is in "Monitor[i] zone" then the current adapter MUST be monitor[i] and when I want to go in fullscreen, just need to set the proper adapter.

The problem is 'set_new_display_adapter()' of allegro 5.2.11 don't change/set/modify anything.

We can use it only once time (at initialization before create display) ! :(

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

That's why it's called al_set_NEW_display_adapter", because it only affects the displays created AFTER it.

Like I said, I don't know what the 'affinity' of a display is to an adapter. Right now it stays with the adapter it was created with.

There would have to be a new function or new settings in order to create the behavior you're expecting.

Like I said, I can look at this tonight, but not until I get home where I have a dual monitor setup.

Regardless, you can work around this by creating a NEW display on the NEW adapter.

Silver Sthan
Member #4,585
April 2004
avatar

I've made a little program to test my Window manager, for my 2D Game Engine.

I join a zip here, you can test it !

For this problem, maybe I need to make one display for each Monitor. I'll keep going to search a solution.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Your test program won't change back from a fullscreen window to a window. No matter what I press. I'm still not home, but I'm going to write a test program too.

Source + Static binary here (7-zip format)

I wrote up a simple test program. You can move and resize the window. You can press M to maximize and N to minimize (restore, actually) (al_set_display_flag(display , ALLEGRO_MAXIMIZED , false);).

You can press F to toggle ALLEGRO_FULLSCREEN_WINDOW, but it always goes fullscreen on the adapter it was created with. You can press O for OpenGL and D for Direct3D. Press a number key to switch adapters.

The program confirms what I thought before. The adapter you create the display on is the adapter that it will go fullscreen window on. There is some other behavior though, like toggling the ALLEGRO_MAXIMIZE flag. It maximizes on the monitor it is currently over. What with it being a window and all, it shouldn't be too hard to get the behavior you want.

Perhaps a few functions like :
al_get_display_adapter_position
al_set_display_adapter_affinity

or the like. Just ideas.

I'll take a look at allegro over the next few days and see what I can dig up.

Source code for my test program here :

#SelectExpand
1 2 3 4 5 6 7 8#include "allegro5/allegro.h" 9#include "allegro5/allegro_font.h" 10#include "allegro5/allegro_ttf.h" 11 12#include "allegro5/allegro_direct3d.h" 13 14 15#include <cstdio> 16 17 18 19class Display { 20protected: 21 ALLEGRO_DISPLAY* display; 22 ALLEGRO_EVENT_QUEUE* queue; 23 ALLEGRO_TIMER* timer; 24 ALLEGRO_FONT* verdana20; 25 int origw; 26 int origh; 27 int w; 28 int h; 29 int xpos; 30 int ypos; 31 int adapter; 32 bool opengl; 33 bool redraw; 34 bool quit; 35 bool fullscreen; 36 37 38 39public : 40 41 Display(); 42 43 int Init(); 44 45 bool Create(int width , int height , int adapter , bool use_opengl); 46 void Destroy(); 47 void RefreshInfo(); 48 void DisplayInfo(); 49 void Register(); 50 51 void ToggleFullscreen(); 52 53 bool SetAdapter(int nadapter); 54 bool UseOpenGL(); 55 bool UseDirect3D(); 56 57 void CheckInput(); 58 59 void Draw(); 60 61 void Run(); 62 63 bool Quit() {return quit;} 64}; 65 66 67 68int main(int argc , char** argv) { 69 70 71 72 Display d; 73 int ret = d.Init(); 74 if (ret != 0) {return ret;} 75 76 if (!d.Create(800 , 600 , 0 , true)) { 77 return 1; 78 } 79 80 d.Run(); 81 82 83 84 return 0; 85} 86 87 88 89Display::Display() : 90 display(0), 91 queue(0), 92 timer(0), 93 verdana20(0), 94 origw(0), 95 origh(0), 96 w(0), 97 h(0), 98 xpos(0), 99 ypos(0), 100 adapter(0), 101 opengl(true), 102 redraw(true), 103 quit(false), 104 fullscreen(false) 105{} 106 107 108 109int Display::Init() { 110 111 if (!al_init()) { 112 return -1; 113 } 114 if (!al_init_font_addon() || !al_init_ttf_addon()) { 115 return -2; 116 } 117 118 if (!al_install_keyboard()) { 119 return -3; 120 } 121 if (!al_install_mouse()) { 122 return -4; 123 } 124 125 queue = al_create_event_queue(); 126 if (!queue) { 127 return -6; 128 } 129 130 timer = al_create_timer(1.0/60.0); 131 if (!timer) { 132 return -7; 133 } 134 135 al_register_event_source(queue , al_get_keyboard_event_source()); 136 al_register_event_source(queue , al_get_timer_event_source(timer)); 137 al_register_event_source(queue , al_get_mouse_event_source()); 138 139 140 verdana20 = al_load_ttf_font("Verdana.ttf" , -20 , 0); 141 if (!verdana20) { 142 return -10; 143 } 144 145 return 0; 146} 147 148 149 150bool Display::Create(int width , int height , int new_adapter , bool use_opengl) { 151 Destroy(); 152 int ndflags = ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE | (use_opengl?ALLEGRO_OPENGL:ALLEGRO_DIRECT3D); 153 al_set_new_display_flags(ndflags); 154 al_set_new_display_adapter(new_adapter); 155 origw = width; 156 origh = height; 157 display = al_create_display(origw,origh); 158 if (display) { 159 opengl = use_opengl; 160 adapter = new_adapter; 161 Register(); 162 al_start_timer(timer); 163 } 164 redraw = true; 165 return display; 166} 167 168 169 170void Display::Destroy() { 171 if (display) { 172 al_stop_timer(timer); 173 al_destroy_display(display); 174 display = 0; 175 } 176} 177 178 179 180void Display::RefreshInfo() { 181 al_get_window_position(display , &xpos , &ypos); 182 w = al_get_display_width(display); 183 h = al_get_display_height(display); 184} 185 186 187 188void Display::DisplayInfo() { 189 RefreshInfo(); 190 al_draw_textf(verdana20 , al_map_rgb(255,255,255) , 10 , 10 , 0 , "Window position <%d , %d>" , xpos , ypos); 191 al_draw_textf(verdana20 , al_map_rgb(255,255,255) , 10 , 40 , 0 , "Window dimensions <%d , %d>" , w , h); 192 al_draw_textf(verdana20 , al_map_rgb(255,255,255) , 10 , 70 , 0 , "Adapter #%d" , adapter); 193 al_draw_textf(verdana20 , al_map_rgb(255,255,255) , 10 , 100 , 0 , "%d Available adapters" , al_get_num_video_adapters()); 194 al_draw_textf(verdana20 , al_map_rgb(255,255,255) , 10 , 130 , 0 , "Using %s" , opengl?"OpenGL":"Direct3D"); 195} 196 197 198 199void Display::Register() { 200 al_register_event_source(queue , al_get_display_event_source(display)); 201} 202 203 204 205void Display::ToggleFullscreen() { 206 fullscreen = !fullscreen; 207 al_set_display_flag(display , ALLEGRO_FULLSCREEN_WINDOW , fullscreen); 208} 209 210 211 212bool Display::SetAdapter(int nadapter) { 213 return Create(w , h , nadapter , opengl); 214} 215 216bool Display::UseOpenGL() { 217 return Create(w , h , adapter , true); 218} 219bool Display::UseDirect3D() { 220 return Create(w , h , adapter , false); 221} 222 223 224 225void Display::CheckInput() { 226 do { 227 ALLEGRO_EVENT ev; 228 al_wait_for_event(queue , &ev); 229 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE || (ev.type == ALLEGRO_EVENT_KEY_DOWN && ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)) { 230 quit = true; 231 break; 232 } 233 if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE) { 234 al_acknowledge_resize(display); 235 } 236 if (ev.type == ALLEGRO_EVENT_KEY_DOWN) { 237 if (ev.keyboard.keycode == ALLEGRO_KEY_F) { 238 ToggleFullscreen(); 239 } 240 if (ev.keyboard.keycode == ALLEGRO_KEY_M) { 241 al_set_display_flag(display , ALLEGRO_MAXIMIZED , true); 242 } 243 if (ev.keyboard.keycode == ALLEGRO_KEY_N) { 244 al_set_display_flag(display , ALLEGRO_MAXIMIZED , false); 245 } 246 if (ev.keyboard.keycode == ALLEGRO_KEY_O) { 247 if (!UseOpenGL()) { 248 printf("Failed to create an opengl context.\n"); 249 quit = true; 250 break; 251 } 252 } 253 if (ev.keyboard.keycode == ALLEGRO_KEY_D) { 254 if (!UseDirect3D()) { 255 printf("Failed to create a Direct3D context.\n"); 256 quit = true; 257 break; 258 } 259 } 260 for (int i = 0 ; i < al_get_num_video_adapters() ; ++i) { 261 if (ev.keyboard.keycode == ALLEGRO_KEY_1 + i) { 262 if (!SetAdapter(i)) { 263 printf("Failed to set adapter %d.\n" , i); 264 quit = true; 265 break; 266 } 267 } 268 } 269 } 270 if (ev.type == ALLEGRO_EVENT_TIMER) { 271 redraw = true; 272 } 273 274 } while (!al_is_event_queue_empty(queue)); 275} 276 277 278 279 280void Display::Draw() { 281 if (redraw) { 282 al_set_target_backbuffer(display); 283 al_clear_to_color(al_map_rgb(0,0,0)); 284 285 DisplayInfo(); 286 287 al_flip_display(); 288 289 redraw = false; 290 } 291} 292 293 294 295void Display::Run() { 296 while (!quit) { 297 Draw(); 298 CheckInput(); 299 } 300}

Silver Sthan
Member #4,585
April 2004
avatar

Yes, new functions could be great !!

I don't really like the idea to destroy/create display when you want to change adapter. not very elegant, but this is currently the only solution.

Maybe a new minor release of Allegro5 soon ! :)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

The majority of the work is done in the _al_win_set_display_flag function in allegro5/src/win/wwindow.c. The adapter there on line 1195 could easily be changed to affect which monitor the window goes fullscreen on.

I dont' know how hard it would be to get allegro to do the same thing on other platforms.

SilverTES
Member #16,572
October 2016

If it's work fine on Windows , I'll be already happy.

It's possible to recompile this module, and add an argument like :

...(..,...,int monitor)

#SelectExpand
1 if (onoff) { 2 int adapter = monitor; <<--------------------------------------- 3 al_get_monitor_info(adapter, &mi); 4 display->flags |= ALLEGRO_FULLSCREEN_WINDOW; 5 display->w = mi.x2 - mi.x1; 6 display->h = mi.y2 - mi.y1; 7 }

or something else.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

_al_set_win_display_flag is probably part of the display driver, and if you change it's arguments then the ABI compatibility would be broken. It might be possible to add an element to the WIN_DISPLAY_DRIVER struct to store a preferred adapter, but that might end up doing the same thing.

Go to: