~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/DolphinWX/Src/X11Utils.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2003 Dolphin Project.
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official SVN repository and contact information can be found at
 
16
// http://code.google.com/p/dolphin-emu/
 
17
 
 
18
#include "X11Utils.h"
 
19
 
 
20
#include <unistd.h>
 
21
#include <spawn.h>
 
22
#include <sys/wait.h>
 
23
 
 
24
extern char **environ;
 
25
 
 
26
#if defined(HAVE_WX) && HAVE_WX
 
27
#include <string>
 
28
#include <algorithm>
 
29
#include "WxUtils.h"
 
30
#endif
 
31
 
 
32
namespace X11Utils
 
33
{
 
34
 
 
35
void SendButtonEvent(Display *dpy, int button, int x, int y, bool pressed)
 
36
{
 
37
        XEvent event;
 
38
        Window win = (Window)Core::GetWindowHandle();
 
39
 
 
40
        // Init X event structure for mouse button press event
 
41
        event.xbutton.type = pressed ? ButtonPress : ButtonRelease;
 
42
        event.xbutton.x = x;
 
43
        event.xbutton.y = y;
 
44
        event.xbutton.button = button;
 
45
 
 
46
        // Send the event
 
47
        if (!XSendEvent(dpy, win, False, False, &event))
 
48
                ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window.");
 
49
}
 
50
 
 
51
void SendMotionEvent(Display *dpy, int x, int y)
 
52
{
 
53
        XEvent event;
 
54
        Window win = (Window)Core::GetWindowHandle();
 
55
 
 
56
        // Init X event structure for mouse motion
 
57
        event.xmotion.type = MotionNotify;
 
58
        event.xmotion.x = x;
 
59
        event.xmotion.y = y;
 
60
 
 
61
        // Send the event
 
62
        if (!XSendEvent(dpy, win, False, False, &event))
 
63
                ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window.");
 
64
}
 
65
 
 
66
void EWMH_Fullscreen(Display *dpy, int action)
 
67
{
 
68
        _assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
 
69
                        || action == _NET_WM_STATE_TOGGLE);
 
70
 
 
71
        Window win = (Window)Core::GetWindowHandle();
 
72
 
 
73
        // Init X event structure for _NET_WM_STATE_FULLSCREEN client message
 
74
        XEvent event;
 
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);
 
81
 
 
82
        // Send the event
 
83
        if (!XSendEvent(dpy, DefaultRootWindow(dpy), False,
 
84
                                SubstructureRedirectMask | SubstructureNotifyMask, &event))
 
85
                ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode.");
 
86
}
 
87
 
 
88
 
 
89
#if defined(HAVE_WX) && HAVE_WX
 
90
Window XWindowFromHandle(void *Handle)
 
91
{
 
92
        return GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(Handle)));
 
93
}
 
94
 
 
95
Display *XDisplayFromHandle(void *Handle)
 
96
{
 
97
        return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(GTK_WIDGET(Handle)));
 
98
}
 
99
#endif
 
100
 
 
101
void InhibitScreensaver(Display *dpy, Window win, bool suspend)
 
102
{
 
103
        char id[11];
 
104
        snprintf(id, sizeof(id), "0x%lx", win);
 
105
 
 
106
        // Call xdg-screensaver
 
107
        char *argv[4] = {
 
108
                (char *)"xdg-screensaver",
 
109
                (char *)(suspend ? "suspend" : "resume"),
 
110
                id,
 
111
                NULL};
 
112
        pid_t pid;
 
113
        if (!posix_spawnp(&pid, "xdg-screensaver", NULL, NULL, argv, environ))
 
114
        {
 
115
                int status;
 
116
                while (waitpid (pid, &status, 0) == -1);
 
117
 
 
118
                DEBUG_LOG(VIDEO, "Started xdg-screensaver (PID = %d)", (int)pid);
 
119
        }
 
120
}
 
121
 
 
122
#if defined(HAVE_XRANDR) && HAVE_XRANDR
 
123
XRRConfiguration::XRRConfiguration(Display *_dpy, Window _win)
 
124
        : dpy(_dpy)
 
125
        , win(_win)
 
126
        , screenResources(NULL), outputInfo(NULL), crtcInfo(NULL)
 
127
        , fullMode(0)
 
128
        , fs_fb_width(0), fs_fb_height(0), fs_fb_width_mm(0), fs_fb_height_mm(0)
 
129
        , bValid(true), bIsFullscreen(false)
 
130
{
 
131
        int XRRMajorVersion, XRRMinorVersion;
 
132
 
 
133
        if (!XRRQueryVersion(dpy, &XRRMajorVersion, &XRRMinorVersion) ||
 
134
                        (XRRMajorVersion < 1 || (XRRMajorVersion == 1 && XRRMinorVersion < 3)))
 
135
        {
 
136
                WARN_LOG(VIDEO, "XRRExtension not supported.");
 
137
                bValid = false;
 
138
                return;
 
139
        }
 
140
 
 
141
        screenResources = XRRGetScreenResourcesCurrent(dpy, win);
 
142
 
 
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);
 
148
 
 
149
        INFO_LOG(VIDEO, "XRRExtension-Version %d.%d", XRRMajorVersion, XRRMinorVersion);
 
150
        Update();
 
151
}
 
152
 
 
153
XRRConfiguration::~XRRConfiguration()
 
154
{
 
155
        if (bValid && bIsFullscreen)
 
156
                ToggleDisplayMode(False);
 
157
        if (screenResources)
 
158
                XRRFreeScreenResources(screenResources);
 
159
        if (outputInfo)
 
160
                XRRFreeOutputInfo(outputInfo);
 
161
        if (crtcInfo)
 
162
                XRRFreeCrtcInfo(crtcInfo);
 
163
}
 
