Implemented SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH on X11
authorSam Lantinga <slouken@libsdl.org>
Thu, 29 Sep 2016 16:05:29 -0700
changeset 1038059efdcdd99e5
parent 10379 84be6396b68b
child 10381 6f77a03fb8cd
Implemented SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH on X11
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11window.h
     1.1 --- a/src/video/x11/SDL_x11events.c	Thu Sep 29 14:48:33 2016 -0700
     1.2 +++ b/src/video/x11/SDL_x11events.c	Thu Sep 29 16:05:29 2016 -0700
     1.3 @@ -35,6 +35,7 @@
     1.4  #include "../../events/SDL_mouse_c.h"
     1.5  #include "../../events/SDL_touch_c.h"
     1.6  
     1.7 +#include "SDL_hints.h"
     1.8  #include "SDL_timer.h"
     1.9  #include "SDL_syswm.h"
    1.10  
    1.11 @@ -523,9 +524,9 @@
    1.12          X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
    1.13                              XA_CARDINAL, 32, PropModeReplace,
    1.14                              (const unsigned char *) &latest, 1);
    1.15 -        #if DEBUG_XEVENTS
    1.16 +#ifdef DEBUG_XEVENTS
    1.17          printf("window %p: updating _NET_WM_USER_TIME to %lu\n", data, latest);
    1.18 -        #endif
    1.19 +#endif
    1.20          data->user_time = latest;
    1.21      }
    1.22  }
    1.23 @@ -711,6 +712,7 @@
    1.24                  data->pending_focus = PENDING_FOCUS_IN;
    1.25                  data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
    1.26              }
    1.27 +            data->last_focus_event_time = SDL_GetTicks();
    1.28          }
    1.29          break;
    1.30  
    1.31 @@ -987,7 +989,7 @@
    1.32              SDL_Mouse *mouse = SDL_GetMouse();
    1.33              if(!mouse->relative_mode || mouse->relative_mode_warp) {
    1.34  #ifdef DEBUG_MOTION
    1.35 -                printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
    1.36 +                printf("window %p: X11 motion: %d,%d\n", data, xevent.xmotion.x, xevent.xmotion.y);
    1.37  #endif
    1.38  
    1.39                  SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
    1.40 @@ -997,9 +999,13 @@
    1.41  
    1.42      case ButtonPress:{
    1.43              int xticks = 0, yticks = 0;
    1.44 +#ifdef DEBUG_XEVENTS
    1.45 +            printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent.xbutton.button);
    1.46 +#endif
    1.47              if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
    1.48                  SDL_SendMouseWheel(data->window, 0, xticks, yticks, SDL_MOUSEWHEEL_NORMAL);
    1.49              } else {
    1.50 +                SDL_bool ignore_click = SDL_FALSE;
    1.51                  int button = xevent.xbutton.button;
    1.52                  if(button == Button1) {
    1.53                      if (ProcessHitTest(_this, data, &xevent)) {
    1.54 @@ -1012,7 +1018,17 @@
    1.55                         => subtract (8-SDL_BUTTON_X1) to get value SDL expects */
    1.56                      button -= (8-SDL_BUTTON_X1);
    1.57                  }
    1.58 -                SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
    1.59 +                if (data->last_focus_event_time) {
    1.60 +                    const int X11_FOCUS_CLICK_TIMEOUT = 10;
    1.61 +                    if (!SDL_TICKS_PASSED(SDL_GetTicks(), data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
    1.62 +                        const char *hint = SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH);
    1.63 +                        ignore_click = (!hint || *hint == '0');
    1.64 +                    }
    1.65 +                    data->last_focus_event_time = 0;
    1.66 +                }
    1.67 +                if (!ignore_click) {
    1.68 +                    SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
    1.69 +                }
    1.70              }
    1.71              X11_UpdateUserTime(data, xevent.xbutton.time);
    1.72          }
    1.73 @@ -1022,7 +1038,10 @@
    1.74              int button = xevent.xbutton.button;
    1.75              /* The X server sends a Release event for each Press for wheels. Ignore them. */
    1.76              int xticks = 0, yticks = 0;
    1.77 -            if (!X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
    1.78 +#ifdef DEBUG_XEVENTS
    1.79 +            printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button);
    1.80 +#endif
    1.81 +            if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
    1.82                  if (button > 7) {
    1.83                      /* see explanation at case ButtonPress */
    1.84                      button -= (8-SDL_BUTTON_X1);
     2.1 --- a/src/video/x11/SDL_x11window.h	Thu Sep 29 14:48:33 2016 -0700
     2.2 +++ b/src/video/x11/SDL_x11window.h	Thu Sep 29 16:05:29 2016 -0700
     2.3 @@ -60,6 +60,7 @@
     2.4      int border_right;
     2.5      int border_top;
     2.6      int border_bottom;
     2.7 +    Uint32 last_focus_event_time;
     2.8      PendingFocusEnum pending_focus;
     2.9      Uint32 pending_focus_time;
    2.10      XConfigureEvent last_xconfigure;