File: sdl_x11.cpp

package info (click to toggle)
glvis 4.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,780 kB
  • sloc: cpp: 35,217; ansic: 5,695; sh: 340; makefile: 301; python: 193
file content (130 lines) | stat: -rw-r--r-- 3,701 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-443271.
//
// This file is part of the GLVis visualization tool and library. For more
// information and source code availability see https://glvis.org.
//
// GLVis is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.

#include "sdl_x11.hpp"

#ifdef SDL_VIDEO_DRIVER_X11

#include <vector>
#include <array>
#include <iostream>

#ifndef __EMSCRIPTEN__
#include <SDL2/SDL_syswm.h>
#else
#include <SDL_syswm.h>
#endif

#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
#include <X11/extensions/XInput2.h>
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2

using namespace std;

void SdlX11Platform::RegisterWindow(SDL_Window* window)
{
   SDL_SysWMinfo sysinfo;
   SDL_VERSION(&sysinfo.version);
   if (!SDL_GetWindowWMInfo(window, &sysinfo))
   {
      cerr << "Error: unable to get window manager information for the "
           << "current window." << endl;
      return;
   }
   if (sysinfo.subsystem != SDL_SYSWM_X11)
   {
      cerr << "Error: created SDL window is not an X11 window." << endl;
      return;
   }
   Display *disp = sysinfo.info.x11.display;

   display_fds.emplace(window, ConnectionNumber(disp));

#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
   // Disable XInput extension events since they are generated even outside
   // the GLVis window.
   Window root_win = DefaultRootWindow(disp);
   unsigned char mask[4] = {0,0,0,0};
   XIEventMask event_mask;
   event_mask.deviceid = XIAllMasterDevices;
   event_mask.mask_len = sizeof(mask);
   event_mask.mask = mask;
#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
   const char Xi_lib[] = SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2;
#else
   const char Xi_lib[] = "libXi.so";
#endif
   typedef int (*XISelectEvents_ptr)(Display *, Window, XIEventMask *, int);
   XISelectEvents_ptr XISelectEvents_ = NULL;
   void *lib = SDL_LoadObject(Xi_lib);
   if (lib != NULL)
   {
      XISelectEvents_ =
         (XISelectEvents_ptr)SDL_LoadFunction(lib, "XISelectEvents");
   }
   if (XISelectEvents_ == NULL)
   {
      cerr << "Error accessing XISelectEvents!" << endl;
      exit(EXIT_FAILURE);
   }
   if (XISelectEvents_(disp, root_win, &event_mask, 1) != Success)
   {
      cerr << "Failed to disable XInput on the default root window!" << endl;
   }
   Window wnd = sysinfo.info.x11.window;
   if (XISelectEvents_(disp, wnd, &event_mask, 1) != Success)
   {
      cerr << "Failed to disable XInput on the current window!" << endl;
   }
#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
   SDL_UnloadObject(lib);
#endif
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2
}

void SdlX11Platform::UnregisterWindow(SDL_Window* window)
{
   display_fds.erase(window);
}

void SdlX11Platform::WaitEvent()
{
   vector<pollfd> pfd;
   pfd.emplace_back( pollfd{ event_pfd[0], POLLIN, 0 } );

   for (auto wnd : display_fds)
   {
      // add file descriptors for the window event queue
      pfd.emplace_back( pollfd{ wnd.second, POLLIN, 0 } );
   }

   int nstr;
   do
   {
      // We timeout the poll call after 500ms, just in case a pending SDL_QUIT
      // needs to be pumped into the SDL event queue
      nstr = poll(pfd.data(), pfd.size(), 500);
   }
   while (nstr == -1 && errno == EINTR);

   if (nstr == -1) { perror("poll()"); }

   int n = 0;
   // Read out the pending GLVisCommand-sent events, if any
   do
   {
      array<char, 16> buf;
      n = read(event_pfd[0], buf.data(), buf.size());
   }
   while (n > 0);
}

#endif // SDL_VIDEO_DRIVER_X11