KiCad PCB EDA Suite
Loading...
Searching...
No Matches
wxgtk/ui.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Ian McInerney <Ian.S.McInerney at ieee.org>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <kiplatform/ui.h>
22
23#include <wx/choice.h>
24#include <wx/dialog.h>
25#include <wx/nonownedwnd.h>
26#include <wx/settings.h>
27#include <wx/window.h>
28#include <wx/log.h>
29
30#include <gtk/gtk.h>
31#include <gdk/gdk.h>
32
33#ifdef GDK_WINDOWING_X11
34#include <gdk/gdkx.h>
35#endif
36
37#ifdef GDK_WINDOWING_WAYLAND
38#include <gdk/gdkwayland.h>
39#endif
40
41#ifdef KICAD_WAYLAND
43#endif
44
45// Set WXTRACE=KICAD_WAYLAND to see logs
46const wxString traceWayland = wxS( "KICAD_WAYLAND" );
47
48
50{
51 wxColour bg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
52
53 // Weighted W3C formula
54 double brightness = ( bg.Red() / 255.0 ) * 0.299 +
55 ( bg.Green() / 255.0 ) * 0.587 +
56 ( bg.Blue() / 255.0 ) * 0.117;
57
58 return brightness < 0.5;
59}
60
61
63{
64 return wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
65}
66
67
68void KIPLATFORM::UI::GetInfoBarColours( wxColour& aFgColour, wxColour& aBgColour )
69{
70 // The GTK3.24 way of getting the colours is to use the style context
71 // Earlier GTKs should be able to use the system settings
72#if( GTK_CHECK_VERSION( 3, 24, 0 ) )
73 GdkRGBA* rgba;
74 GtkWidgetPath* path = gtk_widget_path_new();
75 GtkStyleContext* sc = gtk_style_context_new();
76
77 gtk_widget_path_append_type( path, GTK_TYPE_WINDOW );
78 gtk_widget_path_iter_set_object_name( path, -1, "infobar" );
79 gtk_widget_path_iter_add_class( path, -1, "info" );
80
81 gtk_style_context_set_path( sc, path );
82 gtk_style_context_set_state( sc, GTK_STATE_FLAG_NORMAL );
83
84 gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "background-color", &rgba, NULL );
85 aBgColour = wxColour( *rgba );
86 gdk_rgba_free( rgba );
87
88 gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "color", &rgba, NULL );
89 aFgColour = wxColour( *rgba );
90 gdk_rgba_free( rgba );
91
92 // Some GTK themes use the plain infobar style, but if they don't, the background alpha
93 // is generally 0. In this case, try the revealer and box as these are used for Adwaita
94 // and other themes.
95 if( aBgColour.Alpha() == 0 )
96 {
97 gtk_widget_path_append_type( path, G_TYPE_NONE );
98 gtk_widget_path_iter_set_object_name( path, -1, "revealer" );
99 gtk_widget_path_append_type( path, G_TYPE_NONE );
100 gtk_widget_path_iter_set_object_name( path, -1, "box" );
101
102 gtk_style_context_set_path( sc, path );
103 gtk_style_context_set_state( sc, GTK_STATE_FLAG_NORMAL );
104
105 gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "background-color", &rgba, NULL );
106 aBgColour = wxColour( *rgba );
107 gdk_rgba_free( rgba );
108
109 gtk_style_context_get( sc, GTK_STATE_FLAG_NORMAL, "color", &rgba, NULL );
110 aFgColour = wxColour( *rgba );
111 gdk_rgba_free( rgba );
112 }
113
114 gtk_widget_path_free( path );
115 g_object_unref( sc );
116
117#else
118 aBgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK );
119 aFgColour = wxSystemSettings::GetColour( wxSYS_COLOUR_INFOTEXT );
120#endif
121
122}
123
124
125void KIPLATFORM::UI::ForceFocus( wxWindow* aWindow )
126{
127 aWindow->SetFocus();
128
129 // On GTK, SetFocus() on a dialog may not be sufficient to receive keyboard events
130 // (like ESC for closing). We need to ensure the window is presented and active.
131 // Find the top-level window and present it to ensure keyboard focus.
132 wxWindow* tlw = aWindow;
133
134 while( tlw && !tlw->IsTopLevel() )
135 tlw = tlw->GetParent();
136
137 if( tlw )
138 {
139 GtkWidget* widget = static_cast<GtkWidget*>( tlw->GetHandle() );
140
141 if( widget && GTK_IS_WINDOW( widget ) )
142 gtk_window_present( GTK_WINDOW( widget ) );
143 }
144}
145
146
147bool KIPLATFORM::UI::IsWindowActive( wxWindow* aWindow )
148{
149 if( !aWindow )
150 return false;
151
152 GtkWindow* window = GTK_WINDOW( aWindow->GetHandle() );
153
154 if( window )
155 return gtk_window_is_active( window );
156
157 // We shouldn't really ever reach this point
158 return false;
159}
160
161
162void KIPLATFORM::UI::EnsureVisible( wxWindow* aWindow )
163{
164 // Not needed on this platform
165}
166
167
168void KIPLATFORM::UI::ReparentModal( wxNonOwnedWindow* aWindow )
169{
170 // Not needed on this platform
171}
172
173
174void KIPLATFORM::UI::ReparentWindow( wxNonOwnedWindow* aWindow, wxTopLevelWindow* aParent )
175{
176 // Not needed on this platform (only relevant for macOS child window ordering)
177}
178
179
181{
182 // Not needed on this platform
183}
184
185
186bool KIPLATFORM::UI::IsStockCursorOk( wxStockCursor aCursor )
187{
188 switch( aCursor )
189 {
190 case wxCURSOR_BULLSEYE:
191 case wxCURSOR_HAND:
192 case wxCURSOR_ARROW:
193 case wxCURSOR_BLANK:
194 return true;
195 default:
196 return false;
197 }
198}
199
200
209static void disable_area_apply_attributes_cb( GtkWidget* pItem, gpointer userdata )
210{
211 // GTK needs this enormous chain to get the actual type of item that we want
212 GtkMenuItem* pMenuItem = GTK_MENU_ITEM( pItem );
213 GtkWidget* child = gtk_bin_get_child( GTK_BIN( pMenuItem ) );
214 GtkCellView* pCellView = GTK_CELL_VIEW( child );
215 GtkCellLayout* pCellLayout = GTK_CELL_LAYOUT( pCellView );
216 GtkCellArea* pCellArea = gtk_cell_layout_get_area( pCellLayout );
217
218 g_signal_handlers_block_matched( pCellArea, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, userdata );
219}
220
221
222void KIPLATFORM::UI::LargeChoiceBoxHack( wxChoice* aChoice )
223{
224 AtkObject* atkObj = gtk_combo_box_get_popup_accessible( GTK_COMBO_BOX( aChoice->m_widget ) );
225
226 if( !atkObj || !GTK_IS_ACCESSIBLE( atkObj ) )
227 return;
228
229 GtkWidget* widget = gtk_accessible_get_widget( GTK_ACCESSIBLE( atkObj ) );
230
231 if( !widget || !GTK_IS_MENU( widget ) )
232 return;
233
234 GtkMenu* menu = GTK_MENU( widget );
235
236 gtk_container_foreach( GTK_CONTAINER( menu ), disable_area_apply_attributes_cb, menu );
237}
238
239
240void KIPLATFORM::UI::EllipsizeChoiceBox( wxChoice* aChoice )
241{
242 // This function is based on the code inside the function post_process_ui in
243 // gtkfilechooserwidget.c
244 GList* cells = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( aChoice->m_widget ) );
245
246 if( !cells )
247 return;
248
249 GtkCellRenderer* cell = (GtkCellRenderer*) cells->data;
250
251 if( !cell )
252 return;
253
254 g_object_set( G_OBJECT( cell ), "ellipsize", PANGO_ELLIPSIZE_END, nullptr );
255
256 // Only the list of cells must be freed, the renderer isn't ours to free
257 g_list_free( cells );
258}
259
260
261double KIPLATFORM::UI::GetPixelScaleFactor( const wxWindow* aWindow )
262{
263 double val = 1.0;
264
265 GtkWidget* widget = static_cast<GtkWidget*>( aWindow->GetHandle() );
266
267 if( widget && gtk_check_version( 3, 10, 0 ) == nullptr )
268 val = gtk_widget_get_scale_factor( widget );
269
270 return val;
271}
272
273
274double KIPLATFORM::UI::GetContentScaleFactor( const wxWindow* aWindow )
275{
276 // TODO: Do we need something different here?
277 return GetPixelScaleFactor( aWindow );
278}
279
280
281wxSize KIPLATFORM::UI::GetUnobscuredSize( const wxWindow* aWindow )
282{
283 return wxSize( aWindow->GetSize().GetX() - wxSystemSettings::GetMetric( wxSYS_VSCROLL_X ),
284 aWindow->GetSize().GetY() - wxSystemSettings::GetMetric( wxSYS_HSCROLL_Y ) );
285}
286
287
288void KIPLATFORM::UI::SetOverlayScrolling( const wxWindow* aWindow, bool overlay )
289{
290 gtk_scrolled_window_set_overlay_scrolling( GTK_SCROLLED_WINDOW( aWindow->GetHandle() ),
291 overlay );
292}
293
294
296{
297 gboolean allowed = 1;
298
299 g_object_get( gtk_settings_get_default(), "gtk-menu-images", &allowed, NULL );
300
301 return !!allowed;
302}
303
304
305#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND )
306
307static bool wayland_warp_pointer( GtkWidget* aWidget, GdkDisplay* aDisplay, GdkWindow* aWindow,
308 GdkDevice* aPtrDev, int aX, int aY );
309
310// GDK doesn't know if we've moved the cursor using Wayland pointer constraints.
311// So emulate the actual position here
312static wxPoint s_warped_from;
313static wxPoint s_warped_to;
314
316{
317 wxPoint wx_pos = wxGetMousePosition();
318
319 if( wx_pos == s_warped_from )
320 {
321 wxLogTrace( traceWayland, wxS( "Faked mouse pos %d %d -> %d %d" ), wx_pos.x, wx_pos.y,
322 s_warped_to.x, s_warped_to.y );
323
324 return s_warped_to;
325 }
326 else
327 {
328 // Mouse has moved
329 s_warped_from = wxPoint();
330 s_warped_to = wxPoint();
331 }
332
333 return wx_pos;
334}
335
336#endif
337
338
339bool KIPLATFORM::UI::WarpPointer( wxWindow* aWindow, int aX, int aY )
340{
341 if( !wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr ) )
342 {
343 aWindow->WarpPointer( aX, aY );
344 return true;
345 }
346 else
347 {
348 GtkWidget* widget = static_cast<GtkWidget*>( aWindow->GetHandle() );
349
350 GdkDisplay* disp = gtk_widget_get_display( widget );
351 GdkSeat* seat = gdk_display_get_default_seat( disp );
352 GdkDevice* ptrdev = gdk_seat_get_pointer( seat );
353
354#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND )
355 if( GDK_IS_WAYLAND_DISPLAY( disp ) )
356 {
357 wxPoint initialPos = wxGetMousePosition();
358 GdkWindow* win = aWindow->GTKGetDrawingWindow();
359
360 if( wayland_warp_pointer( widget, disp, win, ptrdev, aX, aY ) )
361 {
362 s_warped_from = initialPos;
363 s_warped_to = aWindow->ClientToScreen( wxPoint( aX, aY ) );
364
365 wxLogTrace( traceWayland, wxS( "Set warped from %d %d to %d %d" ), s_warped_from.x,
366 s_warped_from.y, s_warped_to.x, s_warped_to.y );
367
368 return true;
369 }
370
371 wxLogTrace( traceWayland, wxS( "*** Warp to %d %d failed ***" ), aX, aY );
372
373 return false;
374 }
375#endif
376#ifdef GDK_WINDOWING_X11
377 if( GDK_IS_X11_DISPLAY( disp ) )
378 {
379 GdkWindow* win = gdk_device_get_window_at_position( ptrdev, nullptr, nullptr );
380 GdkCursor* blank_cursor = gdk_cursor_new_for_display( disp, GDK_BLANK_CURSOR );
381 GdkCursor* cur_cursor = gdk_window_get_cursor( win );
382
383 if( cur_cursor )
384 g_object_ref( cur_cursor );
385
386 gdk_window_set_cursor( win, blank_cursor );
387 aWindow->WarpPointer( aX, aY );
388 gdk_window_set_cursor( win, cur_cursor );
389
390 if( cur_cursor )
391 g_object_unref( cur_cursor );
392
393 if( blank_cursor )
394 g_object_unref( blank_cursor );
395
396 return true;
397 }
398#endif
399 }
400
401 return false;
402}
403
404
405void KIPLATFORM::UI::ImmControl( wxWindow* aWindow, bool aEnable )
406{
407}
408
409
411{
412 wxWindowGTK* win = static_cast<wxWindowGTK*>( aWindow );
413 if( win )
414 {
415 GtkIMContext* imContext = win->m_imContext;
416 if( imContext )
417 {
418 gtk_im_context_focus_out( imContext );
419 }
420 }
421}
422
423
424void KIPLATFORM::UI::SetFloatLevel( wxWindow* aWindow )
425{
426}
427
428//
429// **** Wayland hacks ahead ****
430//
431
432#if defined( GDK_WINDOWING_WAYLAND ) && defined( KICAD_WAYLAND )
433
434static bool s_wl_initialized = false;
435static struct wl_compositor* s_wl_compositor = NULL;
436static struct zwp_pointer_constraints_v1* s_wl_pointer_constraints = NULL;
437static struct zwp_confined_pointer_v1* s_wl_confined_pointer = NULL;
438static struct wl_region* s_wl_confinement_region = NULL;
439static bool s_wl_locked_flag = false;
440
441static void handle_global( void* data, struct wl_registry* registry, uint32_t name,
442 const char* interface, uint32_t version )
443{
444 wxLogTrace( traceWayland, "handle_global received %s name %u version %u", interface,
445 (unsigned int) name, (unsigned int) version );
446
447 if( strcmp( interface, wl_compositor_interface.name ) == 0 )
448 {
449 s_wl_compositor = static_cast<wl_compositor*>(
450 wl_registry_bind( registry, name, &wl_compositor_interface, version ) );
451 }
452 else if( strcmp( interface, zwp_pointer_constraints_v1_interface.name ) == 0 )
453 {
454 s_wl_pointer_constraints = static_cast<zwp_pointer_constraints_v1*>( wl_registry_bind(
455 registry, name, &zwp_pointer_constraints_v1_interface, version ) );
456 }
457}
458
459static void handle_global_remove( void*, struct wl_registry*, uint32_t name )
460{
461 wxLogTrace( traceWayland, "handle_global_remove name %u", (unsigned int) name );
462}
463
464static const struct wl_registry_listener registry_listener = {
465 .global = handle_global,
466 .global_remove = handle_global_remove,
467};
468
469static void confined_handler( void* data, struct zwp_confined_pointer_v1* zwp_confined_pointer_v1 )
470{
471 wxLogTrace( traceWayland, wxS( "Pointer confined" ) );
472}
473
474static void unconfined_handler( void* data,
475 struct zwp_confined_pointer_v1* zwp_confined_pointer_v1 )
476{
477 wxLogTrace( traceWayland, wxS( "Pointer unconfined" ) );
478}
479
480static const struct zwp_confined_pointer_v1_listener confined_pointer_listener = {
481 .confined = confined_handler,
482 .unconfined = unconfined_handler
483};
484
485static void locked_handler( void* data, struct zwp_locked_pointer_v1* zwp_locked_pointer_v1 )
486{
487 s_wl_locked_flag = true;
488 wxLogTrace( traceWayland, wxS( "Pointer locked" ) );
489}
490
491static void unlocked_handler( void* data, struct zwp_locked_pointer_v1* zwp_locked_pointer_v1 )
492{
493 wxLogTrace( traceWayland, wxS( "Pointer unlocked" ) );
494}
495
496static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
497 .locked = locked_handler,
498 .unlocked = unlocked_handler
499};
500
501
505static void initialize_wayland( wl_display* wldisp )
506{
507 if( s_wl_initialized )
508 {
509 return;
510 }
511
512 struct wl_registry* registry = wl_display_get_registry( wldisp );
513 wl_registry_add_listener( registry, &registry_listener, NULL );
514 wl_display_roundtrip( wldisp );
515 s_wl_initialized = true;
516}
517
518
519struct zwp_locked_pointer_v1* s_wl_locked_pointer = NULL;
520
521static int s_after_paint_handler_id = 0;
522
523static void on_frame_clock_after_paint( GdkFrameClock* clock, GtkWidget* widget )
524{
525 if( s_wl_locked_pointer )
526 {
527 zwp_locked_pointer_v1_destroy( s_wl_locked_pointer );
528 s_wl_locked_pointer = NULL;
529
530 wxLogTrace( traceWayland, wxS( "after-paint: locked_pointer destroyed" ) );
531
532 g_signal_handler_disconnect( (gpointer) clock, s_after_paint_handler_id );
533 s_after_paint_handler_id = 0;
534
535 // restore confinement
536 if( s_wl_confinement_region != NULL )
537 {
538 wxLogTrace( traceWayland, wxS( "after-paint: Restoring confinement" ) );
539
540 GdkDisplay* disp = gtk_widget_get_display( widget );
541 GdkSeat* seat = gdk_display_get_default_seat( disp );
542 GdkDevice* ptrdev = gdk_seat_get_pointer( seat );
543 GdkWindow* window = gtk_widget_get_window( widget );
544
545 wl_display* wldisp = gdk_wayland_display_get_wl_display( disp );
546 wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( window );
547 wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev );
548
549 s_wl_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
550 s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region,
552
553 wl_display_roundtrip( wldisp );
554 }
555 }
556}
557
558
559static bool wayland_warp_pointer( GtkWidget* aWidget, GdkDisplay* aDisplay, GdkWindow* aWindow,
560 GdkDevice* aPtrDev, int aX, int aY )
561{
562 wl_display* wldisp = gdk_wayland_display_get_wl_display( aDisplay );
563 wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( aWindow );
564 wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( aPtrDev );
565
566 if( s_after_paint_handler_id )
567 {
568 // Previous paint not done yet
569 wxLogTrace( traceWayland, wxS( "Not warping: after-paint pending" ) );
570 return false;
571 }
572
573 initialize_wayland( wldisp );
574
575 if( s_wl_locked_pointer )
576 {
577 // This shouldn't happen but let's be safe
578 wxLogTrace( traceWayland, wxS( "** Destroying previous locked_pointer **" ) );
579 zwp_locked_pointer_v1_destroy( s_wl_locked_pointer );
580 wl_display_roundtrip( wldisp );
581 s_wl_locked_pointer = NULL;
582 }
583
584 // wl_surface_commit causes an assert on GNOME, but has to be called on KDE
585 // before destroying the locked pointer, so wait until GDK commits the surface.
586 GdkFrameClock* frame_clock = gdk_window_get_frame_clock( aWindow );
587 s_after_paint_handler_id = g_signal_connect_after(
588 frame_clock, "after-paint", G_CALLBACK( on_frame_clock_after_paint ), aWidget );
589
590 // temporary disable confinement to allow pointer warping
591 if( s_wl_confinement_region && s_wl_confined_pointer )
592 {
593 zwp_confined_pointer_v1_destroy( s_wl_confined_pointer );
594 wl_display_roundtrip( wldisp );
595 s_wl_confined_pointer = NULL;
596 }
597
598 s_wl_locked_flag = false;
599
600 s_wl_locked_pointer =
601 zwp_pointer_constraints_v1_lock_pointer( s_wl_pointer_constraints, wlsurf, wlptr, NULL,
603
604 zwp_locked_pointer_v1_add_listener(s_wl_locked_pointer, &locked_pointer_listener, NULL);
605
606 gint wx, wy;
607 gtk_widget_translate_coordinates( aWidget, gtk_widget_get_toplevel( aWidget ), 0, 0, &wx, &wy );
608
609 zwp_locked_pointer_v1_set_cursor_position_hint( s_wl_locked_pointer, wl_fixed_from_int( aX + wx ),
610 wl_fixed_from_int( aY + wy ) );
611
612 // Don't call wl_surface_commit, wait for GDK because of an assert on GNOME.
613 wl_display_roundtrip( wldisp ); // To receive "locked" event.
614 gtk_widget_queue_draw( aWidget ); // Needed on some GNOME environment to trigger
615 // the "after-paint" event handler.
616
617 return s_wl_locked_flag;
618}
619
620
621bool KIPLATFORM::UI::InfiniteDragPrepareWindow( wxWindow* aWindow )
622{
623 wxLogTrace( traceWayland, wxS( "InfiniteDragPrepareWindow" ) );
624
625 GtkWidget* widget = static_cast<GtkWidget*>( aWindow->GetHandle() );
626 GdkDisplay* disp = gtk_widget_get_display( widget );
627
628 if( GDK_IS_WAYLAND_DISPLAY( disp ) )
629 {
630 if( s_wl_confined_pointer != NULL )
631 {
633 }
634
635 GdkSeat* seat = gdk_display_get_default_seat( disp );
636 GdkDevice* ptrdev = gdk_seat_get_pointer( seat );
637 GdkWindow* win = aWindow->GTKGetDrawingWindow();
638
639 wl_display* wldisp = gdk_wayland_display_get_wl_display( disp );
640 wl_surface* wlsurf = gdk_wayland_window_get_wl_surface( win );
641 wl_pointer* wlptr = gdk_wayland_device_get_wl_pointer( ptrdev );
642
643 initialize_wayland( wldisp );
644
645 gint x, y, width, height;
646 gdk_window_get_geometry( gdk_window_get_toplevel( win ), &x, &y, &width, &height );
647
648 wxLogTrace( traceWayland, wxS( "Confine region: %d %d %d %d" ), x, y, width, height );
649
650 s_wl_confinement_region = wl_compositor_create_region( s_wl_compositor );
651 wl_region_add( s_wl_confinement_region, x, y, width, height );
652
653 s_wl_confined_pointer = zwp_pointer_constraints_v1_confine_pointer(
654 s_wl_pointer_constraints, wlsurf, wlptr, s_wl_confinement_region,
656
657 zwp_confined_pointer_v1_add_listener( s_wl_confined_pointer, &confined_pointer_listener,
658 NULL );
659
660 wl_display_roundtrip( wldisp );
661 }
662 else if( wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr ) )
663 {
664 // Not working under XWayland
665 return false;
666 }
667
668 return true;
669};
670
671
673{
674 wxLogTrace( traceWayland, wxS( "InfiniteDragReleaseWindow" ) );
675
676 if( s_wl_confined_pointer )
677 {
678 zwp_confined_pointer_v1_destroy( s_wl_confined_pointer );
679 s_wl_confined_pointer = NULL;
680 }
681
682 if( s_wl_confinement_region )
683 {
684 wl_region_destroy( s_wl_confinement_region );
685 s_wl_confinement_region = NULL;
686 }
687};
688
689
690#else // No Wayland support
691
692
694{
695 // Not working under XWayland
696 return !wxGetEnv( wxT( "WAYLAND_DISPLAY" ), nullptr );
697};
698
699
701{
702 // Not needed on X11
703};
704
705
707{
708 return wxGetMousePosition();
709}
710
711void KIPLATFORM::UI::ReleaseChildWindow( wxNonOwnedWindow* aWindow )
712{
713 // Not needed on this platform
714}
715
716
718{
719 GtkWidget* widget = static_cast<GtkWidget*>( aDialog->GetHandle() );
720
721 if( widget && GTK_IS_FILE_CHOOSER( widget ) )
722 gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( widget ), FALSE );
723}
724
725#endif
const char * name
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
bool AllowIconsInMenus()
If the user has disabled icons system-wide, we check that here.
Definition wxgtk/ui.cpp:295
void SetFloatLevel(wxWindow *aWindow)
Intended to set the floating window level in macOS on a window.
Definition wxgtk/ui.cpp:424
void GetInfoBarColours(wxColour &aFGColour, wxColour &aBGColour)
Return the background and foreground colors for info bars in the current scheme.
Definition wxgtk/ui.cpp:68
void ReparentWindow(wxNonOwnedWindow *aWindow, wxTopLevelWindow *aParent)
Definition wxgtk/ui.cpp:174
void ReleaseChildWindow(wxNonOwnedWindow *aWindow)
Release a modal window's parent-child relationship with its parent window.
Definition wxgtk/ui.cpp:711
void EllipsizeChoiceBox(wxChoice *aChoice)
Configure a wxChoice control to ellipsize the shown text in the button with the ellipses placed at th...
Definition wxgtk/ui.cpp:240
void FixupCancelButtonCmdKeyCollision(wxWindow *aWindow)
Definition wxgtk/ui.cpp:180
void SetOverlayScrolling(const wxWindow *aWindow, bool overlay)
Used to set overlay/non-overlay scrolling mode in a window.
Definition wxgtk/ui.cpp:288
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:706
void ImmControl(wxWindow *aWindow, bool aEnable)
Configures the IME mode of a given control handle.
Definition wxgtk/ui.cpp:405
double GetPixelScaleFactor(const wxWindow *aWindow)
Tries to determine the pixel scaling factor currently in use for the window.
Definition wxgtk/ui.cpp:261
void InfiniteDragReleaseWindow()
On Wayland, allows the cursor to freely move again after a drag (see InfiniteDragPrepareWindow).
Definition wxgtk/ui.cpp:700
void EnsureVisible(wxWindow *aWindow)
Ensure that a window is visible on the screen.
Definition wxgtk/ui.cpp:162
bool IsStockCursorOk(wxStockCursor aCursor)
Checks if we designated a stock cursor for this OS as "OK" or else we may need to load a custom one.
Definition wxgtk/ui.cpp:186
double GetContentScaleFactor(const wxWindow *aWindow)
Tries to determine the content scaling factor currently in use for the window.
Definition wxgtk/ui.cpp:274
void ImeNotifyCancelComposition(wxWindow *aWindow)
Asks the IME to cancel.
Definition wxgtk/ui.cpp:410
void LargeChoiceBoxHack(wxChoice *aChoice)
Configure a wxChoice control to support a lot of entries by disabling functionality that makes adding...
Definition wxgtk/ui.cpp:222
bool WarpPointer(wxWindow *aWindow, int aX, int aY)
Move the mouse cursor to a specific position relative to the window.
Definition wxgtk/ui.cpp:339
wxColour GetDialogBGColour()
Definition wxgtk/ui.cpp:62
bool IsWindowActive(wxWindow *aWindow)
Check to see if the given window is the currently active window (e.g.
Definition wxgtk/ui.cpp:147
wxSize GetUnobscuredSize(const wxWindow *aWindow)
Tries to determine the size of the viewport of a scrollable widget (wxDataViewCtrl,...
Definition wxgtk/ui.cpp:281
void ForceFocus(wxWindow *aWindow)
Pass the current focus to the window.
Definition wxgtk/ui.cpp:125
bool InfiniteDragPrepareWindow(wxWindow *aWindow)
On Wayland, restricts the pointer movement to a rectangle slightly bigger than the given wxWindow.
Definition wxgtk/ui.cpp:693
void ReparentModal(wxNonOwnedWindow *aWindow)
Move a window's parent to be the top-level window and force the window to be on top.
Definition wxgtk/ui.cpp:168
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:49
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
std::shared_ptr< PNS_LOG_VIEWER_OVERLAY > overlay
std::string path
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...
Definition wxgtk/ui.cpp:209
const wxString traceWayland
Definition wxgtk/ui.cpp:46