1
// Copyright (C) 2003 Dolphin Project.
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0.
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
15
// Official SVN repository and contact information can be found at
16
// http://code.google.com/p/dolphin-emu/
24
extern char **environ;
26
#if defined(HAVE_WX) && HAVE_WX
35
void SendButtonEvent(Display *dpy, int button, int x, int y, bool pressed)
38
Window win = (Window)Core::GetWindowHandle();
40
// Init X event structure for mouse button press event
41
event.xbutton.type = pressed ? ButtonPress : ButtonRelease;
44
event.xbutton.button = button;
47
if (!XSendEvent(dpy, win, False, False, &event))
48
ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window.");
51
void SendMotionEvent(Display *dpy, int x, int y)
54
Window win = (Window)Core::GetWindowHandle();
56
// Init X event structure for mouse motion
57
event.xmotion.type = MotionNotify;
62
if (!XSendEvent(dpy, win, False, False, &event))
63
ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window.");
66
void EWMH_Fullscreen(Display *dpy, int action)
68
_assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
69
|| action == _NET_WM_STATE_TOGGLE);
71
Window win = (Window)Core::GetWindowHandle();
73
// Init X event structure for _NET_WM_STATE_FULLSCREEN client message
75
event.xclient.type = ClientMessage;
76
event.xclient.message_type = XInternAtom(dpy, "_NET_WM_STATE", False);
77
event.xclient.window = win;
78
event.xclient.format = 32;
79
event.xclient.data.l[0] = action;
80
event.xclient.data.l[1] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
83
if (!XSendEvent(dpy, DefaultRootWindow(dpy), False,
84
SubstructureRedirectMask | SubstructureNotifyMask, &event))
85
ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.");
89
#if defined(HAVE_WX) && HAVE_WX
90
Window XWindowFromHandle(void *Handle)
92
return GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(Handle)));
95
Display *XDisplayFromHandle(void *Handle)
97
return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(GTK_WIDGET(Handle)));
101
void InhibitScreensaver(Display *dpy, Window win, bool suspend)
104
snprintf(id, sizeof(id), "0x%lx", win);
106
// Call xdg-screensaver
108
(char *)"xdg-screensaver",
109
(char *)(suspend ? "suspend" : "resume"),
113
if (!posix_spawnp(&pid, "xdg-screensaver", NULL, NULL, argv, environ))
116
while (waitpid (pid, &status, 0) == -1);
118
DEBUG_LOG(VIDEO, "Started xdg-screensaver (PID = %d)", (int)pid);
122
#if defined(HAVE_XRANDR) && HAVE_XRANDR
123
XRRConfiguration::XRRConfiguration(Display *_dpy, Window _win)
126
, screenResources(NULL), outputInfo(NULL), crtcInfo(NULL)
128
, fs_fb_width(0), fs_fb_height(0), fs_fb_width_mm(0), fs_fb_height_mm(0)
129
, bValid(true), bIsFullscreen(false)
131
int XRRMajorVersion, XRRMinorVersion;
133
if (!XRRQueryVersion(dpy, &XRRMajorVersion, &XRRMinorVersion) ||
134
(XRRMajorVersion < 1 || (XRRMajorVersion == 1 && XRRMinorVersion < 3)))
136
WARN_LOG(VIDEO, "XRRExtension not supported.");
141
screenResources = XRRGetScreenResourcesCurrent(dpy, win);
143
screen = DefaultScreen(dpy);
144
fb_width = DisplayWidth(dpy, screen);
145
fb_height = DisplayHeight(dpy, screen);
146
fb_width_mm = DisplayWidthMM(dpy, screen);
147
fb_height_mm = DisplayHeightMM(dpy, screen);
149
INFO_LOG(VIDEO, "XRRExtension-Version %d.%d", XRRMajorVersion, XRRMinorVersion);
153
XRRConfiguration::~XRRConfiguration()
155
if (bValid && bIsFullscreen)
156
ToggleDisplayMode(False);
158
XRRFreeScreenResources(screenResources);
160
XRRFreeOutputInfo(outputInfo);
162
XRRFreeCrtcInfo(crtcInfo);
165
void XRRConfiguration::Update()
167
if(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution == "Auto")
175
XRRFreeOutputInfo(outputInfo);
180
XRRFreeCrtcInfo(crtcInfo);
185
// Get the resolution setings for fullscreen mode
186
unsigned int fullWidth, fullHeight;
187
char *output_name = NULL;
188
if (SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.find(':') ==
191
fullWidth = fb_width;
192
fullHeight = fb_height;
195
sscanf(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str(),
196
"%m[^:]: %ux%u", &output_name, &fullWidth, &fullHeight);
198
for (int i = 0; i < screenResources->noutput; i++)
200
XRROutputInfo *output_info = XRRGetOutputInfo(dpy, screenResources, screenResources->outputs[i]);
201
if (output_info && output_info->crtc && output_info->connection == RR_Connected)
203
XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, screenResources, output_info->crtc);
206
if (!output_name || !strcmp(output_name, output_info->name))
208
// Use the first output for the default setting.
211
output_name = strdup(output_info->name);
212
SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution =
213
StringFromFormat("%s: %ux%u", output_info->name, fullWidth, fullHeight);
215
outputInfo = output_info;
216
crtcInfo = crtc_info;
217
for (int j = 0; j < output_info->nmode && fullMode == 0; j++)
219
for (int k = 0; k < screenResources->nmode && fullMode == 0; k++)
221
if (output_info->modes[j] == screenResources->modes[k].id)
223
if (fullWidth == screenResources->modes[k].width &&
224
fullHeight == screenResources->modes[k].height)
226
fullMode = screenResources->modes[k].id;
227
if (crtcInfo->x + (int)screenResources->modes[k].width > fs_fb_width)
228
fs_fb_width = crtcInfo->x + screenResources->modes[k].width;
229
if (crtcInfo->y + (int)screenResources->modes[k].height > fs_fb_height)
230
fs_fb_height = crtcInfo->y + screenResources->modes[k].height;
238
if (crtc_info->x + (int)crtc_info->width > fs_fb_width)
239
fs_fb_width = crtc_info->x + crtc_info->width;
240
if (crtc_info->y + (int)crtc_info->height > fs_fb_height)
241
fs_fb_height = crtc_info->y + crtc_info->height;
244
if (crtc_info && crtcInfo != crtc_info)
245
XRRFreeCrtcInfo(crtc_info);
247
if (output_info && outputInfo != output_info)
248
XRRFreeOutputInfo(output_info);
250
fs_fb_width_mm = fs_fb_width * DisplayHeightMM(dpy, screen) / DisplayHeight(dpy, screen);
251
fs_fb_height_mm = fs_fb_height * DisplayHeightMM(dpy, screen) / DisplayHeight(dpy, screen);
256
if (outputInfo && crtcInfo && fullMode)
258
INFO_LOG(VIDEO, "Fullscreen Resolution %dx%d", fullWidth, fullHeight);
262
ERROR_LOG(VIDEO, "Failed to obtain fullscreen size.\n"
263
"Using current desktop resolution for fullscreen.");
267
void XRRConfiguration::ToggleDisplayMode(bool bFullscreen)
269
if (!bValid || !screenResources || !outputInfo || !crtcInfo || !fullMode)
271
if (bFullscreen == bIsFullscreen)
277
XRRSetCrtcConfig(dpy, screenResources, outputInfo->crtc, CurrentTime,
278
crtcInfo->x, crtcInfo->y, fullMode, crtcInfo->rotation,
279
crtcInfo->outputs, crtcInfo->noutput);
280
XRRSetScreenSize(dpy, win, fs_fb_width, fs_fb_height, fs_fb_width_mm, fs_fb_height_mm);
281
bIsFullscreen = true;
285
XRRSetCrtcConfig(dpy, screenResources, outputInfo->crtc, CurrentTime,
286
crtcInfo->x, crtcInfo->y, crtcInfo->mode, crtcInfo->rotation,
287
crtcInfo->outputs, crtcInfo->noutput);
288
XRRSetScreenSize(dpy, win, fb_width, fb_height, fb_width_mm, fb_height_mm);
289
bIsFullscreen = false;
295
#if defined(HAVE_WX) && HAVE_WX
296
void XRRConfiguration::AddResolutions(wxArrayString& arrayStringFor_FullscreenResolution)
298
if (!bValid || !screenResources)
301
//Get all full screen resolutions for the config dialog
302
for (int i = 0; i < screenResources->noutput; i++)
304
XRROutputInfo *output_info =
305
XRRGetOutputInfo(dpy, screenResources, screenResources->outputs[i]);
307
if (output_info && output_info->crtc && output_info->connection == RR_Connected)
309
std::vector<std::string> resos;
310
for (int j = 0; j < output_info->nmode; j++)
311
for (int k = 0; k < screenResources->nmode; k++)
312
if (output_info->modes[j] == screenResources->modes[k].id)
314
const std::string strRes =
315
std::string(output_info->name) + ": " +
316
std::string(screenResources->modes[k].name);
317
// Only add unique resolutions
318
if (std::find(resos.begin(), resos.end(), strRes) == resos.end())
320
resos.push_back(strRes);
321
arrayStringFor_FullscreenResolution.Add(StrToWxStr(strRes));
326
XRRFreeOutputInfo(output_info);