Rebuild autotool system
[construo.git] / x11_display.cxx
blob17bd0bb0ae4ac35419aadfcea8334848abe5de41
1 // $Id: x11_display.cxx,v 1.46 2003/07/28 22:46:48 grumbel Exp $
2 //
3 // Construo - A wire-frame construction game
4 // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <config.h>
21 #include <iostream>
22 #include <X11/Xutil.h>
23 #include <X11/cursorfont.h>
24 #include <X11/keysym.h>
26 #include "cursor_insert.xbm"
27 #include "cursor_insert_mask.xbm"
29 #include "cursor_select.xbm"
30 #include "cursor_select_mask.xbm"
32 #include "cursor_zoom.xbm"
33 #include "cursor_zoom_mask.xbm"
35 #include "cursor_scroll.xbm"
36 #include "cursor_scroll_mask.xbm"
38 #include "cursor_collider.xbm"
39 #include "cursor_collider_mask.xbm"
41 #include "construo_error.hxx"
42 #include "x11_display.hxx"
43 #include "settings.hxx"
44 #include "construo_main.hxx"
46 #include "controller.hxx"
47 #include "screen_manager.hxx"
49 extern ConstruoMain* construo_main;
50 Atom wm_delete_window;
52 X11Display::X11Display(int w, int h, bool fullscreen_)
53 : doublebuffer (settings.doublebuffer),
54 width(w), height(h), shift_pressed (false), fullscreen (fullscreen_)
56 #ifndef HAVE_LIBXXF86VM
57 fullscreen_ = false;
58 std::cout << "X11Display: libXxf86vm missing, fullscreen support not\n"
59 << " available, please recompile." << std::endl;
60 #endif
62 std::cout << "Opening X11 display" << std::endl;
63 display = XOpenDisplay(NULL);
65 if (!display)
66 throw ConstruoError("X11Display: Couldn't conncet to X server");
68 int screen = DefaultScreen(display);
69 XSetWindowAttributes attributes;
71 attributes.background_pixel = BlackPixel(display, screen);
72 attributes.border_pixel = WhitePixel(display, screen);
74 if (fullscreen)
75 attributes.override_redirect = True;
76 else
77 attributes.override_redirect = False;
79 attributes.event_mask =
80 KeyPressMask |
81 KeyReleaseMask |
82 ExposureMask |
83 PointerMotionMask |
84 ButtonPressMask |
85 ButtonReleaseMask |
86 StructureNotifyMask |
87 ExposureMask;
89 colormap = DefaultColormap (display, screen);
90 attributes.colormap = colormap;
91 window = XCreateWindow(display, RootWindow(display, screen),
92 0,0, // position
93 width, height, 0,
94 CopyFromParent, InputOutput, CopyFromParent,
95 CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWEventMask | CWColormap,
96 &attributes);
98 { // Communicate a bit with the window manager
99 char *title = construo_main->get_title();
101 XTextProperty text_property;
102 XStringListToTextProperty(&title, 1, &text_property);
103 XSizeHints size_hints;
104 size_hints.x = 0;
105 size_hints.y = 0;
106 size_hints.flags = PSize | PMinSize | PMaxSize;
108 size_hints.width = width;
109 size_hints.height = height;
111 size_hints.min_width = width;
112 size_hints.min_height = height;
113 size_hints.max_width = width;
114 size_hints.max_height = height;
116 XSetWMProperties(
117 display,
118 window,
119 &text_property,
120 &text_property,
123 &size_hints,
127 // Set WM_DELETE_WINDOW atom in WM_PROTOCOLS property (to get window_delete requests).
128 wm_delete_window = XInternAtom (display, "WM_DELETE_WINDOW", False);
129 XSetWMProtocols (display, window, &wm_delete_window, 1);
132 if (doublebuffer)
133 drawable = XCreatePixmap (display, window, width, height,
134 DefaultDepth(display, screen));
135 else
136 drawable = window;
138 XMapRaised(display, window);
140 XGCValues gcv;
141 gcv.foreground = 0xFFFFFF;
142 gcv.background = 0x000000;
144 if (settings.thick_lines)
145 gcv.line_width = 2;
146 else
147 gcv.line_width = 0;
149 gc = XCreateGC(display, window,
150 GCLineWidth | GCForeground | GCBackground,
151 &gcv);
153 if (fullscreen)
154 enter_fullscreen();
157 // Visual* visual = XDefaultVisual(display, DefaultScreen(display));
158 depth = DefaultDepth(display, DefaultScreen(display));
159 if (depth != 16 && depth != 32)
161 std::cout << "X11Display: Warring color depth '" << depth
162 << "' not supported, Construo will be slow!" << std::endl;
167 // Black&White
168 XColor cursor_fg = get_xcolor(Color(1.0f, 1.0f, 1.0f));
169 XColor cursor_bg = get_xcolor(Color(0, 0, 0));
171 cursor_scroll_pix = XCreateBitmapFromData (display, window, (char*)cursor_scroll_bits,
172 cursor_scroll_width, cursor_scroll_height);
173 cursor_scroll_mask = XCreateBitmapFromData (display, window, (char*)cursor_scroll_mask_bits,
174 cursor_scroll_width, cursor_scroll_height);
175 cursor_scroll = XCreatePixmapCursor(display, cursor_scroll_pix, cursor_scroll_mask, &cursor_bg, &cursor_fg,
176 cursor_scroll_x_hot, cursor_scroll_y_hot);
178 cursor_zoom_pix = XCreateBitmapFromData (display, window, (char*)cursor_zoom_bits,
179 cursor_zoom_width, cursor_zoom_height);
180 cursor_zoom_mask = XCreateBitmapFromData (display, window, (char*)cursor_zoom_mask_bits,
181 cursor_zoom_width, cursor_zoom_height);
182 cursor_zoom = XCreatePixmapCursor(display, cursor_zoom_pix, cursor_zoom_mask, &cursor_bg, &cursor_fg,
183 cursor_zoom_x_hot, cursor_zoom_y_hot);
185 cursor_insert_pix = XCreateBitmapFromData (display, window, (char*)cursor_insert_bits,
186 cursor_insert_width, cursor_insert_height);
187 cursor_insert_mask = XCreateBitmapFromData (display, window, (char*)cursor_insert_mask_bits,
188 cursor_insert_width, cursor_insert_height);
189 cursor_insert = XCreatePixmapCursor(display, cursor_insert_pix, cursor_insert_mask, &cursor_bg, &cursor_fg,
190 cursor_insert_x_hot, cursor_insert_y_hot);
192 cursor_select_pix = XCreateBitmapFromData (display, window, (char*)cursor_select_bits,
193 cursor_select_width, cursor_select_height);
194 cursor_select_mask = XCreateBitmapFromData (display, window, (char*)cursor_select_mask_bits,
195 cursor_select_width, cursor_select_height);
196 cursor_select = XCreatePixmapCursor(display, cursor_select_pix, cursor_select_mask, &cursor_bg, &cursor_fg,
197 cursor_select_x_hot, cursor_select_y_hot);
199 cursor_collider_pix = XCreateBitmapFromData (display, window, (char*)cursor_collider_bits,
200 cursor_collider_width, cursor_collider_height);
201 cursor_collider_mask = XCreateBitmapFromData (display, window, (char*)cursor_collider_mask_bits,
202 cursor_collider_width, cursor_collider_height);
203 cursor_collider = XCreatePixmapCursor(display, cursor_collider_pix, cursor_collider_mask, &cursor_bg, &cursor_fg,
204 cursor_collider_x_hot, cursor_collider_y_hot);
207 set_cursor(CURSOR_INSERT);
210 X11Display::~X11Display ()
212 std::cout << "Closing X11 display" << std::endl;
214 if (fullscreen)
216 std::cout << "X11Display: Restoring video mode" << std::endl;
217 leave_fullscreen ();
220 if (doublebuffer)
221 XFreePixmap (display, drawable);
223 XDestroyWindow (display, window);
224 XCloseDisplay(display);
227 void
228 X11Display::set_cursor_real(CursorType cursor)
230 switch(cursor)
232 case CURSOR_INSERT:
233 XDefineCursor (display, window, cursor_insert);
234 break;
235 case CURSOR_SCROLL:
236 XDefineCursor (display, window, cursor_scroll);
237 break;
238 case CURSOR_ZOOM:
239 XDefineCursor (display, window, cursor_zoom);
240 break;
241 case CURSOR_COLLIDER:
242 XDefineCursor (display, window, cursor_collider);
243 break;
244 case CURSOR_SELECT:
245 XDefineCursor (display, window, cursor_select);
246 break;
247 default:
248 std::cout << "X11Display: Unhandled cursor type: " << cursor << std::endl;
249 break;
253 void
254 X11Display::draw_lines (std::vector<Line>& lines, Color color, int wide)
256 std::vector<XSegment> segments (lines.size());
258 for (std::vector<Line>::size_type i = 0; i < lines.size(); ++i)
260 segments[i].x1 = static_cast<short>(lines[i].x1);
261 segments[i].y1 = static_cast<short>(lines[i].y1);
262 segments[i].x2 = static_cast<short>(lines[i].x2);
263 segments[i].y2 = static_cast<short>(lines[i].y2);
266 XDrawSegments(display, drawable, gc, &*segments.begin(), segments.size());
269 void
270 X11Display::draw_circles(std::vector<Circle>& circles, Color color)
272 std::vector<XArc> arcs (circles.size());
273 for (std::vector<Circle>::size_type i = 0; i < circles.size(); ++i)
275 arcs[i].x = static_cast<short>(circles[i].x - circles[i].r);
276 arcs[i].y = static_cast<short>(circles[i].y - circles[i].r);
277 arcs[i].width = static_cast<short>(2 * circles[i].r);
278 arcs[i].height = static_cast<short>(2 * circles[i].r);
279 arcs[i].angle1 = 0;
280 arcs[i].angle2 = 360 * 64;
283 XSetForeground(display, gc, get_color_value(color));
284 XFillArcs(display, drawable, gc,
285 &*arcs.begin(), arcs.size());
288 void
289 X11Display::draw_line(float x1, float y1, float x2, float y2, Color color, int wide)
291 XSetForeground(display, gc, get_color_value(color));
292 XDrawLine (display, drawable, gc, (int) x1, (int) y1, (int) x2, (int) y2);
295 void
296 X11Display::draw_fill_rect(float x1, float y1, float x2, float y2, Color color)
298 XSetForeground(display, gc, get_color_value(color));
299 XFillRectangle (display, drawable, gc,
300 int(x1), int(y1),
301 int(x2 - x1), int(y2 - y1));
304 void
305 X11Display::draw_fill_circle(float x, float y, float r, Color color)
307 // FIXME: doesn't work
308 XSetForeground(display, gc, get_color_value(color));
309 XFillArc(display, drawable, gc,
310 int(x-r), int(y-r),
311 int(r*2), int(r*2), 0,
312 360*64);
315 void
316 X11Display::draw_circle(float x, float y, float r, Color color)
318 // FIXME: doesn't work
319 XSetForeground(display, gc, get_color_value(color));
320 XDrawArc(display, drawable, gc, int(x-r), int(y-r), int(r*2.0f), int(r*2.0f), 0, 360*64);
323 void
324 X11Display::draw_rect(float x1, float y1, float x2, float y2, Color color)
326 XSetForeground(display, gc, get_color_value(color));
327 XDrawRectangle (display, drawable, gc,
328 int(x1), int(y1),
329 int(x2 - x1), int(y2 - y1));
332 void
333 X11Display::draw_string(float x, float y, const std::string& str, Color color)
335 XSetForeground(display, gc, get_color_value(color));
336 XDrawString (display, drawable, gc, int(x), int(y), str.c_str (), str.length ());
339 void
340 X11Display::draw_string_centered(float x, float y, const std::string& str, Color color)
342 XSetForeground(display, gc, get_color_value(color));
343 XDrawString (display, drawable, gc,
344 int(x) - ((str.length() * 6) / 2), int(y),
345 str.c_str (), str.length ());
349 X11Display::get_mouse_x ()
351 return mouse_x;
355 X11Display::get_mouse_y ()
357 return mouse_y;
360 bool
361 X11Display::get_key (int key)
363 return false;
366 void
367 X11Display::wait_for_events_blocking ()
369 do {
370 while (read_event () == false);
371 } while (XPending (display) > 0);
374 void
375 X11Display::wait_for_events ()
377 while (XPending (display) > 0)
379 read_event ();
383 bool
384 X11Display::read_event ()
386 XEvent event;
388 XNextEvent (display, &event);
390 switch (event.type)
392 case MotionNotify:
393 mouse_x = event.xmotion.x;
394 mouse_y = event.xmotion.y;
395 break;
397 case Expose:
398 if (event.xexpose.count == 0)
399 flip ();
400 break;
402 case NoExpose:
403 //std::cout << "NoExpose" << std::endl;
404 return false; // FIXME: Hack, no idea how to handle NoExpose
405 break;
407 case ButtonPress:
409 //std::cout << "ButtonID: " << event.xbutton.button << " " << event.xbutton.state << std::endl;
411 if (event.xbutton.button == 1)
412 send_button_press(BUTTON_PRIMARY);
413 else if (event.xbutton.button == 2)
414 send_button_press(BUTTON_TERTIARY);
415 else if (event.xbutton.button == 3)
416 send_button_press(BUTTON_SECONDARY);
417 else if (event.xbutton.button == 4)
418 send_button_press(BUTTON_ZOOM_IN);
419 else if (event.xbutton.button == 5)
420 send_button_press(BUTTON_ZOOM_OUT);
422 break;
424 case ButtonRelease:
426 //std::cout << "ButtonID: " << event.xbutton.button << " " << event.xbutton.state << std::endl;
427 if (event.xbutton.button == 1)
428 send_button_release(BUTTON_PRIMARY);
429 else if (event.xbutton.button == 2)
430 send_button_release(BUTTON_TERTIARY);
431 else if (event.xbutton.button == 3)
432 send_button_release(BUTTON_SECONDARY);
433 else if (event.xbutton.button == 4)
434 send_button_release(BUTTON_ZOOM_IN);
435 else if (event.xbutton.button == 5)
436 send_button_release(BUTTON_ZOOM_OUT);
438 break;
440 case KeyPress:
442 KeySym sym = XLookupKeysym(&event.xkey,0);
444 switch (sym)
446 case XK_F11:
447 // FIXME: Shortcut
448 //send_button_press(BUTTON_FULLSCREEN);
449 toggle_fullscreen();
450 break;
452 case XK_Left:
453 send_button_press(BUTTON_SCROLL_LEFT);
454 break;
456 case XK_Right:
457 send_button_press(BUTTON_SCROLL_RIGHT);
458 break;
460 case XK_Up:
461 send_button_press(BUTTON_SCROLL_UP);
462 break;
464 case XK_Down:
465 send_button_press(BUTTON_SCROLL_DOWN);
466 break;
468 case XK_a:
469 send_button_press(BUTTON_ACTIONCAM);
470 break;
472 case XK_s:
473 send_button_press(BUTTON_SCALE);
474 break;
476 case XK_j:
477 send_button_press(BUTTON_JOIN);
478 break;
480 case XK_o:
481 send_button_press(BUTTON_HIDEDOTS);
482 break;
484 case XK_v:
485 send_button_press(BUTTON_SETVELOCITY);
486 break;
488 case XK_Shift_L:
489 case XK_Shift_R:
490 shift_pressed = true;
491 break;
492 case XK_m:
493 send_button_press(BUTTON_MODE_CHANGE);
494 break;
495 case XK_f:
496 send_button_press(BUTTON_FIX);
497 break;
498 case XK_h:
499 send_button_press(BUTTON_FLIP);
500 break;
501 case XK_c:
502 send_button_press(BUTTON_CLEAR);
503 break;
504 case XK_Delete:
505 send_button_press(BUTTON_DELETE);
506 break;
507 case XK_Escape:
508 send_button_press(BUTTON_ESCAPE);
509 break;
510 case XK_u:
511 send_button_press(BUTTON_UNDO);
512 break;
513 case XK_r:
514 send_button_press(BUTTON_REDO);
515 break;
516 case XK_d:
517 send_button_press(BUTTON_DUPLICATE);
518 break;
519 case XK_space:
520 send_button_press(BUTTON_RUN);
521 break;
522 case XK_g:
523 send_button_press(BUTTON_GRID);
524 break;
525 case XK_Tab:
526 send_button_press(BUTTON_TOGGLESLOWMO);
527 break;
528 case 65451: // FIXME: insert symbol here
529 case XK_equal:
530 case XK_plus:
531 send_button_press(BUTTON_ZOOM_IN);
532 break;
533 case 65453: // FIXME: insert symbol here
534 case XK_minus:
535 send_button_press(BUTTON_ZOOM_OUT);
536 break;
537 case XK_0:
538 send_load_or_save(0);
539 break;
540 case XK_1:
541 send_load_or_save(1);
542 break;
543 case XK_2:
544 send_load_or_save(2);
545 break;
546 case XK_3:
547 send_load_or_save(3);
548 break;
549 case XK_4:
550 send_load_or_save(4);
551 break;
552 case XK_5:
553 send_load_or_save(5);
554 break;
555 case XK_6:
556 send_load_or_save(6);
557 break;
558 case XK_7:
559 send_load_or_save(7);
560 break;
561 case XK_8:
562 send_load_or_save(8);
563 break;
564 case XK_9:
565 send_load_or_save(9);
566 break;
568 default:
569 std::cout << "X11Display: unhandled keypress: " << sym << " " << XK_grave << std::endl;
570 break;
573 break;
575 case KeyRelease:
577 KeySym sym = XLookupKeysym(&event.xkey,0);
579 switch (sym)
581 case XK_Shift_L:
582 case XK_Shift_R:
583 shift_pressed = false;
584 break;
585 default:
586 //std::cout << "X11Display: unhandled keyrelease: " << sym << " " << XK_f << std::endl;
587 break;
590 break;
592 case ConfigureNotify:
593 //std::cout << "X11Display: " << event.xconfigure.width << "x" << event.xconfigure.height
594 //<< "+" << event.xconfigure.x << "+" << event.xconfigure.y << std::endl;
595 break;
597 case DestroyNotify:
598 std::cout << "Window got destroyed" << std::endl;
599 break;
601 case ClientMessage:
602 std::cout << "X11Display: got client message" << std::endl;
603 // Window close request
604 if ((int) event.xclient.data.l[0] == (int) wm_delete_window) {
605 std::cout << "Window is destroyed" << std::endl;
606 send_button_press(BUTTON_ESCAPE);
608 break;
610 default:
611 std::cout << "X11Display: Unhandled event: " << event.type << std::endl;
612 break;
614 return true;
617 void
618 X11Display::send_load_or_save(int n)
620 if (shift_pressed)
621 send_button_press(BUTTON_QUICKLOAD0 + n);
622 else
623 send_button_press(BUTTON_QUICKSAVE0 + n);
626 void
627 X11Display::send_button_press (int i)
629 Event ev;
630 ev.button.type = BUTTON_EVENT;
631 ev.button.id = i;
632 ev.button.pressed = true;
633 events.push(ev);
636 void
637 X11Display::send_button_release (int i)
639 Event ev;
640 ev.button.type = BUTTON_EVENT;
641 ev.button.id = i;
642 ev.button.pressed = false;
643 events.push(ev);
646 void
647 X11Display::clear ()
649 XSetForeground (display, gc, 0x000000);
650 XFillRectangle (display, drawable, gc, 0, 0, width, height);
653 void
654 X11Display::flip (int x1, int y1, int x2, int y2)
656 if (doublebuffer)
658 FlipRect flip_rect;
660 flip_rect.x1 = x1;
661 flip_rect.y1 = y1;
662 flip_rect.x2 = x2;
663 flip_rect.y2 = y2;
665 //flip_rects.push_back(flip_rect);
669 void
670 X11Display::real_flip ()
672 if (doublebuffer)
674 for (std::vector<FlipRect>::iterator i = flip_rects.begin ();
675 i != flip_rects.end ();
676 ++i)
678 XCopyArea (display, drawable, window, gc,
679 i->x1, i->y1, // source
680 i->x2 - i->x1, i->y2 - i->y1, // width/height
681 i->x1, i->y1 // destination
684 flip_rects.clear ();
688 void
689 X11Display::flip ()
691 if (doublebuffer)
693 // FIXME: Use another gc here
694 XCopyArea (display, drawable, window, gc,
695 0, 0, // source
696 width, height,
697 0, 0 // destination
699 //XFlush(display);
703 void
704 X11Display::save_mode()
706 #ifdef HAVE_LIBXXF86VM
707 memset(&orig_modeline, 0, sizeof(orig_modeline));
709 // Get the current display settings for later restore
710 XF86VidModeGetModeLine(display,
711 DefaultScreen(display),
712 &orig_dotclock,
713 &orig_modeline);
715 XF86VidModeGetViewPort(display,
716 DefaultScreen(display),
717 &orig_viewport_x,
718 &orig_viewport_y);
719 std::cout << "save_mode: "
720 << orig_dotclock << " "
721 << orig_viewport_x << ", " << orig_viewport_y << std::endl;
723 #endif /* HAVE_LIBXXF86VM */
726 void
727 X11Display::enter_fullscreen ()
729 #ifndef HAVE_LIBXXF86VM
730 std::cout << "X11Display: libXxf86vm missing, fullscreen support not\n"
731 << " available, please recompile." << std::endl;
732 #else
733 int event_base;
734 int error_base;
736 if (XF86VidModeQueryExtension(display, &event_base, &error_base) != True)
738 // No VidMode extension available, bailout
739 std::cout << "X11Display: VidMode extension not available, bailout." << std::endl;
740 return;
743 save_mode();
745 XF86VidModeModeInfo **modes;
746 int nmodes;
747 int mode_index = -1;
748 if (XF86VidModeGetAllModeLines(display,
749 DefaultScreen(display),
750 &nmodes,&modes)) // FIXME: memleak
752 std::cout << "VideoModes: (searching for " << width << "x" << height << ")" << std::endl;
753 for (int i = 0; i < nmodes; i++)
755 //std::cout << i << " " << mode.Width,mode.Height);
756 std::cout << " " << modes[i]->hdisplay
757 << "x" << modes[i]->vdisplay;
759 if (modes[i]->hdisplay == width && modes[i]->vdisplay == height)
761 std::cout << " <-";
762 mode_index = i;
764 std::cout << std::endl;
767 if (mode_index != -1) // Found a good mode
769 if (0)
770 { // FIXME: doesn't work to change override_redirect after window creation
771 std::cout << "Changing override_redirect" << std::endl;
772 // Switch border away and go to 0,0
773 XSetWindowAttributes attributes;
774 attributes.override_redirect = True;
775 XChangeWindowAttributes(display, window, CWOverrideRedirect, &attributes);
778 std::cout << "Switching to: "
779 << modes[mode_index]->hdisplay << "x" << modes[mode_index]->vdisplay
780 << std::endl;
782 if(XF86VidModeSwitchToMode(display,
783 DefaultScreen(display),
784 modes[mode_index]))
786 fullscreen = true;
788 { // Now that we have switched to the correct mode, we
789 // need to position the Viewport correct to the window
790 Window child_window;
791 int x, y;
792 // Get the windows absolute position (aka relative to
793 // the root window)
794 XTranslateCoordinates(display, window, DefaultRootWindow(display),
795 0, 0,
796 &x, &y, &child_window);
797 XF86VidModeSetViewPort(display, DefaultScreen(display), x, y);
800 // Hijack the focus (works only till the next focus change)
801 XSetInputFocus(display, window, RevertToParent, CurrentTime);
803 // Capture the pointer
804 if (XGrabPointer(display, window, true, 0, GrabModeAsync, GrabModeAsync,
805 window, None, CurrentTime) != GrabSuccess)
807 std::cout << "X11Display: Couldn't grab the pointer" << std::endl;
810 else
812 std::cout << "X11Display: Throuble switiching to fullscreen?!" << std::endl;
815 else // No mode found
817 std::cout << "Disabling override redirect" << std::endl;
818 // Fullscreen not possible, switch Window attributes back to windowed mode
819 XSetWindowAttributes attributes;
820 attributes.override_redirect = False;
821 XChangeWindowAttributes(display, window, CWOverrideRedirect, &attributes);
823 // Remap the Window to let the allow override to take effect
824 XUnmapWindow (display, window);
825 XMapRaised(display, window);
828 else
830 std::cout << "X11Display: Couldn't get available video modes" << std::endl;
832 #endif
835 void
836 X11Display::run()
838 while (!ScreenManager::instance ()->is_finished ())
840 ScreenManager::instance ()->run_once();
842 if (Controller::instance()->is_running())
844 system_context->sleep (0); // FIXME: limit CPU usage via brute force
845 wait_for_events();
847 else
849 wait_for_events_blocking();
854 void
855 X11Display::toggle_fullscreen()
857 //std::cout << "Fullscreen state: " << fullscreen << std::endl;
859 if (fullscreen)
860 leave_fullscreen();
861 else
862 enter_fullscreen();
865 void
866 X11Display::leave_fullscreen()
868 #ifdef HAVE_LIBXXF86VM
869 std::cout << "X11Display::restore_mode()" << std::endl;
871 XF86VidModeModeInfo modeinfo;
873 modeinfo.dotclock = orig_dotclock;
875 // Copy XF86VidModeModeLine struct into XF86VidModeModeInfo
876 modeinfo.hdisplay = orig_modeline.hdisplay;
877 modeinfo.hsyncstart = orig_modeline.hsyncstart;
878 modeinfo.hsyncend = orig_modeline.hsyncend;
879 modeinfo.htotal = orig_modeline.htotal;
880 modeinfo.hskew = orig_modeline.hskew;
881 modeinfo.vdisplay = orig_modeline.vdisplay;
882 modeinfo.vsyncstart = orig_modeline.vsyncstart;
883 modeinfo.vsyncend = orig_modeline.vsyncend;
884 modeinfo.vtotal = orig_modeline.vtotal;
885 modeinfo.flags = orig_modeline.flags;
886 modeinfo.privsize = orig_modeline.privsize;
887 modeinfo.c_private = orig_modeline.c_private;
889 XF86VidModeSwitchToMode(display, DefaultScreen(display),
890 &modeinfo);
891 XF86VidModeSetViewPort(display, DefaultScreen(display),
892 orig_viewport_x, orig_viewport_y);
894 XUngrabPointer(display, CurrentTime);
896 fullscreen = false;
897 #endif
900 void
901 X11Display::set_clip_rect (int x1, int y1, int x2, int y2)
903 XRectangle rect[1];
905 rect[0].x = x1;
906 rect[0].y = y1;
907 rect[0].width = x2 - x1 + 1;
908 rect[0].height = y2 - y1 + 1;
910 XSetClipRectangles (display, gc,
911 0, 0, // clip origin
912 rect, 1,
913 Unsorted);
916 unsigned int
917 X11Display::get_color_value(const Color& color)
919 switch (depth)
921 case 32:
922 // FIXME Cast evil?!
923 return static_cast<unsigned int>(color.get_as_rrggbb());
924 case 16:
925 return int(31 * color.b) | (int((63 * color.g)) << 5) | (int((31 * color.r)) << 11);
926 default:
927 { // This is extremly slow!
928 XColor x_color;
930 x_color.red = int(color.r * 65535);
931 x_color.green = int(color.g * 65535);
932 x_color.blue = int(color.b * 65535);
934 XAllocColor(display, colormap, &x_color);
936 return x_color.pixel;
938 break;
942 XColor
943 X11Display::get_xcolor(const Color& color)
945 XColor x_color;
947 x_color.red = int(color.r * 65535);
948 x_color.green = int(color.g * 65535);
949 x_color.blue = int(color.b * 65535);
951 XAllocColor(display, colormap, &x_color);
953 return x_color;
957 /* EOF */