164
 
 
165
void XRRConfiguration::Update()
 
166
{
 
167
        if(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution == "Auto")
 
168
                return;
 
169
        
 
170
        if (!bValid)
 
171
                return;
 
172
 
 
173
        if (outputInfo)
 
174
        {
 
175
                XRRFreeOutputInfo(outputInfo);
 
176
                outputInfo = NULL;
 
177
        }
 
178
        if (crtcInfo)
 
179
        {
 
180
                XRRFreeCrtcInfo(crtcInfo);
 
181
                crtcInfo = NULL;
 
182
        }
 
183
        fullMode = 0;
 
184
 
 
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(':') ==
 
189
                        std::string::npos)
 
190
        {
 
191
                fullWidth = fb_width;
 
192
                fullHeight = fb_height;
 
193
        }
 
194
        else
 
195
                sscanf(SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution.c_str(),
 
196
                                "%m[^:]: %ux%u", &output_name, &fullWidth, &fullHeight);
 
197
 
 
198
        for (int i = 0; i < screenResources->noutput; i++)
 
199
        {
 
200
                XRROutputInfo *output_info = XRRGetOutputInfo(dpy, screenResources, screenResources->outputs[i]);
 
201
                if (output_info && output_info->crtc && output_info->connection == RR_Connected)
 
202
                {
 
203
                        XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(dpy, screenResources, output_info->crtc);
 
204
                        if (crtc_info)
 
205
                        {
 
206
                                if (!output_name || !strcmp(output_name, output_info->name))
 
207
                                {
 
208
                                        // Use the first output for the default setting.
 
209
                                        if (!output_name)
 
210
                                        {
 
211
                                                output_name = strdup(output_info->name);
 
212
                                                SConfig::GetInstance().m_LocalCoreStartupParameter.strFullscreenResolution =
 
213
                                                        StringFromFormat("%s: %ux%u", output_info->name, fullWidth, fullHeight);
 
214
                                        }
 
215
                                        outputInfo = output_info;
 
216
                                        crtcInfo = crtc_info;
 
217
                                        for (int j = 0; j < output_info->nmode && fullMode == 0; j++)
 
218
                                        {
 
219
                                                for (int k = 0; k < screenResources->nmode && fullMode == 0; k++)
 
220
                                                {
 
221
                                                        if (output_info->modes[j] == screenResources->modes[k].id)
 
222
                                                        {
 
223
                                                                if (fullWidth == screenResources->modes[k].width &&
 
224
                                                                                fullHeight == screenResources->modes[k].height)
 
225
                                                                {
 
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;
 
231
                                                                }
 
232
                                                        }
 
233
                                                }
 
234
                                        }
 
235
                                }
 
236
                                else
 
237
                                {
 
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;
 
242
                                }
 
243
                        }
 
244
                        if (crtc_info && crtcInfo != crtc_info)
 
245
                                XRRFreeCrtcInfo(crtc_info);
 
246
                }
 
247
                if (output_info && outputInfo != output_info)
 
248
                        XRRFreeOutputInfo(output_info);
 
249
        }
 
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);
 
252
 
 
253
        if (output_name)
 
254
                free(output_name);
 
255
 
 
256
        if (outputInfo && crtcInfo && fullMode)
 
257
        {
 
258
                INFO_LOG(VIDEO, "Fullscreen Resolution %dx%d", fullWidth, fullHeight);
 
259
        }
 
260
        else
 
261
        {
 
262
                ERROR_LOG(VIDEO, "Failed to obtain fullscreen size.\n"
 
263
                                "Using current desktop resolution for fullscreen.");
 
264
        }
 
265
}
 
266
 
 
267
void XRRConfiguration::ToggleDisplayMode(bool bFullscreen)
 
268
{
 
269
        if (!bValid || !screenResources || !outputInfo || !crtcInfo || !fullMode)
 
270
                return;
 
271
        if (bFullscreen == bIsFullscreen)
 
272
                return;
 
273
 
 
274
        XGrabServer(dpy);
 
275
        if (bFullscreen)
 
276
        {
 
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;
 
282
        }
 
283
        else
 
284
        {
 
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;
 
290
        }
 
291
        XUngrabServer(dpy);
 
292
        XSync(dpy, false);
 
293
}
 
294
 
 
295
#if defined(HAVE_WX) && HAVE_WX
 
296
void XRRConfiguration::AddResolutions(wxArrayString& arrayStringFor_FullscreenResolution)
 
297
{
 
298
        if (!bValid || !screenResources)
 
299
                return;
 
300
 
 
301
        //Get all full screen resolutions for the config dialog
 
302
        for (int i = 0; i < screenResources->noutput; i++)
 
303
        {
 
304
                XRROutputInfo *output_info =
 
305
                        XRRGetOutputInfo(dpy, screenResources, screenResources->outputs[i]);
 
306
 
 
307
                if (output_info && output_info->crtc && output_info->connection == RR_Connected)
 
308
                {
 
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)
 
313
                                        {
 
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())
 
319
                                                {
 
320
                                                        resos.push_back(strRes);
 
321
                                                        arrayStringFor_FullscreenResolution.Add(StrToWxStr(strRes));
 
322
                                                }
 
323
                                        }
 
324
                }
 
325
                if (output_info)
 
326
                        XRRFreeOutputInfo(output_info);
 
327
        }
 
328
}
 
329
#endif
 
330
 
 
331
#endif
 
332
 
 
333
}