ultimatepp/uppsrc/CtrlCore/GtkCapture.cpp
2026-01-16 19:26:25 +01:00

132 lines
2.7 KiB
C++

#include <CtrlCore/CtrlCore.h>
#ifdef GUI_GTK
namespace Upp {
#define LLOG(x) // DLOG(x)
Ptr<Ctrl> Ctrl::grabwindow;
Ptr<Ctrl> Ctrl::grabpopup;
#if GTK_CHECK_VERSION(3, 20, 0)
GdkSeat *Ctrl::GetSeat()
{
return gdk_display_get_default_seat(gdk_display_get_default());
}
#endif
GdkDevice *Ctrl::GetMouseDevice()
{
#if GTK_CHECK_VERSION(3, 20, 0)
return gdk_seat_get_pointer(GetSeat());
#else
return gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default()));
#endif
}
// (*) it is not really possible to do system-wide grab as there is conflict with csd
// so we depend on gtk doing automatic grab when mouse is down
bool Ctrl::MouseIsGrabbed()
{
if(grabwindow && grabwindow->top && grabwindow->utop->csd) // (*)
return true;
return gdk_display_device_is_grabbed(gdk_display_get_default(), GetMouseDevice());
}
bool Ctrl::GrabMouse()
{
if(top && utop->csd) // (*)
return true;
return
#if GTK_CHECK_VERSION(3, 20, 0)
gdk_seat_grab(GetSeat(), gdk(), GDK_SEAT_CAPABILITY_ALL_POINTING, true, NULL, NULL, NULL, 0)
#else
gdk_device_grab(GetMouseDevice(), gdk(), GDK_OWNERSHIP_APPLICATION, true, (GdkEventMask)0, NULL, GDK_CURRENT_TIME)
#endif
== GDK_GRAB_SUCCESS;
}
void Ctrl::UngrabMouse()
{
if(grabwindow && grabwindow->top && grabwindow->utop->csd) // (*)
return;
#if GTK_CHECK_VERSION(3, 20, 0)
gdk_seat_ungrab(GetSeat());
#else
gdk_device_ungrab(GetMouseDevice(), GDK_CURRENT_TIME);
#endif
}
void Ctrl::StopGrabPopup()
{
if(grabpopup && MouseIsGrabbed()) {
UngrabMouse();
grabpopup = NULL;
}
}
void Ctrl::StartGrabPopup()
{
if(activePopup.GetCount() && !grabpopup) {
Ctrl *w = activePopup[0];
if(w && w->IsOpen()) {
ReleaseWndCapture0();
// NOTE: On Wayland GrabMouse() is broken and shouldn't be used.
if(IsWayland() || w->GrabMouse()) {
grabpopup = w;
}
}
}
}
bool Ctrl::SetWndCapture()
{
GuiLock __;
ASSERT(IsMainThread());
LLOG("SetWndCapture " << Name());
if(!IsOpen())
return false;
StopGrabPopup();
ReleaseWndCapture();
if(GrabMouse()) {
grabwindow = this;
return true;
}
return false;
}
bool Ctrl::ReleaseWndCapture0()
{
GuiLock __;
ASSERT(IsMainThread());
if(grabwindow) {
UngrabMouse();
grabwindow = NULL;
StartGrabPopup();
return true;
}
return false;
}
bool Ctrl::ReleaseWndCapture()
{
return ReleaseWndCapture0();
}
bool Ctrl::HasWndCapture() const
{
GuiLock __;
return this == grabwindow && grabwindow->IsOpen() && MouseIsGrabbed();
}
void Ctrl::CaptureSync()
{
if(grabwindow && grabwindow->IsOpen() && !MouseIsGrabbed() && !grabwindow->GrabMouse())
grabwindow = NULL;
}
};
#endif