[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16543] trunk/blender/intern/ghost/intern: Small fix in GHOST X11 system.
Diego Borghetti
bdiego at gmail.com
Mon Sep 15 20:23:37 CEST 2008
Revision: 16543
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16543
Author: bdiego
Date: 2008-09-15 20:23:34 +0200 (Mon, 15 Sep 2008)
Log Message:
-----------
Small fix in GHOST X11 system.
* Fix and a little of cleanup to the full screen, minimzed and
maximized code.
* Fix bad argument in the ClientMessage event to support the
_NET_ACTIVE_WINDOW property.
* Fix focus problem in some WM (like TWM), this is because Blender
don't set the WM_PROTOCOLS list, now it does, a very basic list
but it's what we need now.
Modified Paths:
--------------
trunk/blender/intern/ghost/intern/GHOST_SystemX11.cpp
trunk/blender/intern/ghost/intern/GHOST_SystemX11.h
trunk/blender/intern/ghost/intern/GHOST_WindowX11.cpp
trunk/blender/intern/ghost/intern/GHOST_WindowX11.h
Modified: trunk/blender/intern/ghost/intern/GHOST_SystemX11.cpp
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_SystemX11.cpp 2008-09-15 18:15:11 UTC (rev 16542)
+++ trunk/blender/intern/ghost/intern/GHOST_SystemX11.cpp 2008-09-15 18:23:34 UTC (rev 16543)
@@ -96,15 +96,26 @@
if (!m_display) return;
#ifdef __sgi
- m_delete_window_atom
- = XSGIFastInternAtom(m_display,
+ m_delete_window_atom = XSGIFastInternAtom(m_display,
"WM_DELETE_WINDOW",
SGI_XA_WM_DELETE_WINDOW, False);
#else
- m_delete_window_atom
- = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
+ m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
#endif
+ m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
+ m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
+ m_wm_state= XInternAtom(m_display, "WM_STATE", False);
+ m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False);
+ m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False);
+ m_net_max_horz= XInternAtom(m_display,
+ "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ m_net_max_vert= XInternAtom(m_display,
+ "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ m_net_fullscreen= XInternAtom(m_display,
+ "_NET_WM_STATE_FULLSCREEN", False);
+ m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
+
// compute the initial time
timeval tv;
if (gettimeofday(&tv,NULL) == -1) {
@@ -477,7 +488,7 @@
XClientMessageEvent & xcme = xe->xclient;
#ifndef __sgi
- if (xcme.data.l[0] == m_delete_window_atom) {
+ if (((Atom)xcme.data.l[0]) == m_delete_window_atom) {
g_event = new
GHOST_Event(
getMilliSeconds(),
@@ -511,6 +522,14 @@
GHOST_kEventNDOFButton,
window, data);
}
+ }
+ else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
+ /* as ICCCM say, we need reply this event
+ * with a SetInputFocus, the data[1] have
+ * the valid timestamp (send by the window
+ * manager).
+ */
+ XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
} else {
/* Unknown client message, ignore */
}
@@ -528,6 +547,24 @@
// XCrossingEvents pointer leave enter window.
break;
case MapNotify:
+ /*
+ * From ICCCM:
+ * [ Clients can select for StructureNotify on their
+ * top-level windows to track transition between
+ * Normal and Iconic states. Receipt of a MapNotify
+ * event will indicate a transition to the Normal
+ * state, and receipt of an UnmapNotify event will
+ * indicate a transition to the Iconic state. ]
+ */
+ if (window->m_post_init == True) {
+ /*
+ * Now we are sure that the window is
+ * mapped, so only need change the state.
+ */
+ window->setState(window->m_post_state);
+ window->m_post_init= False;
+ }
+ break;
case UnmapNotify:
break;
case MappingNotify:
Modified: trunk/blender/intern/ghost/intern/GHOST_SystemX11.h
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_SystemX11.h 2008-09-15 18:15:11 UTC (rev 16542)
+++ trunk/blender/intern/ghost/intern/GHOST_SystemX11.h 2008-09-15 18:23:34 UTC (rev 16543)
@@ -215,15 +215,27 @@
*/
virtual void putClipboard(GHOST_TInt8 *buffer, int flag) const;
+ /**
+ * Atom used for ICCCM, WM-spec and Motif.
+ * We only need get this atom at the start, it's relative
+ * to the display not the window and are public for every
+ * window that need it.
+ */
+ Atom m_wm_protocols;
+ Atom m_wm_take_focus;
+ Atom m_wm_state;
+ Atom m_wm_change_state;
+ Atom m_net_state;
+ Atom m_net_max_horz;
+ Atom m_net_max_vert;
+ Atom m_net_fullscreen;
+ Atom m_motif;
+ Atom m_delete_window_atom;
+
private :
Display * m_display;
- /**
- * Atom used to detect window close events
- */
- Atom m_delete_window_atom;
-
/// The vector of windows that need to be updated.
std::vector<GHOST_WindowX11 *> m_dirty_windows;
Modified: trunk/blender/intern/ghost/intern/GHOST_WindowX11.cpp
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_WindowX11.cpp 2008-09-15 18:15:11 UTC (rev 16542)
+++ trunk/blender/intern/ghost/intern/GHOST_WindowX11.cpp 2008-09-15 18:23:34 UTC (rev 16543)
@@ -55,6 +55,16 @@
#define MWM_HINTS_DECORATIONS (1L << 1)
/*
+ * A client can't change the window property, that is the
+ * work of the window manager. We send a ClientMessage
+ * event to the Root window with the property
+ * and the Action (WM-spec define this):
+ */
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+#define _NET_WM_STATE_TOGGLE 2
+
+/*
import bpy
I = bpy.data.images['blender.png'] # the 48x48 icon
@@ -154,7 +164,8 @@
// Set up the minimum atrributes that we require and see if
// X can find us a visual matching those requirements.
-
+ Atom atoms[2];
+ int natom;
int attributes[40], i = 0;
@@ -228,7 +239,6 @@
Window root_return;
int x_return,y_return;
unsigned int w_return,h_return,border_w_return,depth_return;
- GHOST_TInt32 screen_x, screen_y;
XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
&w_return, &h_return, &border_w_return, &depth_return );
@@ -262,46 +272,26 @@
// Are we in fullscreen mode - then include
// some obscure blut code to remove decorations.
- if (state == GHOST_kWindowStateFullScreen) {
+ /*
+ * One of the problem with WM_spec is that can't set a property
+ * to a window that isn't mapped. That is why we can't "just
+ * call setState" here.
+ *
+ * To fix this, we first need know that the window is really
+ * mapped waiting for the MapNotify event.
+ *
+ * So, m_post_init indicate that we need wait for the MapNotify
+ * event and then set the window state to the m_post_state.
+ */
+ if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
+ m_post_init = True;
+ m_post_state = state;
+ }
+ else {
+ m_post_init = False;
+ m_post_state = GHOST_kWindowStateNormal;
+ }
- MotifWmHints hints;
- Atom atom;
-
- atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
-
- if (atom == None) {
- GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n");
- } else {
- hints.flags = MWM_HINTS_DECORATIONS;
- hints.decorations = 0; /* Absolutely no decorations. */
- // other hints.decorations make no sense
- // you can't select individual decorations
-
- XChangeProperty(m_display, m_window,
- atom, atom, 32,
- PropModeReplace, (unsigned char *) &hints, 4);
- }
- } else if (state == GHOST_kWindowStateMaximized) {
- // With this, xprop should report the following just after launch
- // _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ
- // After demaximization the right side is empty, though (maybe not the most correct then?)
- Atom state, atomh, atomv;
-
- state = XInternAtom(m_display, "_NET_WM_STATE", False);
- atomh = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
- atomv = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
- if (state == None ) {
- GHOST_PRINT("Atom _NET_WM_STATE requested but not avaliable nor created.\n");
- } else {
- XChangeProperty(m_display, m_window,
- state, XA_ATOM, 32,
- PropModeAppend, (unsigned char *) &atomh, 1);
- XChangeProperty(m_display, m_window,
- state, XA_ATOM, 32,
- PropModeAppend, (unsigned char *) &atomv, 1);
- }
- }
-
// Create some hints for the window manager on how
// we want this window treated.
@@ -324,7 +314,26 @@
free(wmclass);
XFree(xclasshint);
+ /* The basic for a good ICCCM "work" */
+ if (m_system->m_wm_protocols) {
+ natom= 0;
+ if (m_system->m_delete_window_atom) {
+ atoms[natom]= m_system->m_delete_window_atom;
+ natom++;
+ }
+
+ if (m_system->m_wm_take_focus) {
+ atoms[natom]= m_system->m_wm_take_focus;
+ natom++;
+ }
+
+ if (natom) {
+ /* printf("Register atoms: %d\n", natom); */
+ XSetWMProtocols(m_display, m_window, atoms, natom);
+ }
+ }
+
// Set the window icon
XWMHints *xwmhints = XAllocWMHints();
XImage *x_image, *mask_image;
@@ -645,28 +654,298 @@
outY = ay;
}
+void GHOST_WindowX11::icccmSetState(int state)
+{
+ XEvent xev;
- GHOST_TWindowState
-GHOST_WindowX11::
-getState(
-) const {
- //FIXME
- return GHOST_kWindowStateNormal;
+ if (state != IconicState)
+ return;
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = m_display;
+ xev.xclient.window = m_window;
+ xev.xclient.format = 32;
+ xev.xclient.message_type = m_system->m_wm_change_state;
+ xev.xclient.data.l[0] = state;
+ XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
}
- GHOST_TSuccess
-GHOST_WindowX11::
-setState(
- GHOST_TWindowState state
-){
- //TODO
+int GHOST_WindowX11::icccmGetState(void) const
+{
+ unsigned char *prop_ret;
+ unsigned long bytes_after, num_ret;
+ Atom type_ret;
+ int format_ret, st;
- if (state == (int)getState()) {
+ prop_ret = NULL;
+ st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0,
+ 0x7fffffff, False, m_system->m_wm_state, &type_ret,
+ &format_ret, &num_ret, &bytes_after, &prop_ret);
+
+ if ((st == Success) && (prop_ret) && (num_ret == 2))
+ st = prop_ret[0];
+ else
+ st = NormalState;
+
+ if (prop_ret)
+ XFree(prop_ret);
+ return (st);
+}
+
+void GHOST_WindowX11::netwmMaximized(bool set)
+{
+ XEvent xev;
+
+ xev.xclient.type= ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.window = m_window;
+ xev.xclient.message_type = m_system->m_net_state;
+ xev.xclient.format = 32;
+
+ if (set == True)
+ xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
+ else
+ xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+
+ xev.xclient.data.l[1] = m_system->m_net_max_horz;
+ xev.xclient.data.l[2] = m_system->m_net_max_vert;
+ xev.xclient.data.l[3] = 0;
+ xev.xclient.data.l[4] = 0;
+ XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
+ False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+}
+
+bool GHOST_WindowX11::netwmIsMaximized(void) const
+{
+ unsigned char *prop_ret;
+ unsigned long bytes_after, num_ret, i;
+ Atom type_ret;
+ bool st;
+ int format_ret, count;
+
+ prop_ret = NULL;
+ st = False;
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list