Ejemplo n.º 1
0
func (c *Client) attachEventCallbacks() {
	c.win.Listen(xproto.EventMaskPropertyChange |
		xproto.EventMaskStructureNotify)

	pid := c.Frame().Parent().Id
	attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), pid).Reply()
	if err == nil {
		masks := int(attrs.YourEventMask)
		if wm.Config.Ffm {
			masks |= xproto.EventMaskEnterWindow
		}
		c.Frame().Parent().Listen(masks)
	}

	c.cbMapNotify().Connect(wm.X, c.Id())
	c.cbUnmapNotify().Connect(wm.X, c.Id())
	c.cbDestroyNotify().Connect(wm.X, c.Id())
	c.cbConfigureRequest().Connect(wm.X, c.Id())
	c.cbPropertyNotify().Connect(wm.X, c.Id())
	c.cbClientMessage().Connect(wm.X, c.Id())
	c.cbShapeNotify().Connect(wm.X, c.Id())

	// Focus follows mouse?
	if wm.Config.Ffm {
		c.cbEnterNotify().Connect(wm.X, c.Frame().Parent().Id)
	}
	c.handleFocusIn().Connect(wm.X, c.Frame().Parent().Id)
	c.handleFocusOut().Connect(wm.X, c.Frame().Parent().Id)

	wm.ClientMouseSetup(c)
	wm.FrameMouseSetup(c, c.frame.Parent().Id)
}
Ejemplo n.º 2
0
func isNormalWindow(xid xproto.Window) bool {
	winProps, err := xproto.GetWindowAttributes(XU.Conn(), xid).Reply()
	if err != nil {
		logger.Debug("faild Get WindowAttributes:", xid, err)
		return false
	}
	if winProps.MapState != xproto.MapStateViewable {
		return false
	}
	// logger.Debug("enter isNormalWindow:", xid)
	if wmClass, err := icccm.WmClassGet(XU, xid); err == nil {
		if wmClass.Instance == "explorer.exe" && wmClass.Class == "Wine" {
			return false
		} else if wmClass.Class == "DDELauncher" {
			// FIXME:
			// start_monitor_launcher_window like before?
			return false
		} else if wmClass.Class == "Desktop" {
			// FIXME:
			// get_desktop_pid like before?
			return false
		} else if wmClass.Class == "Dlock" {
			return false
		}
	}
	if isSkipTaskbar(xid) {
		return false
	}
	types, err := ewmh.WmWindowTypeGet(XU, xid)
	if err != nil {
		logger.Debug("Get Window Type failed:", err)
		if _, err := xprop.GetProperty(XU, xid, "_XEMBED_INFO"); err != nil {
			logger.Debug("has _XEMBED_INFO")
			return true
		} else {
			logger.Debug("Get _XEMBED_INFO failed:", err)
			return false
		}
	}

	mayBeDocked := false
	cannotBeDoced := false
	for _, wmType := range types {
		if wmType == "_NET_WM_WINDOW_TYPE_NORMAL" {
			mayBeDocked = true
		} else if wmType == "_NET_WM_WINDOW_TYPE_DIALOG" {
			if !canBeMinimized(xid) {
				mayBeDocked = false
				break
			} else {
				mayBeDocked = true
			}
		} else if contains(cannotBeDockedType, wmType) {
			cannotBeDoced = true
		}
	}

	isNormal := mayBeDocked && !cannotBeDoced
	return isNormal
}
Ejemplo n.º 3
0
func (c *Client) isAttrsUnmapped() bool {
	attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), c.Id()).Reply()
	if err != nil {
		logger.Warning.Printf(
			"Could not get window attributes for '%s': %s.", c, err)
		return false
	}
	return attrs.MapState == xproto.MapStateUnmapped
}
Ejemplo n.º 4
0
// manageExistingClients traverse the window tree and tries to manage all
// top-level clients. Clients that are not in the Unmapped state will be
// managed.
func manageExistingClients() {
	tree, err := xproto.QueryTree(wm.X.Conn(), wm.Root.Id).Reply()
	if err != nil {
		logger.Warning.Printf("Could not issue QueryTree request: %s", err)
		return
	}
	for _, potential := range tree.Children {
		// Ignore our own dummy window...
		if potential == wm.X.Dummy() {
			continue
		}

		attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), potential).Reply()
		if err != nil {
			continue
		}
		if attrs.MapState == xproto.MapStateUnmapped {
			continue
		}
		logger.Message.Printf("Managing existing client %d", potential)
		xclient.New(potential)
	}
}
Ejemplo n.º 5
0
func (m *ClientManager) listenRootWindow() {
	var update = func() {
		list, err := ewmh.ClientListGet(XU)
		if err != nil {
			logger.Warning("Can't Get _NET_CLIENT_LIST", err)
		}
		isLauncherShown = false
		for _, xid := range list {
			if !isDeepinLauncher(xid) {
				continue
			}

			winProps, err :=
				xproto.GetWindowAttributes(XU.Conn(),
					xid).Reply()
			if err != nil {
				break
			}
			if winProps.MapState == xproto.MapStateViewable {
				isLauncherShown = true
			}
			break
		}
		ENTRY_MANAGER.runtimeAppChanged(list)
	}

	xwindow.New(XU, XU.RootWin()).Listen(xproto.EventMaskPropertyChange)
	xevent.PropertyNotifyFun(func(XU *xgbutil.XUtil, ev xevent.PropertyNotifyEvent) {
		switch ev.Atom {
		case _NET_CLIENT_LIST:
			update()
		case _NET_ACTIVE_WINDOW:
			var err error
			isLauncherShown = false
			if activeWindow, err = ewmh.ActiveWindowGet(XU); err == nil {
				appId := find_app_id_by_xid(activeWindow,
					DisplayModeType(setting.GetDisplayMode()))
				logger.Debug("current active window:", appId)
				if rApp, ok := ENTRY_MANAGER.runtimeApps[appId]; ok {
					logger.Debug("find runtime app")
					rApp.setLeader(activeWindow)
					rApp.updateState(activeWindow)
				}

				logger.Debug("active window is", appId)
				if appId != DDELauncher {
					LAUNCHER, err := launcher.NewLauncher(
						"com.deepin.dde.launcher",
						"/com/deepin/dde/launcher",
					)
					if err != nil {
						logger.Debug(err)
					} else {
						LAUNCHER.Hide()
						launcher.DestroyLauncher(LAUNCHER)
					}
				} else {
					isLauncherShown = true
				}

				lastActive = appId
				dbus.Emit(m, "ActiveWindowChanged", uint32(activeWindow))
			}

			hideMode := HideModeType(setting.GetHideMode())
			if hideMode == HideModeSmartHide || hideMode == HideModeKeepHidden {
				hideModemanager.UpdateState()
			}
		case _NET_SHOWING_DESKTOP:
			dbus.Emit(m, "ShowingDesktopChanged")
		case DEEPIN_SCREEN_VIEWPORT:
			updateCurrentViewport()
		}
	}).Connect(XU, XU.RootWin())

	update()
	xevent.Main(XU)
}
Ejemplo n.º 6
0
func New(id xproto.Window) *Client {
	wm.X.Grab()
	defer wm.X.Ungrab()

	// If this is an override redirect, skip...
	attrs, err := xproto.GetWindowAttributes(wm.X.Conn(), id).Reply()
	if err != nil {
		logger.Warning.Printf("Could not get window attributes for '%d': %s",
			id, err)
	} else {
		if attrs.OverrideRedirect {
			logger.Message.Printf(
				"Not managing override redirect window %d", id)
			return nil
		}
	}

	if client := wm.FindManagedClient(id); client != nil {
		logger.Message.Printf("Already managing client: %s", client)
		return nil
	}

	win := xwindow.New(wm.X, id)
	if _, err := win.Geometry(); err != nil {
		logger.Warning.Printf("Could not manage client %d because: %s", id, err)
		return nil
	}

	c := &Client{
		win:         win,
		name:        "N/A",
		state:       frame.Inactive,
		layer:       stack.LayerDefault,
		maximized:   false,
		iconified:   false,
		unmapIgnore: 0,
		floating:    false,
		fullscreen:  false,
		skipTaskbar: false,
		skipPager:   false,
		demanding:   false,
		attnQuit:    make(chan struct{}, 0),
	}

	c.manage()

	// We don't fire the managed hook on startup since it can lead to
	// unintuitive state changes.
	// If someone really wants it, we can add a new "startup_managed" hook
	// or something.
	if !wm.Startup {
		c.FireHook(hook.Managed)
	}
	if !c.iconified {
		c.Map()
		if !wm.Startup && c.PrimaryType() == TypeNormal {
			if !wm.Config.Ffm || wm.Config.FfmStartupFocus {
				c.Focus()
			}
		}
	}

	return c
}
Ejemplo n.º 7
0
func main() {
	var err error
	xConn, err = xgb.NewConn()
	if err != nil {
		log.Fatal(err)
	}
	if err = xinerama.Init(xConn); err != nil {
		log.Fatal(err)
	}
	xSetup := xp.Setup(xConn)
	if len(xSetup.Roots) != 1 {
		log.Fatalf("X setup has unsupported number of roots: %d", len(xSetup.Roots))
	}
	rootXWin = xSetup.Roots[0].Root

	becomeTheWM()
	initAtoms()
	initDesktop(&xSetup.Roots[0])
	initKeyboardMapping()
	initScreens()

	// Manage any existing windows.
	if tree, err := xp.QueryTree(xConn, rootXWin).Reply(); err != nil {
		log.Fatal(err)
	} else if tree != nil {
		for _, c := range tree.Children {
			if c == desktopXWin {
				continue
			}
			attrs, err := xp.GetWindowAttributes(xConn, c).Reply()
			if attrs == nil || err != nil {
				continue
			}
			if attrs.OverrideRedirect || attrs.MapState == xp.MapStateUnmapped {
				continue
			}
			manage(c, false)
		}
	}

	// Process X events.
	eeChan := make(chan xEventOrError)
	go func() {
		for {
			e, err := xConn.WaitForEvent()
			eeChan <- xEventOrError{e, err}
		}
	}()
	for {
		for i, c := range checkers {
			if err := c.Check(); err != nil {
				log.Println(err)
			}
			checkers[i] = nil
		}
		checkers = checkers[:0]

		select {
		case f := <-proactiveChan:
			f()
		case ee := <-eeChan:
			if ee.error != nil {
				log.Println(ee.error)
				continue
			}
			switch e := ee.event.(type) {
			case xp.ButtonPressEvent:
				eventTime = e.Time
				handleButtonPress(e)
			case xp.ButtonReleaseEvent:
				eventTime = e.Time
			case xp.ClientMessageEvent:
				// No-op.
			case xp.ConfigureNotifyEvent:
				// No-op.
			case xp.ConfigureRequestEvent:
				handleConfigureRequest(e)
			case xp.DestroyNotifyEvent:
				// No-op.
			case xp.EnterNotifyEvent:
				eventTime = e.Time
				handleEnterNotify(e)
			case xp.ExposeEvent:
				handleExpose(e)
			case xp.KeyPressEvent:
				eventTime, keyRootX, keyRootY, keyState = e.Time, e.RootX, e.RootY, e.State
				handleKeyPress(e)
			case xp.KeyReleaseEvent:
				eventTime, keyRootX, keyRootY, keyState = e.Time, 0, 0, 0
			case xp.MapNotifyEvent:
				// No-op.
			case xp.MappingNotifyEvent:
				// No-op.
			case xp.MapRequestEvent:
				manage(e.Window, true)
			case xp.MotionNotifyEvent:
				eventTime = e.Time
				handleMotionNotify(e)
			case xp.UnmapNotifyEvent:
				unmanage(e.Window)
			default:
				log.Printf("unhandled event: %v", ee.event)
			}
		}
	}
}
Ejemplo n.º 8
0
func (m *TrayManager) isValidWindow(xid xproto.Window) bool {
	r, err := xproto.GetWindowAttributes(TrayXU.Conn(), xid).Reply()
	return r != nil && err == nil
}