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) }
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 }
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 }
// 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) } }
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) }
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 }
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) } } } }
func (m *TrayManager) isValidWindow(xid xproto.Window) bool { r, err := xproto.GetWindowAttributes(TrayXU.Conn(), xid).Reply() return r != nil && err == nil }