[Pkg-mozext-commits] [firetray] 134/399: restore window to its previous virtual desktop

David Prévot taffit at alioth.debian.org
Tue Oct 29 18:23:28 UTC 2013


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch dfsg-clean
in repository firetray.

commit 5e4eaea614f037c1541a47ac58f5321dc71d914c
Author: foudfou <foudil.newbie+git at gmail.com>
Date:   Mon Jan 9 22:13:27 2012 +0100

    restore window to its previous virtual desktop
---
 src/modules/ctypes/gdk.jsm          |    7 +++
 src/modules/ctypes/x11.jsm          |  112 ++++++++++-------------------------
 src/modules/gtk2/FiretrayWindow.jsm |   90 ++++++++++++++++++++++------
 testing/Makefile                    |    6 +-
 testing/xev_desktop.c               |   60 +++++++++++++++++++
 5 files changed, 175 insertions(+), 100 deletions(-)

diff --git a/src/modules/ctypes/gdk.jsm b/src/modules/ctypes/gdk.jsm
index 6cbeb48..5e5e600 100644
--- a/src/modules/ctypes/gdk.jsm
+++ b/src/modules/ctypes/gdk.jsm
@@ -108,6 +108,10 @@ function gdk_defines(lib) {
   this.GDK_GRAB_BROKEN       = 35;
   this.GDK_DAMAGE            = 36;
   this.GDK_EVENT_LAST = 37;      /* helper variable for decls */
+  this.GdkPropMode = ctypes.int; // enum
+  this.GDK_PROP_MODE_REPLACE = 0;
+  this.GDK_PROP_MODE_PREPEN  = 1;
+  this.GDK_PROP_MODE_APPEND  = 2;
 
   this.GdkWindow = ctypes.StructType("GdkWindow");
   this.GdkByteOrder = ctypes.int; // enum
@@ -176,6 +180,7 @@ function gdk_defines(lib) {
     { "changed_mask": this.GdkWindowState },
     { "new_window_state": this.GdkWindowState },
   ]);
