15 #include "pandabase.h"
19 #include "tinyXGraphicsWindow.h"
20 #include "tinyGraphicsStateGuardian.h"
21 #include "tinyXGraphicsPipe.h"
22 #include "config_tinydisplay.h"
24 #include "graphicsPipe.h"
25 #include "keyboardButton.h"
26 #include "mouseButton.h"
27 #include "clockObject.h"
28 #include "pStatTimer.h"
29 #include "textEncoder.h"
30 #include "throw_event.h"
31 #include "lightReMutexHolder.h"
32 #include "nativeWindowHandle.h"
53 _reduced_frame_buffer = NULL;
54 _full_frame_buffer = NULL;
56 update_pixel_factor();
65 ~TinyXGraphicsWindow() {
66 if (_gc != NULL && _display != NULL) {
67 XFreeGC(_display, _gc);
69 if (_ximage != NULL) {
70 PANDA_FREE_ARRAY(_ximage->data);
72 XDestroyImage(_ximage);
85 bool TinyXGraphicsWindow::
86 begin_frame(FrameMode mode,
Thread *current_thread) {
87 PStatTimer timer(_make_current_pcollector, current_thread);
89 if (_xwindow == (X11_Window)NULL) {
93 begin_frame_spam(mode);
97 if (_awaiting_configure) {
104 DCAST_INTO_R(tinygsg, _gsg,
false);
106 if (_reduced_frame_buffer != (
ZBuffer *)NULL) {
107 tinygsg->_current_frame_buffer = _reduced_frame_buffer;
109 tinygsg->_current_frame_buffer = _full_frame_buffer;
113 _gsg->set_current_properties(&get_fb_properties());
114 return _gsg->begin_frame(current_thread);
124 void TinyXGraphicsWindow::
125 end_frame(FrameMode mode,
Thread *current_thread) {
126 end_frame_spam(mode);
129 if (mode == FM_render) {
134 _gsg->end_frame(current_thread);
136 if (mode == FM_render) {
138 clear_cube_map_selection();
152 void TinyXGraphicsWindow::
154 if (_xwindow == (X11_Window)NULL || !_flip_ready) {
159 if (_reduced_frame_buffer != (
ZBuffer *)NULL) {
161 ZB_zoomFrameBuffer(_full_frame_buffer, 0, 0,
162 _full_frame_buffer->xsize, _full_frame_buffer->ysize,
163 _reduced_frame_buffer, 0, 0,
164 _reduced_frame_buffer->xsize, _reduced_frame_buffer->ysize);
172 ZB_copyFrameBufferNoAlpha(_full_frame_buffer, _ximage->data, _pitch);
174 XPutImage(_display, _xwindow, _gc, _ximage, 0, 0, 0, 0,
175 _full_frame_buffer->xsize, _full_frame_buffer->ysize);
194 bool TinyXGraphicsWindow::
195 supports_pixel_zoom()
const {
209 void TinyXGraphicsWindow::
215 if (_xwindow == (X11_Window)0) {
222 XKeyEvent keyrelease_event;
223 bool got_keyrelease_event =
false;
225 while (XCheckIfEvent(_display, &event, check_event, (
char *)
this)) {
226 if (XFilterEvent(&event, None)) {
230 if (got_keyrelease_event) {
236 got_keyrelease_event =
false;
238 if (event.type == KeyPress &&
239 event.xkey.keycode == keyrelease_event.keycode &&
240 (event.xkey.time - keyrelease_event.time <= 1)) {
243 handle_keystroke(event.xkey);
247 handle_keypress(event.xkey);
253 handle_keyrelease(keyrelease_event);
260 switch (event.type) {
264 case ConfigureNotify:
265 _awaiting_configure =
false;
266 if (_properties.get_fixed_size()) {
274 if (event.xconfigure.width != current_props.
get_x_size() ||
275 event.xconfigure.height != current_props.
get_y_size()) {
276 XWindowChanges changes;
279 int value_mask = (CWWidth | CWHeight);
280 XConfigureWindow(_display, _xwindow, value_mask, &changes);
285 properties.
set_size(event.xconfigure.width, event.xconfigure.height);
286 system_changed_properties(properties);
287 ZB_resize(_full_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
288 _pitch = (_full_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
289 create_reduced_frame_buffer();
296 button = get_mouse_button(event.xbutton);
297 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
298 _input_devices[0].button_down(button);
302 button = get_mouse_button(event.xbutton);
303 _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
304 _input_devices[0].button_up(button);
308 _input_devices[0].set_pointer_in_window(event.xmotion.x, event.xmotion.y);
312 handle_keystroke(event.xkey);
313 handle_keypress(event.xkey);
320 keyrelease_event =
event.xkey;
321 got_keyrelease_event =
true;
325 _input_devices[0].set_pointer_in_window(event.xcrossing.x, event.xcrossing.y);
329 _input_devices[0].set_pointer_out_of_window();
334 system_changed_properties(properties);
338 _input_devices[0].focus_lost();
340 system_changed_properties(properties);
345 system_changed_properties(properties);
350 system_changed_properties(properties);
353 XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime);
357 if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
360 string close_request_event = get_close_request_event();
361 if (!close_request_event.empty()) {
364 throw_event(close_request_event);
373 system_changed_properties(properties);
382 tinydisplay_cat.info()
383 <<
"DestroyNotify\n";
387 tinydisplay_cat.error()
388 <<
"unhandled X event type " <<
event.type <<
"\n";
392 if (got_keyrelease_event) {
395 handle_keyrelease(keyrelease_event);
405 void TinyXGraphicsWindow::
409 DCAST_INTO_V(tinygsg, _gsg);
410 tinygsg->_current_frame_buffer = NULL;
414 x11GraphicsWindow::close_window();
424 bool TinyXGraphicsWindow::
426 TinyXGraphicsPipe *tinyx_pipe;
427 DCAST_INTO_R(tinyx_pipe, _pipe,
false);
436 DCAST_INTO_R(tinygsg, _gsg,
false);
439 XVisualInfo vinfo_template;
440 vinfo_template.screen = _screen;
441 vinfo_template.depth = 32;
442 vinfo_template.c_class = TrueColor;
446 VisualScreenMask | VisualDepthMask | VisualClassMask,
447 VisualScreenMask | VisualClassMask,
448 VisualScreenMask | VisualDepthMask,
455 XVisualInfo *vinfo_array;
456 while (try_masks[i] != 0 && num_vinfos == 0) {
458 XGetVisualInfo(_display, try_masks[i], &vinfo_template, &num_vinfos);
462 if (num_vinfos == 0) {
464 tinydisplay_cat.error()
465 <<
"No suitable X Visual available; cannot open window.\n";
468 _visual_info = &vinfo_array[0];
470 _visual = _visual_info->visual;
471 _depth = _visual_info->depth;
472 _bytes_per_pixel = _depth / 8;
473 if (_bytes_per_pixel == 3) {
475 _bytes_per_pixel = 4;
477 tinydisplay_cat.info()
478 <<
"Got X Visual with depth " << _depth <<
" (bpp " << _bytes_per_pixel <<
") and class ";
479 switch (_visual_info->c_class) {
481 tinydisplay_cat.info(
false) <<
"TrueColor\n";
485 tinydisplay_cat.info(
false) <<
"DirectColor\n";
489 tinydisplay_cat.info(
false) <<
"StaticColor\n";
493 tinydisplay_cat.info(
false) <<
"StaticGray\n";
497 tinydisplay_cat.info(
false) <<
"GrayScale\n";
501 tinydisplay_cat.info(
false) <<
"PseudoColor\n";
505 setup_colormap(_visual_info);
507 if (!x11GraphicsWindow::open_window()) {
511 _gc = XCreateGC(_display, _xwindow, 0, NULL);
513 create_full_frame_buffer();
514 if (_full_frame_buffer == NULL) {
515 tinydisplay_cat.error()
516 <<
"Could not create frame buffer.\n";
519 create_reduced_frame_buffer();
521 nassertr(_ximage != NULL,
false);
523 tinygsg->_current_frame_buffer = _full_frame_buffer;
531 XMapWindow(_display, _xwindow);
533 if (_properties.get_raw_mice()) {
536 if (tinydisplay_cat.is_debug()) {
537 tinydisplay_cat.debug()
538 <<
"Raw mice not requested.\n";
543 _window_handle = NativeWindowHandle::make_x11(_xwindow);
547 _parent_window_handle->attach_child(_window_handle);
558 void TinyXGraphicsWindow::
559 pixel_factor_changed() {
560 x11GraphicsWindow::pixel_factor_changed();
561 create_reduced_frame_buffer();
570 void TinyXGraphicsWindow::
571 create_full_frame_buffer() {
572 if (_full_frame_buffer != NULL) {
573 ZB_close(_full_frame_buffer);
574 _full_frame_buffer = NULL;
578 switch (_bytes_per_pixel) {
580 tinydisplay_cat.error()
581 <<
"Palette images are currently not supported.\n";
585 mode = ZB_MODE_5R6G5B;
595 _full_frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), mode, 0, 0, 0, 0);
596 _pitch = (_full_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
605 void TinyXGraphicsWindow::
606 create_reduced_frame_buffer() {
607 if (!_full_frame_buffer) {
611 if (_reduced_frame_buffer != NULL) {
612 ZB_close(_reduced_frame_buffer);
613 _reduced_frame_buffer = NULL;
616 int x_size = get_fb_x_size();
617 int y_size = get_fb_y_size();
619 if (x_size == _full_frame_buffer->xsize) {
625 _reduced_frame_buffer = ZB_open(x_size, y_size, _full_frame_buffer->mode, 0, 0, 0, 0);
636 void TinyXGraphicsWindow::
638 if (_ximage != NULL) {
639 PANDA_FREE_ARRAY(_ximage->data);
640 _ximage->data = NULL;
641 XDestroyImage(_ximage);
645 int image_size = _full_frame_buffer->ysize * _pitch;
646 char *data = (
char *)PANDA_MALLOC_ARRAY(image_size);
648 _ximage = XCreateImage(_display, _visual, _depth, ZPixmap, 0, data,
649 _full_frame_buffer->xsize, _full_frame_buffer->ysize,
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
This object represents a window on the desktop, not necessarily a Panda window.
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool reset_if_new()
Calls reset() to initialize the GSG, but only if it hasn't been called yet.
int get_y_size() const
Returns size in pixels in the y dimension of the useful part of the window, not including decorations...
bool is_valid() const
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
void set_size(const LVector2i &size)
Specifies the requested size of the window, in pixels.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An object to create GraphicsOutputs that share a particular 3-D API.
This is a base class for the various different classes that represent the result of a frame of render...
Similar to MutexHolder, but for a light reentrant mutex.
void set_foreground(bool foreground)
Specifies whether the window should be opened in the foreground (true), or left in the background (fa...
int get_x_size() const
Returns size in pixels in the x dimension of the useful part of the window, not including decorations...
A thread; that is, a lightweight process.
void set_minimized(bool minimized)
Specifies whether the window should be created minimized (true), or normal (false).
Encapsulates all the communication with a particular instance of a given rendering backend...
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
void set_open(bool open)
Specifies whether the window should be open.
An interface to the TinyPanda software rendering code within this module.
Interfaces to the X11 window system.