📄 display_window_opengl.cpp
字号:
}
catch (CL_Error& err)
{
CL_Log::log("debug", "Joystick Error: %1", err.message);
done = true;
}
}
else
{
CL_Log::log("debug", "Joystick Error: %1: %2", pathname, strerror(errno));
done = true;
}
}
}
void CL_DisplayWindow_OpenGL::destroy_window()
{
set_windowed();
if (context)
{
if (!glXMakeCurrent(disp, None, NULL))
{
printf("Could not release drawing context.\n");
}
glXDestroyContext(disp, context);
context = NULL;
}
keyboard = CL_InputDevice();
mouse = CL_InputDevice();
get_ic()->clear();
if (window) XDestroyWindow(disp, window);
window = 0;
if (disp_ref_count > 0)
{
disp_ref_count--;
if (disp_ref_count == 0)
{
XCloseDisplay(disp);
disp = 0;
}
}
}
void CL_DisplayWindow_OpenGL::on_xevent(XEvent &event)
{
//Disabled for now
}
void CL_DisplayWindow_OpenGL::flip()
{
CL_GLStateChecker::from_gc(get_gc())->flush();
XSync(disp,False);
glXSwapBuffers(disp, window);
}
void CL_DisplayWindow_OpenGL::set_fullscreen(int width, int height, int bpp, int refresh_rate)
{
if(fullscreen)
return;
// Vid-mode Switching
int num_modes;
XF86VidModeModeInfo **modes;
XF86VidModeModeLine cur_mode;
std::list<XF86VidModeModeInfo *> usable_modes;
XF86VidModeGetModeLine(disp, 0, &dotclock, &cur_mode);
old_mode.dotclock = dotclock;
old_mode.hdisplay = cur_mode.hdisplay;
old_mode.hsyncstart = cur_mode.hsyncstart;
old_mode.hsyncend = cur_mode.hsyncend;
old_mode.htotal = cur_mode.htotal;
old_mode.vdisplay = cur_mode.vdisplay;
old_mode.vsyncstart = cur_mode.vsyncstart;
old_mode.vsyncend = cur_mode.vsyncend;
old_mode.vtotal = cur_mode.vtotal;
old_mode.flags = cur_mode.flags;
old_mode.privsize = 0;
XF86VidModeGetAllModeLines(disp, 0, &num_modes, &modes);
for(int i = 0; i < num_modes; i++)
{
if(modes[i]->hdisplay == width && modes[i]->vdisplay == height)
{
CL_Log::log("debug", "Useable fullscreen mode found: %1x%2", width, height);
usable_modes.push_back(modes[i]);
}
}
if (usable_modes.empty())
{
CL_Log::log("debug", "No useable fullscreen modes available!");
}
if(!width)
width = get_width();
if(!height)
height = get_height();
if(!bpp)
bpp = glx_bpp;
//Hide Window
XUnmapWindow(disp, window);
XSync(disp, True);
// Turn off WM control
attributes.override_redirect = True;
XChangeWindowAttributes(disp, window, CWBorderPixel | CWColormap | CWOverrideRedirect, &attributes);
XMoveResizeWindow(disp, window, 0, 0, width, height);
// Re-appear window
XMapRaised(disp, window);
XSync(disp, True);
// Get input focus
XSetInputFocus (disp,window, RevertToNone, CurrentTime);
int x,y;
set_position(0,0);
// Move the mouse and switch moves
XWarpPointer(disp, None, window, 0, 0, 0, 0, 0, 0);
if (!usable_modes.empty())
{
XF86VidModeSwitchToMode(disp, 0, *(usable_modes.begin()));
}
XWarpPointer(disp, None, window, 0, 0, 0, 0, 0, 0);
XGrabPointer(disp, window, True, 0, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
XF86VidModeGetViewPort(disp, 0, &x, &y);
set_position(x, y);
if (!usable_modes.empty())
{
old_x = x;
old_y = y;
}
else
{
// If we never managed to switch mode, tell restore mode code.
old_x = -1;
old_y = -1;
}
CL_Log::log("debug", "Viewport is %1x%2", x, y);
XSync(disp, True);
fullscreen = true;
}
void CL_DisplayWindow_OpenGL::set_windowed()
{
if(!fullscreen)
return;
// Hide window
XUnmapWindow(disp, window);
XSync(disp, True);
// Turn on WM control
attributes.override_redirect = False;
XChangeWindowAttributes(disp, window, CWBorderPixel | CWColormap | CWOverrideRedirect, &attributes);
XMoveResizeWindow(disp, window, 0, 0, fullscreen_width, fullscreen_height);
XMapRaised(disp, window);
XSync(disp, True);
fullscreen = false;
// Only restore mode if we ever switched mode.
if (old_x != -1 || old_y != -1)
{
XF86VidModeSwitchToMode(disp, 0, &old_mode);
XF86VidModeSetViewPort(disp, 0, old_x, old_y);
}
XUngrabPointer(disp, CurrentTime);
XSync(disp, True);
}
void CL_DisplayWindow_OpenGL::set_title(const std::string &title)
{
XSetStandardProperties(disp, window, title.c_str(), title.c_str(), None, NULL, 0, NULL);
}
void CL_DisplayWindow_OpenGL::set_position(const CL_Rect &pos)
{
set_position(pos.left, pos.top);
XResizeWindow(disp, window, pos.get_width(), pos.get_height());
set_size(pos.get_width(), pos.get_height());
}
void CL_DisplayWindow_OpenGL::set_position(int x, int y)
{
XMoveWindow(disp, window, x, y);
}
void CL_DisplayWindow_OpenGL::set_size(int width, int height)
{
fullscreen_width = width;
fullscreen_height = height;
sig_resize(width, height);
}
void CL_DisplayWindow_OpenGL::set_buffer_count(int flipping_buffers)
{
// Not implemented.
// We can't change how many buffer we use in OpenGL, the drivers pick for us
CL_Log::log("debug", "CL_DisplayWindow_OpenGL::set_buffer_count is not implemented");
}
void CL_DisplayWindow_OpenGL::update(const CL_Rect &rect)
{
CL_OpenGLState state(get_gc());
state.set_active();
state.setup_2d();
clReadBuffer(CL_BACK);
if(clGetError() == CL_NO_ERROR) // Check if we got more than 1 buffer.
{
float raster_pos[4];
clGetFloatv(CL_CURRENT_RASTER_POSITION, raster_pos);
clDrawBuffer(CL_FRONT);
clRasterPos3f(rect.left, rect.bottom, raster_pos[2]);
clCopyPixels(rect.top, rect.left, rect.get_width(), rect.get_height(), CL_COLOR);
// Return to drawing to the back buffer
clDrawBuffer(CL_BACK);
}
}
void CL_DisplayWindow_OpenGL::show_system_cursor()
{
XDefineCursor(disp, window, system_cursor);
}
void CL_DisplayWindow_OpenGL::hide_system_cursor()
{
XDefineCursor(disp, window, hidden_cursor);
}
void CL_DisplayWindow_OpenGL::cursor_changed()
{
// We have to extract the data from the cursor in order to display it
// At this point nothing more than hiding/unhiding the system cursor is supported
// I'm waiting for the release of XFree86 4.3, which has the Xcursor extension library.
// This will greatly simplify this, so I don't want to start implenting this.
// --MSR, Nov. 13, 2002
}
void CL_DisplayWindow_OpenGL::keep_alive()
{
XEvent event, next_event;
CL_Rect *rect;
for (int i=XPending(disp); i>0; i--)
{
XNextEvent(disp, &event);
switch(event.type)
{
//Resize or Move
case ConfigureNotify:
#ifdef DEBUG
CL_Log::log("debug", "ConfigureNotify Event received");
#endif
set_size(event.xconfigure.width,event.xconfigure.height);
break;
case ClientMessage:
#ifdef DEBUG
CL_Log::log("debug", "Received ClientMessage, sending close signal");
#endif
sig_window_close();
break;
case Expose:
// Repaint notification
// Could be more efficient if we checked ahead for other
// repaint notifications
#ifdef DEBUG
CL_Log::log("debug", "Expose Event received");
#endif
rect = new CL_Rect(event.xexpose.x, event.xexpose.y,
event.xexpose.x + event.xexpose.width, event.xexpose.y + event.xexpose.height);
sig_paint(*rect);
delete rect;
break;
case FocusIn:
#ifdef DEBUG
CL_Log::log("debug", "Focus In");
#endif
focus = true;
sig_got_focus();
break;
case FocusOut:
#ifdef DEBUG
CL_Log::log("debug", "Focus Out");
#endif
focus = false;
sig_lost_focus();
break;
case KeyRelease:
if( XEventsQueued( disp, QueuedAfterReading ) )
{
XPeekEvent( disp, &next_event );
if( next_event.type == KeyPress &&
next_event.xkey.window == event.xkey.window &&
next_event.xkey.keycode == event.xkey.keycode &&
next_event.xkey.time == event.xkey.time )
{
// Do not report anything for this event
break;
}
}
case KeyPress:
case KeymapNotify:
case ButtonPress:
case ButtonRelease:
case MotionNotify:
sig_xevent(event);
break;
case PropertyNotify:
#ifdef DEBUG
// This looks to be mostly useless
// I'm getting a lot of WM messages that aren't really useful.
// --MSR, April 5, 2003
/*
if(event.xproperty.state == PropertyNewValue)
{
CL_Log::log("debug", "%1 has a new value", XGetAtomName(disp, event.xproperty.atom));
}
*/
#endif
break;
#ifdef DEBUG
case EnterNotify:
case LeaveNotify:
CL_Log::log("debug", "The mouse has left or entered the window");
break;
default:
CL_Log::log("debug", "Unhandled event type: %1", event.type);
#endif
}
}
}
// Local Variables: ***
// mode: clanlib ***
// End: ***
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -