24#include <wx/nonownedwnd.h> 
   25#include <wx/settings.h> 
   32#ifdef GDK_WINDOWING_X11 
   36#ifdef GDK_WINDOWING_WAYLAND 
   37#include <gdk/gdkwayland.h> 
   50    wxColour bg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
 
   53    double brightness = ( bg.Red() / 255.0 ) * 0.299 +
 
   54                        ( bg.Green() / 255.0 ) * 0.587 +
 
   55                        ( bg.Blue() / 255.0 ) * 0.117;
 
   57    return brightness < 0.5;
 
 
   63    return wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
 
 
   71#if( GTK_CHECK_VERSION( 3, 24, 0 ) ) 
   73    GtkWidgetPath*   
path = gtk_widget_path_new();
 
   74    GtkStyleContext* sc = gtk_style_context_new();
 
   76    gtk_widget_path_append_type( 
path, GTK_TYPE_WINDOW );
 
   77    gtk_widget_path_iter_set_object_name( 
path, -1, 
"infobar" );
 
   78    gtk_widget_path_iter_add_class( 
path, -1, 
"info" );
 
   80    gtk_style_context_set_path( sc, 
path );
 
   81    gtk_style_context_set_state( sc, GTK_STATE_FLAG_NORMAL );
 
   83    gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, 
"background-color", &rgba, NULL );
 
   84    aBgColour = wxColour( *rgba );
 
   85    gdk_rgba_free( rgba );
 
   87    gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, 
"color", &rgba, NULL );
 
   88    aFgColour = wxColour( *rgba );
 
   89    gdk_rgba_free( rgba );
 
   94    if( aBgColour.Alpha() == 0 )
 
   96        gtk_widget_path_append_type( 
path, G_TYPE_NONE );
 
   97        gtk_widget_path_iter_set_object_name( 
path, -1, 
"revealer" );
 
   98        gtk_widget_path_append_type( 
path, G_TYPE_NONE );
 
   99        gtk_widget_path_iter_set_object_name( 
path, -1, 
"box" );
 
  101        gtk_style_context_set_path( sc, 
path );
 
  102        gtk_style_context_set_state( sc, GTK_STATE_FLAG_NORMAL );
 
  104        gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, 
"background-color", &rgba, NULL );
 
  105        aBgColour = wxColour( *rgba );
 
  106        gdk_rgba_free( rgba );
 
  108        gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, 
"color", &rgba, NULL );
 
  109        aFgColour = wxColour( *rgba );
 
  110        gdk_rgba_free( rgba );
 
  113    gtk_widget_path_free( 
path );
 
  114    g_object_unref( sc );
 
  117    aBgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK );
 
  118    aFgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOTEXT );
 
 
  135    GtkWindow* window = GTK_WINDOW( aWindow->GetHandle() );
 
  138        return gtk_window_is_active( window );
 
 
  173    case wxCURSOR_BULLSEYE:
 
 
  195    GtkMenuItem*   pMenuItem   = GTK_MENU_ITEM( pItem );
 
  196    GtkWidget*     child       = gtk_bin_get_child( GTK_BIN( pMenuItem ) );
 
  197    GtkCellView*   pCellView   = GTK_CELL_VIEW( child );
 
  198    GtkCellLayout* pCellLayout = GTK_CELL_LAYOUT( pCellView );
 
  199    GtkCellArea*   pCellArea   = gtk_cell_layout_get_area( pCellLayout );
 
  201    g_signal_handlers_block_matched( pCellArea, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, userdata );
 
 
  207    AtkObject* atkObj = gtk_combo_box_get_popup_accessible( GTK_COMBO_BOX( aChoice->m_widget ) );
 
  209    if( !atkObj || !GTK_IS_ACCESSIBLE( atkObj ) )
 
  212    GtkWidget* widget = gtk_accessible_get_widget( GTK_ACCESSIBLE( atkObj ) );
 
  214    if( !widget || !GTK_IS_MENU( widget ) )
 
  217    GtkMenu* menu = GTK_MENU( widget );
 
 
  227    GList* cells = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( aChoice->m_widget ) );
 
  232    GtkCellRenderer* cell = (GtkCellRenderer*) cells->data;
 
  237    g_object_set( G_OBJECT( cell ), 
"ellipsize", PANGO_ELLIPSIZE_END, 
nullptr );
 
  240    g_list_free( cells );
 
 
  248    GtkWidget* widget = 
static_cast<GtkWidget*
>( aWindow->GetHandle() );
 
  250    if( widget && gtk_check_version( 3, 10, 0 ) == 
nullptr )
 
  251        val = gtk_widget_get_scale_factor( widget );
 
 
  266    return wxSize( aWindow->GetSize().GetX() - wxSystemSettings::GetMetric( wxSYS_VSCROLL_X ),
 
  267                   aWindow->GetSize().GetY() - wxSystemSettings::GetMetric( wxSYS_HSCROLL_Y ) );
 
 
  273    gtk_scrolled_window_set_overlay_scrolling( GTK_SCROLLED_WINDOW( aWindow->GetHandle() ),
 
 
  280    gboolean allowed = 1;
 
  282    g_object_get( gtk_settings_get_default(), 
"gtk-menu-images", &allowed, NULL );
 
 
  288#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND ) 
  290static bool wayland_warp_pointer( GtkWidget* aWidget, GdkDisplay* aDisplay, GdkWindow* aWindow,
 
  291                                  GdkDevice* aPtrDev, 
int aX, 
int aY );
 
  295static wxPoint s_warped_from;
 
  296static wxPoint s_warped_to;
 
  300    wxPoint wx_pos = wxGetMousePosition();
 
  302    if( wx_pos == s_warped_from )
 
  304        wxLogTrace( 
traceWayland, wxS( 
"Faked mouse pos %d %d -> %d %d" ), wx_pos.x, wx_pos.y,
 
  305                    s_warped_to.x, s_warped_to.y );
 
  312        s_warped_from = wxPoint();
 
  313        s_warped_to = wxPoint();
 
  324    if( !wxGetEnv( wxT( 
"WAYLAND_DISPLAY" ), 
nullptr ) )
 
  326        aWindow->WarpPointer( aX, aY );
 
  331        GtkWidget* widget = 
static_cast<GtkWidget*
>( aWindow->GetHandle() );
 
  333        GdkDisplay* disp = gtk_widget_get_display( widget );
 
  334        GdkSeat*    seat = gdk_display_get_default_seat( disp );
 
  335        GdkDevice*  ptrdev = gdk_seat_get_pointer( seat );
 
  337#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND ) 
  338        if( GDK_IS_WAYLAND_DISPLAY( disp ) )
 
  340            wxPoint    initialPos = wxGetMousePosition();
 
  341            GdkWindow* win = aWindow->GTKGetDrawingWindow();
 
  343            if( wayland_warp_pointer( widget, disp, win, ptrdev, aX, aY ) )
 
  345                s_warped_from = initialPos;
 
  346                s_warped_to = aWindow->ClientToScreen( wxPoint( aX, aY ) );
 
  348                wxLogTrace( 
traceWayland, wxS( 
"Set warped from %d %d to %d %d" ), s_warped_from.x,
 
  349                            s_warped_from.y, s_warped_to.x, s_warped_to.y );
 
  354            wxLogTrace( 
traceWayland, wxS( 
"*** Warp to %d %d failed ***" ), aX, aY );
 
  359#ifdef GDK_WINDOWING_X11 
  360        if( GDK_IS_X11_DISPLAY( disp ) )
 
  362            GdkWindow* win = gdk_device_get_window_at_position( ptrdev, 
nullptr, 
nullptr );
 
  363            GdkCursor* blank_cursor = gdk_cursor_new_for_display( disp, GDK_BLANK_CURSOR );
 
  364            GdkCursor* cur_cursor = gdk_window_get_cursor( win );
 
  367                g_object_ref( cur_cursor );
 
  369            gdk_window_set_cursor( win, blank_cursor );
 
  370            aWindow->WarpPointer( aX, aY );
 
  371            gdk_window_set_cursor( win, cur_cursor );
 
  374                g_object_unref( cur_cursor );
 
  377                g_object_unref( blank_cursor );
 
 
  395    wxWindowGTK* win = 
static_cast<wxWindowGTK*
>( aWindow );
 
  398        GtkIMContext* imContext = win->m_imContext;
 
  401            gtk_im_context_focus_out( imContext );
 
 
  415#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND ) 
  417static bool                               s_wl_initialized = 
false;
 
  418static struct wl_compositor*              s_wl_compositor = NULL;
 
  419static struct zwp_pointer_constraints_v1* s_wl_pointer_constraints = NULL;
 
  420static struct zwp_confined_pointer_v1*    s_wl_confined_pointer = NULL;
 
  421static struct wl_region*                  s_wl_confinement_region = NULL;
 
  422static bool                               s_wl_locked_flag = 
false;
 
  424static void handle_global( 
void* data, 
struct wl_registry* registry, uint32_t 
name,
 
  425                           const char* interface, uint32_t version )
 
  427    wxLogTrace( 
traceWayland, 
"handle_global received %s name %u version %u", interface,
 
  428                (
unsigned int) 
name, (
unsigned int) version );
 
  430    if( strcmp( interface, wl_compositor_interface.name ) == 0 )
 
  432        s_wl_compositor = 
static_cast<wl_compositor*
>(
 
  433                wl_registry_bind( registry, 
name, &wl_compositor_interface, version ) );
 
  437        s_wl_pointer_constraints = 
static_cast<zwp_pointer_constraints_v1*
>( wl_registry_bind(
 
  442static void handle_global_remove( 
void*, 
struct wl_registry*, uint32_t 
name )
 
  444    wxLogTrace( 
traceWayland, 
"handle_global_remove name %u", (
unsigned int) 
name );
 
  447static const struct wl_registry_listener registry_listener = {
 
  448    .global = handle_global,
 
  449    .global_remove = handle_global_remove,
 
  452static void confined_handler( 
void* data, 
struct zwp_confined_pointer_v1* zwp_confined_pointer_v1 )
 
  457static void unconfined_handler( 
void*                           data,
 
  458                                struct zwp_confined_pointer_v1* zwp_confined_pointer_v1 )
 
  460    wxLogTrace( 
traceWayland, wxS( 
"Pointer unconfined" ) );
 
  464    .confined = confined_handler,
 
  465    .unconfined = unconfined_handler
 
  468static void locked_handler( 
void* data, 
struct zwp_locked_pointer_v1* zwp_locked_pointer_v1 )
 
  470    s_wl_locked_flag = 
true;
 
  474static void unlocked_handler( 
void* data, 
struct zwp_locked_pointer_v1* zwp_locked_pointer_v1 )
 
  480    .locked = locked_handler,
 
  481    .unlocked = unlocked_handler
 
  488static void initialize_wayland( wl_display* wldisp )
 
  490    if( s_wl_initialized )
 
  495    struct wl_registry* registry = wl_display_get_registry( wldisp );
 
  496    wl_registry_add_listener( registry, ®istry_listener, NULL );
 
  497    wl_display_roundtrip( wldisp );
 
  498    s_wl_initialized = 
true;
 
  502struct zwp_locked_pointer_v1* s_wl_locked_pointer = NULL;
 
  504static int s_after_paint_handler_id = 0;
 
  506static void on_frame_clock_after_paint( GdkFrameClock* clock, GtkWidget* widget )
 
  508    if( s_wl_locked_pointer )
 
  511        s_wl_locked_pointer = NULL;
 
  513        wxLogTrace( 
traceWayland, wxS( 
"after-paint: locked_pointer destroyed" ) );
 
  515        g_signal_handler_disconnect( (gpointer) clock, s_after_paint_handler_id );
 
  516        s_after_paint_handler_id = 0;
 
  519        if( s_wl_confinement_region != NULL )
 
  521            wxLogTrace( 
traceWayland, wxS( 
"after-paint: Restoring confinement" ) );
 
  523            GdkDisplay* disp = gtk_widget_get_display( widget );
 
  524            GdkSeat*    seat = gdk_display_get_default_seat( disp );
 
  525            GdkDevice*  ptrdev = gdk_seat_get_pointer( seat );
 
  526            GdkWindow*  window = gtk_widget_get_window( widget );
 
  528            wl_display* wldisp = gdk_wayland_display_get_wl_display( disp );
 
  529            wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( window );
 
  530            wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev );
 
  533                    s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region,
 
  536            wl_display_roundtrip( wldisp );
 
  542static bool wayland_warp_pointer( GtkWidget* aWidget, GdkDisplay* aDisplay, GdkWindow* aWindow,
 
  543                                  GdkDevice* aPtrDev, 
int aX, 
int aY )
 
  545    wl_display* wldisp = gdk_wayland_display_get_wl_display( aDisplay );
 
  546    wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( aWindow );
 
  547    wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( aPtrDev );
 
  549    if( s_after_paint_handler_id )
 
  552        wxLogTrace( 
traceWayland, wxS( 
"Not warping: after-paint pending" ) );
 
  556    initialize_wayland( wldisp );
 
  558    if( s_wl_locked_pointer )
 
  561        wxLogTrace( 
traceWayland, wxS( 
"** Destroying previous locked_pointer **" ) );
 
  563        wl_display_roundtrip( wldisp );
 
  564        s_wl_locked_pointer = NULL;
 
  569    GdkFrameClock* frame_clock = gdk_window_get_frame_clock( aWindow );
 
  570    s_after_paint_handler_id = g_signal_connect_after(
 
  571            frame_clock, 
"after-paint", G_CALLBACK( on_frame_clock_after_paint ), aWidget );
 
  574    if( s_wl_confinement_region && s_wl_confined_pointer )
 
  577        wl_display_roundtrip( wldisp );
 
  578        s_wl_confined_pointer = NULL;
 
  581    s_wl_locked_flag = 
false;
 
  583    s_wl_locked_pointer =
 
  590    gtk_widget_translate_coordinates( aWidget, gtk_widget_get_toplevel( aWidget ), 0, 0, &wx, &wy );
 
  593                                                    wl_fixed_from_int( aY + wy ) );
 
  596    wl_display_roundtrip( wldisp ); 
 
  597    gtk_widget_queue_draw( aWidget ); 
 
  600    return s_wl_locked_flag;
 
  606    wxLogTrace( 
traceWayland, wxS( 
"InfiniteDragPrepareWindow" ) );
 
  608    GtkWidget*  widget = 
static_cast<GtkWidget*
>( aWindow->GetHandle() );
 
  609    GdkDisplay* disp = gtk_widget_get_display( widget );
 
  611    if( GDK_IS_WAYLAND_DISPLAY( disp ) )
 
  613        if( s_wl_confined_pointer != NULL )
 
  618        GdkSeat*   seat = gdk_display_get_default_seat( disp );
 
  619        GdkDevice* ptrdev = gdk_seat_get_pointer( seat );
 
  620        GdkWindow* win = aWindow->GTKGetDrawingWindow();
 
  622        wl_display* wldisp = gdk_wayland_display_get_wl_display( disp );
 
  623        wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( win );
 
  624        wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev );
 
  626        initialize_wayland( wldisp );
 
  628        gint x, y, width, height;
 
  629        gdk_window_get_geometry( gdk_window_get_toplevel( win ), &x, &y, &width, &height );
 
  631        wxLogTrace( 
traceWayland, wxS( 
"Confine region: %d %d %d %d" ), x, y, width, height );
 
  633        s_wl_confinement_region = wl_compositor_create_region( s_wl_compositor );
 
  634        wl_region_add( s_wl_confinement_region, x, y, width, height );
 
  637                s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region,
 
  643        wl_display_roundtrip( wldisp );
 
  645    else if( wxGetEnv( wxT( 
"WAYLAND_DISPLAY" ), 
nullptr ) )
 
  657    wxLogTrace( 
traceWayland, wxS( 
"InfiniteDragReleaseWindow" ) );
 
  659    if( s_wl_confined_pointer )
 
  662        s_wl_confined_pointer = NULL;
 
  665    if( s_wl_confinement_region )
 
  667        wl_region_destroy( s_wl_confinement_region );
 
  668        s_wl_confinement_region = NULL;
 
  679    return !wxGetEnv( wxT( 
"WAYLAND_DISPLAY" ), 
nullptr );
 
 
  691    return wxGetMousePosition();
 
 
static void zwp_confined_pointer_v1_destroy(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)
Destroy the confined pointer object.
 
static int zwp_confined_pointer_v1_add_listener(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, const struct zwp_confined_pointer_v1_listener *listener, void *data)
 
static void zwp_locked_pointer_v1_set_cursor_position_hint(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, wl_fixed_t surface_x, wl_fixed_t surface_y)
Set the cursor position hint relative to the top left corner of the surface.
 
static int zwp_locked_pointer_v1_add_listener(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, const struct zwp_locked_pointer_v1_listener *listener, void *data)
 
static void zwp_locked_pointer_v1_destroy(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)
Destroy the locked pointer object.
 
static struct zwp_locked_pointer_v1 * zwp_pointer_constraints_v1_lock_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)
The lock_pointer request lets the client request to disable movements of the virtual pointer (i....
 
static struct zwp_confined_pointer_v1 * zwp_pointer_constraints_v1_confine_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)
The confine_pointer request lets the client request to confine the pointer cursor to a given region.
 
@ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT
the pointer constraint is defunct once deactivated
 
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
 
const struct wl_interface zwp_pointer_constraints_v1_interface
 
static void disable_area_apply_attributes_cb(GtkWidget *pItem, gpointer userdata)
The following two functions are based on the "hack" contained in the attached patch at https://gitlab...
 
const wxString traceWayland