You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
15 KiB
426 lines
15 KiB
/***************************************************************************
|
|
x11.cpp
|
|
-------
|
|
begin : Wed Feb 26 2003
|
|
copyright : (C) 2003-2007 by kiriuja
|
|
email : http://kplayer.sourceforge.net/email.html
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
***************************************************************************/
|
|
|
|
#include <kdebug.h>
|
|
#include <X11/Xlib.h>
|
|
|
|
#ifdef DEBUG
|
|
kdbgstream kdDebugTime (void);
|
|
#define DEBUG_KPLAYER_GRAB
|
|
//#define DEBUG_KPLAYER_PROPERTY
|
|
//#define DEBUG_KPLAYER_X11
|
|
//#define DEBUG_KPLAYER_FOCUS
|
|
//#define DEBUG_KPLAYER_KEY
|
|
//#define DEBUG_KPLAYER_RESIZE
|
|
//#define DEBUG_KPLAYER_CLIENT
|
|
#endif
|
|
|
|
#ifdef DEBUG_KPLAYER_CLIENT
|
|
extern Atom qt_xdnd_position;
|
|
extern Atom qt_xdnd_status;
|
|
#endif
|
|
|
|
/*bool KPlayerX11TestGrab (Display* display, int winid)
|
|
{
|
|
if ( int status = XGrabPointer (display, winid, False,
|
|
(uint)(ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask),
|
|
GrabModeAsync, GrabModeAsync, None, None, CurrentTime) )
|
|
{
|
|
const char *s =
|
|
status == GrabNotViewable ? "GrabNotViewable" :
|
|
status == AlreadyGrabbed ? "AlreadyGrabbed" :
|
|
status == GrabFrozen ? "GrabFrozen" :
|
|
status == GrabInvalidTime ? "GrabInvalidTime" : "Unknown";
|
|
#ifdef DEBUG_KPLAYER_GRAB
|
|
kdDebugTime() << "Grab failed, status: " << s << "\n";
|
|
#endif
|
|
return false;
|
|
}
|
|
#define DEBUG_KPLAYER_GRAB
|
|
kdDebugTime() << "Grab succeeded\n";
|
|
#endif
|
|
XUngrabPointer (display, CurrentTime);
|
|
return true;
|
|
}*/
|
|
|
|
extern void KPlayerSetControlShiftState (bool control, bool shift);
|
|
extern void KPlayerWidgetResizeHandler (bool);
|
|
extern void KPlayerWidgetMapHandler (uint);
|
|
extern void KPlayerWidgetUnmapHandler (uint);
|
|
extern void KPlayerWindowStateChanged (uint);
|
|
|
|
typedef int (*QX11EventFilter) (XEvent*);
|
|
|
|
static QX11EventFilter PreviousX11EventFilter = 0;
|
|
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
|
|
const char* KPlayerX11EventTypeNames [LASTEvent] = {
|
|
"EVENT0",
|
|
"EVENT1",
|
|
"KeyPress",
|
|
"KeyRelease",
|
|
"ButtonPress",
|
|
"ButtonRelease",
|
|
"MotionNotify",
|
|
"EnterNotify",
|
|
"LeaveNotify",
|
|
"FocusIn",
|
|
"FocusOut",
|
|
"KeymapNotify",
|
|
"Expose",
|
|
"GraphicsExpose",
|
|
"NoExpose",
|
|
"VisibilityNotify",
|
|
"CreateNotify",
|
|
"DestroyNotify",
|
|
"UnmapNotify",
|
|
"MapNotify",
|
|
"MapRequest",
|
|
"ReparentNotify",
|
|
"ConfigureNotify",
|
|
"ConfigureRequest",
|
|
"GravityNotify",
|
|
"ResizeRequest",
|
|
"CirculateNotify",
|
|
"CirculateRequest",
|
|
"PropertyNotify",
|
|
"SelectionClear",
|
|
"SelectionRequest",
|
|
"SelectionNotify",
|
|
"ColormapNotify",
|
|
"ClientMessage",
|
|
"MappingNotify"
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
|
|
const char* KPlayerX11EventModeNames [4] = {
|
|
"NotifyNormal",
|
|
"NotifyGrab",
|
|
"NotifyUngrab",
|
|
"NotifyWhileGrabbed"
|
|
};
|
|
|
|
const char* KPlayerX11EventDetailNames [8] = {
|
|
"NotifyAncestor",
|
|
"NotifyVirtual",
|
|
"NotifyInferior",
|
|
"NotifyNonlinear",
|
|
"NotifyNonlinearVirtual",
|
|
"NotifyPointer",
|
|
"NotifyPointerRoot",
|
|
"NotifyDetailNone"
|
|
};
|
|
|
|
#endif
|
|
|
|
int KPlayerX11EventFilter (XEvent* event)
|
|
{
|
|
#ifdef DEBUG_KPLAYER_X11
|
|
XAnyEvent* anyev = (XAnyEvent*) event;
|
|
kdDebugTime() << "X11 event " << KPlayerX11EventTypeNames [event -> type] << " " << anyev -> window
|
|
<< " " << anyev -> send_event << " " << anyev -> serial << "\n";
|
|
#endif
|
|
if ( event -> type == FocusIn || event -> type == FocusOut )
|
|
{
|
|
XFocusChangeEvent* ev = (XFocusChangeEvent*) event;
|
|
#ifdef DEBUG_KPLAYER_FOCUS
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> window << " "
|
|
<< ev -> send_event << " " << ev -> serial << " mode " << KPlayerX11EventModeNames [ev -> mode]
|
|
<< " detail " << KPlayerX11EventDetailNames [ev -> detail] << "\n";
|
|
#endif
|
|
if ( event -> type == FocusIn && ev -> mode == NotifyUngrab
|
|
|| event -> type == FocusOut && ev -> mode == NotifyGrab && ev -> detail == NotifyAncestor )
|
|
{
|
|
#ifdef DEBUG_KPLAYER_GRAB
|
|
kdDebugTime() << "Calling KPlayerWidgetResizeHandler (" << (ev -> mode == NotifyGrab) << ")\n";
|
|
#endif
|
|
KPlayerWidgetResizeHandler (ev -> mode == NotifyGrab);
|
|
}
|
|
}
|
|
else if ( event -> type == KeyPress || event -> type == KeyRelease )
|
|
{
|
|
XKeyEvent* ev = (XKeyEvent*) event;
|
|
#ifdef DEBUG_KPLAYER_KEY
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> window << " "
|
|
<< ev -> send_event << " " << ev -> serial << " root " << ev -> root << " subwindow "
|
|
<< ev -> subwindow << " " << ev -> x << "x" << ev -> y << " " << ev -> x_root << "x" << ev -> y_root
|
|
<< " keycode " << ev -> keycode << " state " << ev -> state << " same " << ev -> same_screen << "\n";
|
|
#endif
|
|
KPlayerSetControlShiftState ((ev -> state & ControlMask) == ControlMask, (ev -> state & ShiftMask) == ShiftMask);
|
|
if ( (ev -> state & ShiftMask) == ShiftMask && (ev -> state & (ControlMask | Mod1Mask)) != 0
|
|
&& ev -> keycode != 100 && ev -> keycode != 102
|
|
&& ((ev -> state & Mod1Mask) != Mod1Mask || ev -> keycode != 98 && ev -> keycode != 104) )
|
|
ev -> state &= ~ ShiftMask;
|
|
}
|
|
#ifdef DEBUG_KPLAYER_CLIENT
|
|
else if ( event -> type == ClientMessage && (event -> xclient.message_type == qt_xdnd_position
|
|
|| event -> xclient.message_type == qt_xdnd_status) )
|
|
{
|
|
XClientMessageEvent* ev = (XClientMessageEvent*) event;
|
|
kdDebugTime() << "X11 ClientMessage " << ev -> message_type << " " << ev -> window << " "
|
|
<< ev -> send_event << " " << ev -> serial << " format " << ev -> format << " window " << ev -> data.l[0]
|
|
<< " flags " << ev -> data.l[1] << " position " << ((ev -> data.l[2] & 0xffff0000) >> 16)
|
|
<< "x" << (ev -> data.l[2] & 0x0000ffff) << " size " << ((ev -> data.l[3] & 0xffff0000) >> 16)
|
|
<< "x" << (ev -> data.l[3] & 0x0000ffff) << " action " << ev -> data.l[4] << "\n";
|
|
}
|
|
#endif
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
else if ( event -> type == ConfigureNotify )
|
|
{
|
|
XConfigureEvent* ev = (XConfigureEvent*) event;
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> event
|
|
<< " " << ev -> window << " " << ev -> send_event << " " << ev -> serial
|
|
<< " " << ev -> x << "x" << ev -> y << " " << ev -> width << "x" << ev -> height
|
|
<< " border " << ev -> border_width << " above " << ev -> above << " override " << ev -> override_redirect << "\n";
|
|
}
|
|
else if ( event -> type == ConfigureRequest )
|
|
{
|
|
XConfigureRequestEvent* ev = (XConfigureRequestEvent*) event;
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> parent
|
|
<< " " << ev -> window << " " << ev -> send_event << " " << ev -> serial
|
|
<< " " << ev -> x << "x" << ev -> y << " " << ev -> width << "x" << ev -> height
|
|
<< " border " << ev -> border_width << " above " << ev -> above
|
|
<< " detail " << ev -> detail << " mask " << ev -> value_mask << "\n";
|
|
}
|
|
else if ( event -> type == ResizeRequest )
|
|
{
|
|
XResizeRequestEvent* ev = (XResizeRequestEvent*) event;
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type]
|
|
<< " " << ev -> window << " " << ev -> send_event << " " << ev -> serial
|
|
<< " " << ev -> width << "x" << ev -> height << "\n";
|
|
}
|
|
else if ( event -> type == ReparentNotify )
|
|
{
|
|
XReparentEvent* ev = (XReparentEvent*) event;
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> event
|
|
<< " " << ev -> window << " " << ev -> parent << " " << ev -> send_event << " " << ev -> serial
|
|
<< " " << ev -> x << "x" << ev -> y << " override " << ev -> override_redirect << "\n";
|
|
}
|
|
else if ( event -> type == MapNotify )
|
|
{
|
|
XMapEvent* ev = (XMapEvent*) event;
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> event << " " << ev -> window
|
|
<< " " << ev -> send_event << " " << ev -> serial << " override " << ev -> override_redirect << "\n";
|
|
}
|
|
#endif
|
|
else if ( event -> type == MapRequest )
|
|
{
|
|
XMapRequestEvent* ev = (XMapRequestEvent*) event;
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> parent
|
|
<< " " << ev -> window << " " << ev -> send_event << " " << ev -> serial << "\n";
|
|
#endif
|
|
KPlayerWidgetMapHandler (ev -> window);
|
|
}
|
|
else if ( event -> type == UnmapNotify )
|
|
{
|
|
XUnmapEvent* ev = (XUnmapEvent*) event;
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> event << " " << ev -> window
|
|
<< " " << ev -> send_event << " " << ev -> serial << " from configure " << ev -> from_configure << "\n";
|
|
#endif
|
|
KPlayerWidgetUnmapHandler (ev -> window);
|
|
}
|
|
else if ( event -> type == PropertyNotify )
|
|
{
|
|
XPropertyEvent* ev = (XPropertyEvent*) event;
|
|
#ifdef DEBUG_KPLAYER_PROPERTY
|
|
kdDebugTime() << "X11 " << KPlayerX11EventTypeNames [event -> type] << " " << ev -> send_event
|
|
<< " " << ev -> window << " " << ev -> atom << " " << ev -> time << " " << ev -> state << "\n";
|
|
#endif
|
|
char* propname = XGetAtomName (ev -> display, ev -> atom);
|
|
if ( propname )
|
|
{
|
|
if ( strcmp (propname, "_NET_WM_STATE") == 0 )
|
|
KPlayerWindowStateChanged (ev -> window);
|
|
#ifdef DEBUG_KPLAYER_PROPERTY
|
|
kdDebugTime() << "X11 property name " << propname << "\n";
|
|
#endif
|
|
}
|
|
#ifdef DEBUG_KPLAYER_PROPERTY
|
|
if ( ev -> state == PropertyNewValue )
|
|
{
|
|
Atom type;
|
|
int format;
|
|
unsigned long items, bytes;
|
|
unsigned char* data;
|
|
if ( XGetWindowProperty (ev -> display, ev -> window, ev -> atom, 0, 32, false, AnyPropertyType,
|
|
&type, &format, &items, &bytes, &data) == Success && type != None )
|
|
{
|
|
kdDebugTime() << "X11 property type " << type << " format " << format
|
|
<< " items " << items << " bytes " << bytes << "\n";
|
|
if ( data )
|
|
{
|
|
if ( format == 8 )
|
|
kdDebugTime() << "X11 property value " << data << "\n";
|
|
else if ( format == 16 )
|
|
{
|
|
short* sdata = (short*) data;
|
|
for ( unsigned long i = 0; i < items; ++ i )
|
|
kdDebugTime() << "X11 property value " << sdata[i] << "\n";
|
|
}
|
|
else if ( format == 32 )
|
|
if ( strcmp (propname, "_NET_SUPPORTED") == 0
|
|
|| strcmp (propname, "_NET_WM_WINDOW_TYPE") == 0
|
|
|| strcmp (propname, "_NET_WM_STATE") == 0
|
|
|| strcmp (propname, "_NET_WM_ALLOWED_ACTIONS") == 0 )
|
|
{
|
|
Atom* adata = (Atom*) data;
|
|
for ( unsigned long i = 0; i < items; ++ i )
|
|
{
|
|
char* atomname = XGetAtomName (ev -> display, adata[i]);
|
|
if ( atomname )
|
|
{
|
|
kdDebugTime() << "X11 property name " << atomname << "\n";
|
|
XFree (atomname);
|
|
}
|
|
else
|
|
kdDebugTime() << "X11 property value " << adata[i] << "\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long* ldata = (long*) data;
|
|
for ( unsigned long i = 0; i < items; ++ i )
|
|
kdDebugTime() << "X11 property value " << ldata[i] << "\n";
|
|
}
|
|
XFree (data);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if ( propname )
|
|
XFree (propname);
|
|
}
|
|
if ( PreviousX11EventFilter )
|
|
return PreviousX11EventFilter (event);
|
|
return 0;
|
|
}
|
|
|
|
Display* tqt_xdisplay (void);
|
|
extern Time tqt_x_time;
|
|
|
|
void KPlayerX11SetInputFocus (uint id)
|
|
{
|
|
XSetInputFocus (tqt_xdisplay(), id, RevertToNone, tqt_x_time);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11MapWindow (uint id)
|
|
{
|
|
XMapWindow (tqt_xdisplay(), id);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11UnmapWindow (uint id)
|
|
{
|
|
XUnmapWindow (tqt_xdisplay(), id);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11ClearExposeWindow (uint id)
|
|
{
|
|
XClearArea (tqt_xdisplay(), id, 0, 0, 0, 0, True);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11SendConfigureEvent (uint id, int w, int h)
|
|
{
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
kdDebugTime() << "KPlayerX11SendConfigureEvent " << id << " " << w << "x" << h << "\n";
|
|
#endif
|
|
XConfigureEvent event = { ConfigureNotify, 0, True, tqt_xdisplay(), id, id, 0, 0, w, h, 0, None, False };
|
|
XSendEvent (tqt_xdisplay(), event.event, True, StructureNotifyMask, (XEvent*) &event);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11SendConfigureEvent (uint id, int x, int y, int w, int h)
|
|
{
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
kdDebugTime() << "KPlayerX11SendConfigureEvent " << id << " " << x << "x" << y << " " << w << "x" << h << "\n";
|
|
#endif
|
|
XConfigureEvent event = { ConfigureNotify, 0, True, tqt_xdisplay(), id, id, x, y, w, h, 0, None, False };
|
|
XSendEvent (tqt_xdisplay(), event.event, True, StructureNotifyMask, (XEvent*) &event);
|
|
XFlush (tqt_xdisplay());
|
|
}
|
|
|
|
void KPlayerX11DiscardConfigureEvents (uint id)
|
|
{
|
|
XEvent event;
|
|
while ( XCheckTypedWindowEvent (tqt_xdisplay(), id, ConfigureNotify, &event) )
|
|
#ifdef DEBUG_KPLAYER_RESIZE
|
|
kdDebugTime() << "Discarded ConfigureEvent " << event.xconfigure.event << " " << event.xconfigure.window
|
|
<< " " << event.xconfigure.send_event << " " << event.xconfigure.serial
|
|
<< " " << event.xconfigure.x << "x" << event.xconfigure.y
|
|
<< " " << event.xconfigure.width << "x" << event.xconfigure.height
|
|
<< " border " << event.xconfigure.border_width << " above " << event.xconfigure.above
|
|
<< " override " << event.xconfigure.override_redirect << "\n"
|
|
#endif
|
|
;
|
|
}
|
|
|
|
void KPlayerX11GetKeyboardMouseState (uint id)
|
|
{
|
|
#ifdef DEBUG_KPLAYER_KEY
|
|
kdDebugTime() << "KPlayerX11GetKeyboardMouseState " << id << "\n";
|
|
#endif
|
|
Window root, child;
|
|
int root_x, root_y, win_x, win_y;
|
|
uint state;
|
|
if ( XQueryPointer (tqt_xdisplay(), id, &root, &child, &root_x, &root_y, &win_x, &win_y, &state) )
|
|
{
|
|
#ifdef DEBUG_KPLAYER_KEY
|
|
kdDebugTime() << " root " << root << " " << root_x << "x" << root_y << " child " << child
|
|
<< " " << win_x << "x" << win_y << " state " << state << "\n";
|
|
#endif
|
|
KPlayerSetControlShiftState ((state & ControlMask) == ControlMask, (state & ShiftMask) == ShiftMask);
|
|
}
|
|
}
|
|
|
|
extern QX11EventFilter tqt_set_x11_event_filter (QX11EventFilter);
|
|
|
|
static int KPlayerX11EventFilterCount = 0;
|
|
|
|
void KPlayerSetX11EventFilter (void)
|
|
{
|
|
if ( ! KPlayerX11EventFilterCount ++ )
|
|
PreviousX11EventFilter = tqt_set_x11_event_filter (KPlayerX11EventFilter);
|
|
}
|
|
|
|
void KPlayerResetX11EventFilter (void)
|
|
{
|
|
if ( -- KPlayerX11EventFilterCount )
|
|
return;
|
|
tqt_set_x11_event_filter (PreviousX11EventFilter);
|
|
PreviousX11EventFilter = 0;
|
|
}
|
|
|
|
// fixed for enable-final
|
|
#undef Above
|
|
#undef Always
|
|
#undef Below
|
|
#undef Bool
|
|
#undef CursorShape
|
|
#undef FocusIn
|
|
#undef FocusOut
|
|
#undef KeyPress
|
|
#undef KeyRelease
|
|
#undef None
|
|
#undef Unsorted
|