+  this.GdkAtom = ctypes.StructType("GdkAtom");
 
   this.GdkFilterFunc_t = ctypes.FunctionType(
     ctypes.default_abi, this.GdkFilterReturn,
@@ -225,6 +230,8 @@ function gdk_defines(lib) {
   lib.lazy_bind("gdk_drawable_get_size", ctypes.void_t, this.GdkDrawable.ptr, gobject.gint.ptr, gobject.gint.ptr);
   // lib.lazy_bind("gdk_window_get_geometry", ctypes.void_t, this.GdkWindow.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr, gobject.gint.ptr);
   lib.lazy_bind("gdk_window_move_resize", ctypes.void_t, this.GdkWindow.ptr, gobject.gint, gobject.gint, gobject.gint, gobject.gint);
+  lib.lazy_bind("gdk_atom_intern", this.GdkAtom, gobject.gchar.ptr, gobject.gboolean);
+  lib.lazy_bind("gdk_property_change", ctypes.void_t, this.GdkWindow.ptr, this.GdkAtom, this.GdkAtom, gobject.gint, this.GdkPropMode, gobject.guchar.ptr, gobject.gint);
 
 }
 
diff --git a/src/modules/ctypes/x11.jsm b/src/modules/ctypes/x11.jsm
index 72236b7..97c8a78 100644
--- a/src/modules/ctypes/x11.jsm
+++ b/src/modules/ctypes/x11.jsm
@@ -34,7 +34,8 @@ const XATOMS_EWMH_WM_STATES =  [
   "_NET_WM_STATE_FULLSCREEN", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_BELOW",
   "_NET_WM_STATE_DEMANDS_ATTENTION"
 ];
-const XATOMS = XATOMS_ICCCM.concat(XATOMS_EWMH_WM_STATES).concat(XATOMS_EWMH_GENERAL);
+const XATOMS = XATOMS_ICCCM.concat(XATOMS_EWMH_WM_STATES)
+  .concat(XATOMS_EWMH_GENERAL).concat(["CARDINAL"]);
 
 
 function x11_defines(lib) {
@@ -55,35 +56,43 @@ function x11_defines(lib) {
   }
 
   // X.h
-  this.Success = 0;
-  this.None = 0;
-  this.AnyPropertyType = 0;
-  this.BadValue = 2;
-  this.BadWindow = 3;
-  this.BadAtom = 5;
-  this.BadMatch = 8;
-  this.BadAlloc = 11;
+  this.Success          = 0;
+  this.None             = 0;
+  this.AnyPropertyType  = 0;
+  this.BadValue         = 2;
+  this.BadWindow        = 3;
+  this.BadAtom          = 5;
+  this.BadMatch         = 8;
+  this.BadAlloc         = 11;
   this.PropertyNewValue = 0;
-  this.PropertyDelete = 1;
+  this.PropertyDelete   = 1;
+  this.PropModeReplace  = 0;
+  this.PropModePrepend  = 1;
+  this.PropModeAppend   = 2;
   // Event names
-  this.DestroyNotify = 17;
-  this.UnmapNotify = 18;
-  this.MapNotify = 19;
+  this.DestroyNotify  = 17;
+  this.UnmapNotify    = 18;
+  this.MapNotify      = 19;
   this.PropertyNotify = 28;
-  this.ClientMessage = 33;
+  this.ClientMessage  = 33;
   // Xutils.h: definitions for initial window state
   this.WithdrawnState = 0;      /* for windows that are not mapped */
-  this.NormalState = 1;         /* most applications want to start this way */
-  this.IconicState = 3;         /* application wants to start as an icon */
+  this.NormalState    = 1;      /* most applications want to start this way */
+  this.IconicState    = 3;      /* application wants to start as an icon */
   // Xatom
-  this.XA_ATOM = 4;
+  this.XA_ATOM     = 4;
+  this.XA_CARDINAL = 6;
+  // Input Event Masks
+  this.SubstructureNotifyMask   = 1<<19;
+  this.SubstructureRedirectMask = 1<<20;
 
   this.Bool = ctypes.int;
+  this.Status = ctypes.int;
   this.Display = ctypes.StructType("Display");
   // union not supported by js-ctypes
   // https://bugzilla.mozilla.org/show_bug.cgi?id=535378 "You can always
   // typecast pointers, at least as long as you know which type is the biggest"
-  this.XEvent = ctypes.void_t;
+  this.XEvent = ctypes.void_t;  // union
   this.XAnyEvent = ctypes.StructType("XAnyEvent", [
     { "type": ctypes.int },
     { "serial": ctypes.unsigned_long },
@@ -116,6 +125,9 @@ function x11_defines(lib) {
   lib.lazy_bind("XInternAtom", this.Atom, this.Display.ptr, ctypes.char.ptr, this.Bool); // only_if_exsits
   lib.lazy_bind("XGetWindowProperty", ctypes.int, this.Display.ptr, this.Window, this.Atom, ctypes.long, ctypes.long, this.Bool, this.Atom, this.Atom.ptr, ctypes.int.ptr, ctypes.unsigned_long.ptr, ctypes.unsigned_long.ptr, ctypes.unsigned_char.ptr.ptr);
   lib.lazy_bind("XChangeProperty", ctypes.int, this.Display.ptr, this.Window, this.Atom, this.Atom, ctypes.int, ctypes.int, ctypes.unsigned_char.ptr, ctypes.int);
+  lib.lazy_bind("XDefaultRootWindow", this.Window, this.Display.ptr);
+  lib.lazy_bind("XSendEvent", this.Status, this.Display.ptr, this.Window, this.Bool, ctypes.long, this.XEvent.ptr);
+
 }
 
 if (!x11) {
@@ -149,67 +161,3 @@ typedef unsigned long Atom;
 typedef CARD32 Atom;
 #  endif
 */
-
-/*
-XEvent {
-        int type;
-        XAnyEvent xany;
-        XKeyEvent xkey;
-        XButtonEvent xbutton;
-        XMotionEvent xmotion;
-        XCrossingEvent xcrossing;
-        XFocusChangeEvent xfocus;
-        XExposeEvent xexpose;
-        XGraphicsExposeEvent xgraphicsexpose;
-        XNoExposeEvent xnoexpose;
-        XVisibilityEvent xvisibility;
-        XCreateWindowEvent xcreatewindow;
-        XDestroyWindowEvent xdestroywindow;
-        XUnmapEvent xunmap;
-        XMapEvent xmap;
-        XMapRequestEvent xmaprequest;
-        XReparentEvent xreparent;
-        XConfigureEvent xconfigure;
-        XGravityEvent xgravity;
-        XResizeRequestEvent xresizerequest;
-        XConfigureRequestEvent xconfigurerequest;
-        XCirculateEvent xcirculate;
-        XCirculateRequestEvent xcirculaterequest;
-        XPropertyEvent xproperty;
-        XSelectionClearEvent xselectionclear;
-        XSelectionRequestEvent xselectionrequest;
-        XSelectionEvent xselection;
-        XColormapEvent xcolormap;
-        XClientMessageEvent xclient;
-        XMappingEvent xmapping;
-        XErrorEvent xerror;
-        XKeymapEvent xkeymap;
-        XGenericEvent xgeneric;
-        XGenericEventCookie xcookie;
-        long pad[24];
-}
-
-GdkEvent {
-  GdkEventType              type;
-  GdkEventAny               any;
-  GdkEventExpose            expose;
-  GdkEventNoExpose          no_expose;
-  GdkEventVisibility        visibility;
-  GdkEventMotion            motion;
-  GdkEventButton            button;
-  GdkEventScroll            scroll;
-  GdkEventKey               key;
-  GdkEventCrossing          crossing;
-  GdkEventFocus             focus_change;
-  GdkEventConfigure         configure;
-  GdkEventProperty          property;
-  GdkEventSelection         selection;
-  GdkEventOwnerChange       owner_change;
-  GdkEventProximity         proximity;
-  GdkEventClient            client;
-  GdkEventDND               dnd;
-  GdkEventWindowState       window_state;
-  GdkEventSetting           setting;
-  GdkEventGrabBroken        grab_broken;
-};
-*/
diff --git a/src/modules/gtk2/FiretrayWindow.jsm b/src/modules/gtk2/FiretrayWindow.jsm
index 88b117e..7628114 100644
--- a/src/modules/gtk2/FiretrayWindow.jsm
+++ b/src/modules/gtk2/FiretrayWindow.jsm
@@ -176,18 +176,20 @@ firetray.Window = {
       firetray.Handler.windows[xid].savedWidth,
       firetray.Handler.windows[xid].savedHeight,
       false); // repaint
+
+    ['savedX', 'savedX', 'savedWidth', 'savedHeight'].forEach(function(element, index, array) {
+      delete firetray.Handler.windows[xid][element];
+    });
   },
 
   saveWindowStates: function(xid) {
-    // TODO: we may want to restore the window onto its original
-    // desktop/monitor/etc.
     let winStates = firetray.Window.getXWindowStates(x11.Window(xid));
-    firetray.Handler.windows[xid].savedWindowStates = winStates;
+    firetray.Handler.windows[xid].savedStates = winStates;
     LOG("save: windowStates="+winStates);
   },
 
   restoreWindowStates: function(xid) {
-    let winStates = firetray.Handler.windows[xid].savedWindowStates;
+    let winStates = firetray.Handler.windows[xid].savedStates;
     LOG("restored WindowStates: " + winStates);
     if (winStates & FIRETRAY_XWINDOW_MAXIMIZED) {
       firetray.Handler.windows[xid].chromeWin.maximize();
@@ -196,6 +198,36 @@ firetray.Window = {
     if (!hides_on_minimize && (winStates & FIRETRAY_XWINDOW_HIDDEN)) {
       firetray.Handler.windows[xid].chromeWin.minimize();
     }
+
+    delete firetray.Handler.windows[xid].savedStates;
+  },
+
+  saveWindowDesktop: function(xid) {
+    let winDesktop = firetray.Window.getXWindowDesktop(x11.Window(xid));
+    firetray.Handler.windows[xid].savedDesktop = winDesktop;
+    LOG("save: windowDesktop="+winDesktop);
+  },
+
+  restoreWindowDesktop: function(xid) {
+    let desktopDest = firetray.Handler.windows[xid].savedDesktop;
+    if (desktopDest === null) return;
+
+    let xev = new x11.XClientMessageEvent;
+    xev.type = x11.ClientMessage;
+    xev.window = x11.Window(xid);
+    xev.message_type = x11.current.Atoms._NET_WM_DESKTOP;
+    xev.format = 32;
+    xev.data[0] = desktopDest;
+
+    let rootWin = x11.XDefaultRootWindow(x11.current.Display);
+    let propagate = false;
+    let mask = ctypes.long(x11.SubstructureNotifyMask|x11.SubstructureRedirectMask);
+    // fortunately, it's OK not to cast xev. ctypes.cast to a void_t doesn't work (length pb)
+    let status = x11.XSendEvent(x11.current.Display, rootWin, propagate, mask, xev.address());
+    // always returns 1 (BadRequest as a coincidence)
+
+    LOG("restored to desktop: "+desktopDest);
+    delete firetray.Handler.windows[xid].savedDesktop;
   },
 
 /* KEPT FOR LATER USE
@@ -213,12 +245,12 @@ firetray.Window = {
 */
 
   /**
-   * YOU MUST x11.XFree() THE VARIABLE RETURN BY THIS FUNCTION
+   * YOU MUST x11.XFree() THE VARIABLE RETURNED BY THIS FUNCTION
    * @param xwin: a x11.Window
    * @param prop: a x11.Atom
    */
   getXWindowProperties: function(xwin, prop) {
-    // infos returned by XGetWindowProperty()
+    // infos returned by XGetWindowProperty() - FIXME: should be freed ?
     let actual_type = new x11.Atom;
     let actual_format = new ctypes.int;
     let nitems = new ctypes.unsigned_long;
@@ -229,7 +261,8 @@ firetray.Window = {
     let offset = 0;
     let res = x11.XGetWindowProperty(
       x11.current.Display, xwin, prop, offset, bufSize, 0, x11.AnyPropertyType,
-      actual_type.address(), actual_format.address(), nitems.address(), bytes_after.address(), prop_value.address());
+      actual_type.address(), actual_format.address(), nitems.address(),
+      bytes_after.address(), prop_value.address());
     LOG("XGetWindowProperty res="+res+", actual_type="+actual_type.value+", actual_format="+actual_format.value+", bytes_after="+bytes_after.value+", nitems="+nitems.value);
 
     if (!strEquals(res, x11.Success)) {
@@ -264,19 +297,20 @@ firetray.Window = {
   getXWindowStates: function(xwin) {
     let winStates = 0;
 
-    let [propsFound, nitems] = firetray.Window.getXWindowProperties(xwin, x11.current.Atoms._NET_WM_STATE);
+    let [propsFound, nitems] =
+      firetray.Window.getXWindowProperties(xwin, x11.current.Atoms._NET_WM_STATE);
     LOG("propsFound, nitems="+propsFound+", "+nitems);
     if (!propsFound) return 0;
 
     let maximizedHorz = maximizedVert = false;
     for (let i=0, len=nitems.value; i<len; ++i) {
       LOG("i: "+propsFound.contents[i]);
-      let foundProp = propsFound.contents[i].toString();
-      if (strEquals(propsFound.contents[i], x11.current.Atoms['_NET_WM_STATE_HIDDEN']))
+      let currentProp = propsFound.contents[i];
+      if (strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_HIDDEN']))
         winStates |= FIRETRAY_XWINDOW_HIDDEN;
-      else if (strEquals(propsFound.contents[i], x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_HORZ']))
+      else if (strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_HORZ']))
         maximizedHorz = true;
-      else if (strEquals(propsFound.contents[i], x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_VERT']))
+      else if (strEquals(currentProp, x11.current.Atoms['_NET_WM_STATE_MAXIMIZED_VERT']))
         maximizedVert = true;
     }
 
@@ -288,6 +322,25 @@ firetray.Window = {
     return winStates;
   },
 
+  getXWindowDesktop: function(xwin) {
+    let desktop = null;
+
+    let [propsFound, nitems] =
+      firetray.Window.getXWindowProperties(xwin, x11.current.Atoms._NET_WM_DESKTOP);
+    LOG("DESKTOP propsFound, nitems="+propsFound+", "+nitems);
+
+    if (strEquals(nitems.value, 0))
+      WARN("desktop number not found");
+    else if (strEquals(nitems.value, 1))
+      desktop = propsFound.contents[0];
+    else
+      throw new RangeError("more than one desktop found");
+
+    x11.XFree(propsFound);
+
+    return desktop;
+  },
+
   filterWindow: function(xev, gdkEv, data) {
     if (!xev)
       return gdk.GDK_FILTER_CONTINUE;
@@ -301,7 +354,7 @@ firetray.Window = {
       case x11.UnmapNotify:
         LOG("UnmapNotify");
         let winStates = firetray.Window.getXWindowStates(xwin);
-        let isHidden =  winStates & FIRETRAY_XWINDOW_HIDDEN;
+        let isHidden = winStates & FIRETRAY_XWINDOW_HIDDEN;
         LOG("winStates="+winStates+", isHidden="+isHidden);
         if (isHidden) {
           let hides_on_minimize = firetray.Utils.prefService.getBoolPref('hides_on_minimize');
@@ -436,8 +489,10 @@ firetray.Handler.showSingleWindow = function(xid) {
 
   // try to restore previous state. TODO: z-order respected ?
   firetray.Window.restoreWindowPositionAndSize(xid);
-  firetray.Window.restoreWindowStates(xid); // no need to be saved
+  firetray.Window.restoreWindowStates(xid);
   firetray.Handler.windows[xid].baseWin.visibility = true; // show
+  firetray.Window.restoreWindowDesktop(xid);               // after show
+  // TODO: we need want to restore to the original monitor (screen)
 
   firetray.Handler.windows[xid].visibility = true;
   firetray.Handler.visibleWindowsCount += 1;
@@ -450,6 +505,7 @@ firetray.Handler.hideSingleWindow = function(xid) {
 
   firetray.Window.saveWindowPositionAndSize(xid);
   firetray.Window.saveWindowStates(xid);
+  firetray.Window.saveWindowDesktop(xid);
   firetray.Handler.windows[xid].baseWin.visibility = false; // hide
 
   firetray.Handler.windows[xid].visibility = false;
@@ -477,9 +533,9 @@ firetray.Handler.showHideAllWindows = function(gtkStatusIcon, userData) {
 
 /**
  * init X11 Display and handled XAtoms.
- * Needs to be defined and called outside x11.jsm because: gdk already imports
- * x11, and there is no means to get the default Display solely with Xlib
- * without opening one...  :-(
+ * Needs to be defined and called outside x11.jsm because: 1. gdk already
+ * imports x11, 2. there is no means to get the default Display solely with
+ * Xlib without opening one... :-(
  */
 x11.init = function() {
   if (!isEmpty(this.current))
diff --git a/testing/Makefile b/testing/Makefile
index b26eda4..da8150c 100644
--- a/testing/Makefile
+++ b/testing/Makefile
@@ -1,5 +1,6 @@
 includes := $(shell pkg-config --libs --cflags gtk+-2.0)
-executables :=  gtk_icon_example trayicon hide xtypes x11XGetWindowProp window_state_event
+executables :=  gtk_icon_example trayicon hide xtypes x11XGetWindowProp \
+	window_state_event xev_desktop
 
 .PHONY: all
 all: $(executables)
@@ -25,3 +26,6 @@ x11XGetWindowProp: x11XGetWindowProp.c
 
 window_state_event: window_state_event.c
 	gcc $(includes) -o window_state_event window_state_event.c
+
+xev_desktop: xev_desktop.c
+	gcc -lXm -lXt -lX11 -o xev_desktop xev_desktop.c
diff --git a/testing/xev_desktop.c b/testing/xev_desktop.c
new file mode 100644
index 0000000..eb2fb73
--- /dev/null
+++ b/testing/xev_desktop.c
@@ -0,0 +1,60 @@
+/**
+ * cc -o memo memo.c -lXm -lXt -lX11 -I/usr/X11R6/include/
+ -L/usr/X11R6/lib/
+*/
+
+
+#include <Xm/Xm.h>
+#include <X11/X.h>
+#include <Xm/Label.h>
+#include <X11/Xatom.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void main(int argc, char **argv)
+{
+  Widget shell, msg;
+  XtAppContext app;
+  XmString xmstr;
+  XClientMessageEvent xev;
+  Display *display;
+
+  shell = XtAppInitialize(&app, "Memo", NULL, 0, &argc, argv, NULL,
+                          NULL, 0);
+
+  xmstr = XmStringCreateLtoR("move window test",
+                             XmFONTLIST_DEFAULT_TAG);
+
+  msg =
+    XtVaCreateManagedWidget(
+      "message", xmLabelWidgetClass, shell, XmNlabelString, xmstr,
+      NULL);
+
+  XmStringFree(xmstr);
+
+  XtRealizeWidget(shell);
+
+
+/* Now move the window to a different area */
+  display = XtDisplay(shell);
+
+
+  xev.type = ClientMessage;
+  xev.window = XtWindow(shell);
+  xev.message_type = XInternAtom(display, "_NET_WM_DESKTOP", False);
+  xev.format = 32;
+
+/* Force into desktop 2 */
+  xev.data.l[0] = 2;
+
+
+  XSendEvent(
+    display,
+    RootWindowOfScreen(XtScreen(shell)),
+    False,
+    SubstructureNotifyMask|SubstructureRedirectMask,
+    (XEvent *) &xev);
+
+
+  XtAppMainLoop(app);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firetray.git



More information about the Pkg-mozext-commits mailing list