Changeset 181

Show
Ignore:
Timestamp:
11/23/2005 09:12:44 AM (3 years ago)
Author:
petli
Message:

Views can now be managed on a most-recently-visited basis, set ViewManager?.view_reorder_views to true to enable it.

Location:
trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/examples/petliwm.py

    r174 r181  
    5959 
    6060 
     61class TraceIM: 
     62    """Class for TraceIMClient.traceim_filters objects. 
     63    """ 
     64 
     65    def __init__(self, enable, unseen, message): 
     66        """Create a TraceIM filter. 
     67 
     68        enable is a client filter selecting the clients that should be 
     69        traced.  It is checked when the client is created. 
     70 
     71        unseen is a client filter which is true when there are unseen 
     72        IMs for this client, and then message is displayed in the mode 
     73        window. 
     74        """ 
     75         
     76        self.enable = enable 
     77        self.unseen = unseen 
     78        self.message = message 
     79 
     80         
    6181class TraceIMClient: 
    6282 
     
    6888    """ 
    6989 
    70     # A list of tuples (filter_enable_tracing, filter_unseen_im, message) 
    71      
    72     traceim_clients = () 
     90    # A list of TraceIM objects 
     91     
     92    traceim_filters = () 
    7393     
    7494    def __client_init__(self): 
    75         self.traceim_unseen = None 
    7695        self.traceim_message = None 
    77         self.traceim_is_unseen = 0 
    78          
    79         for enable, unseen, message in self.traceim_clients: 
    80             if enable(self): 
    81                 wmanager.debug('traceim', 'Enabling IM tracing for %s' % self.get_title()) 
    82                 self.traceim_unseen = unseen 
    83                 self.traceim_message = message 
    84                 self.dispatch.add_handler(X.PropertyNotify, self.traceim_handle_property) 
    85                 self.dispatch.add_handler(wmevents.ClientIconified, self.traceim_handle_iconified) 
    86                 self.dispatch.add_handler(wmevents.ClientDeiconified, self.traceim_handle_iconified) 
    87                 self.traceim_update() 
    88                 break 
     96 
     97        filters = None 
     98        for f in self.traceim_filters: 
     99            if f.enable(self): 
     100                if filters is None: 
     101                    wmanager.debug('traceim', 'Enabling IM tracing for %s' % self.get_title()) 
     102                    self.dispatch.add_handler(X.PropertyNotify, self.traceim_handle_property) 
     103                    self.dispatch.add_handler(wmevents.ClientIconified, self.traceim_handle_iconified) 
     104                    self.dispatch.add_handler(wmevents.ClientDeiconified, self.traceim_handle_iconified) 
     105                    filters = [f] 
     106                else: 
     107                    filters.append(f) 
     108 
     109        if filters: 
     110            self.traceim_filters = filters 
     111            self.traceim_message = None 
     112            self.traceim_update() 
    89113 
    90114    def __client_del__(self): 
    91         if self.traceim_is_unseen: 
    92             self.wm.traceim_remove_message(self) 
     115        self.wm.traceim_remove_message(self) 
    93116 
    94117    def traceim_handle_property(self, evt): 
     
    100123 
    101124    def traceim_update(self): 
    102         if self.traceim_unseen(self): 
    103             if not self.traceim_is_unseen: 
    104                 wmanager.debug('traceim', 'Unseen IM for %s' % self.get_title()) 
    105                 self.traceim_is_unseen = 1 
    106                 self.wm.traceim_add_message(self, self.traceim_message) 
     125        m = [] 
     126        for f in self.traceim_filters: 
     127            if f.unseen(self): 
     128                m.append(f.message) 
     129 
     130        if m: 
     131            m = ' '.join(m) 
     132            if m != self.traceim_message: 
     133                wmanager.debug('traceim', 'Unseen IM for %s: %s', self.get_title(), m) 
     134                self.traceim_message = m 
     135                self.wm.traceim_add_message(self, m) 
    107136        else: 
    108             if self.traceim_is_unseen: 
    109                 wmanager.debug('traceim', 'No longer unseen IM for %s' % self.get_title()) 
    110                 self.traceim_is_unseen = 0 
     137            if self.traceim_message: 
     138                wmanager.debug('traceim', 'No longer unseen IM for %s', self.get_title()) 
     139                self.traceim_message = None 
    111140                self.wm.traceim_remove_message(self) 
    112141             
     
    157186    border_focuscolor_name = "grey60" 
    158187 
    159     traceim_clients = [ 
    160         (name('Emacs'),                       # KOM runs in Emacs 
    161          And(iconified, re_title('Olästa')),  # only when iconified and unread 
    162          'Olästa') 
     188    traceim_filters = [ 
     189        TraceIM(name('Emacs'),                       # KOM runs in Emacs 
     190                And(iconified, re_title('Olästa')),  # only when iconified and unread 
     191                'Olästa'), 
     192 
     193        TraceIM(name('Emacs'),         # TNT runs in Emacs 
     194                re_title(r'\(IM\)'),   # always when unacknowledged IM event 
     195                'IM'), 
    163196        ] 
    164197 
     
    173206 
    174207    view_always_visible_clients = none 
     208    view_reorder_views = 1 
     209    view_reorder_delay = 2.0 
     210     
    175211    allow_self_changes = none 
    176212 
     
    330366                                                        name('AcroRead'))) 
    331367 
     368    def F7(self, evt): 
     369        self.wm.current_screen.view_find_with_client(name('Ccm')) 
     370 
     371    def F8(self, evt): 
     372        self.wm.current_screen.view_find_with_client(name('Vmware')) 
     373 
    332374    def F5(self, evt): 
    333375        self.wm.current_screen.view_find_tag('F5') 
     
    401443    # 
    402444 
    403     def F7(self, evt): 
    404         # lower volume.  First main to 50, then pcm to 0 
    405         main = self.wm.mixer_get('vol') 
    406         if main > 50: 
    407             self.wm.mixer_set('vol', max(main - 10, 50)) 
    408         else: 
    409             pcm = self.wm.mixer_get('pcm') 
    410             if pcm > 0: 
    411                 self.wm.mixer_set('pcm', max(pcm - 10, 0)) 
    412             else: 
    413                 self.wm.display.bell(100) 
    414                  
    415         self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
    416  
    417     def F8(self, evt): 
    418         # raise volume.  First pcm to 100, then main to 100 
    419         pcm = self.wm.mixer_get('pcm') 
    420         if pcm < 100: 
    421             self.wm.mixer_set('pcm', min(pcm + 10, 100)) 
    422         else: 
    423             main = self.wm.mixer_get('vol') 
    424             if main < 100: 
    425                 self.wm.mixer_set('vol', min(main + 10, 100)) 
    426             else: 
    427                 self.wm.display.bell(-50) 
    428                  
    429         self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
    430  
    431     def S_F7(self, evt): 
    432         # toggle mute 
    433         self.wm.mixer_mute('pcm') 
    434         self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
    435  
    436     S_F8 = S_F7 
     445    # def F7(self, evt): 
     446    #   # lower volume.  First main to 50, then pcm to 0 
     447    #   main = self.wm.mixer_get('vol') 
     448    #   if main > 50: 
     449    #       self.wm.mixer_set('vol', max(main - 10, 50)) 
     450    #   else: 
     451    #       pcm = self.wm.mixer_get('pcm') 
     452    #       if pcm > 0: 
     453    #           self.wm.mixer_set('pcm', max(pcm - 10, 0)) 
     454    #       else: 
     455    #           self.wm.display.bell(100) 
     456    #            
     457    #   self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
     458    #  
     459    # def F8(self, evt): 
     460    #   # raise volume.  First pcm to 100, then main to 100 
     461    #   pcm = self.wm.mixer_get('pcm') 
     462    #   if pcm < 100: 
     463    #       self.wm.mixer_set('pcm', min(pcm + 10, 100)) 
     464    #   else: 
     465    #       main = self.wm.mixer_get('vol') 
     466    #       if main < 100: 
     467    #           self.wm.mixer_set('vol', min(main + 10, 100)) 
     468    #       else: 
     469    #           self.wm.display.bell(-50) 
     470    #            
     471    #   self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
     472    #  
     473    # def S_F7(self, evt): 
     474    #   # toggle mute 
     475    #   self.wm.mixer_mute('pcm') 
     476    #   self.wm.mixer_status_view(devs = ('vol', 'pcm')) 
     477    #  
     478    # S_F8 = S_F7 
    437479 
    438480     
  • trunk/plwm/cfilter.py

    r103 r181  
    1 # $Id: cfilter.py,v 1.4 2002-01-16 12:38:27 petli Exp $ 
     1# $Id: cfilter.py,v 1.5 2005-11-23 15:12:44 petli Exp $ 
    22# 
    33# cfilter.py -- Client filter functions 
     
    8383 
    8484class StaticClientFilter: 
     85    NAME = None 
     86     
    8587    def __init__(self): 
    8688        self.__call__ = self.__call__ 
    87          
     89 
     90    def __str__(self): 
     91        return Name 
     92     
    8893class _True(StaticClientFilter): 
     94    NAME = 'true' 
    8995    def __call__(self, c): 
    9096        return 1 
     97 
    9198true = _True() 
    9299all = true 
    93100 
    94101class _False(StaticClientFilter): 
     102    NAME = 'false' 
    95103    def __call__(self, c): 
    96104        return 0 
     105 
    97106false = _False() 
    98107none = false 
     
    108117        return 1 
    109118 
     119    def __str__(self): 
     120        return 'And(%s)' % ', '.join([str(f) for f in self.filters]) 
     121         
    110122class Or: 
    111123    def __init__(self, *args): 
     
    118130        return 0 
    119131 
     132    def __str__(self): 
     133        return 'Or(%s)' % ', '.join([str(f) for f in self.filters]) 
     134 
    120135class Not: 
    121136    def __init__(self, filter): 
     
    125140        return not self.filter(c) 
    126141 
     142    def __str__(self): 
     143        return 'Not(%s)' % str(self.filter) 
     144 
    127145 
    128146class _IsClient(StaticClientFilter): 
    129  
     147    NAME = 'is_client' 
     148     
    130149    # We can't import wmanager when cfilter is loaded, 
    131150    # since wmanager imports cfilter.  If we try, 
     
    148167 
    149168class _Iconified(StaticClientFilter): 
     169    NAME = 'iconified' 
    150170    def __call__(self, c): 
    151171        return not c.is_mapped() 
     
    153173 
    154174class _Mapped(StaticClientFilter): 
     175    NAME = 'mapped' 
    155176    def __call__(self, c): 
    156177        return c.is_mapped() 
     
    168189            return self.check_pattern(str) 
    169190 
     191    def __str__(self): 
     192        return '%s(%s)' % (self.__class__.__name__, repr(self.pattern)) 
     193 
     194         
    170195class _StringName(_NameBase): 
    171196    def check_pattern(self, str): 
  • trunk/plwm/views.py

    r167 r181  
    1 # $Id: views.py,v 1.7 2004-11-03 15:30:01 mtigges Exp $ 
     1# $Id: views.py,v 1.8 2005-11-23 15:12:44 petli Exp $ 
    22# 
    33# views.py -- Handle views ("workspaces") 
     
    2222from Xlib import X, Xatom 
    2323import types 
     24import time 
    2425import modewindow 
    2526import string 
     
    3637class ViewHandler: 
    3738    view_always_visible_clients = cfilter.false 
     39 
     40    # If true, views will be reorded with the most-recently visited at 
     41    # the front.  This means that finding a view when several match 
     42    # the last visited view will be found first, rather than the one 
     43    # that happens to follow the currently visited view. 
     44    view_reorder_views = 0 
     45 
     46    # How long a view must have been current to be deemed visited, in 
     47    # seconds.  Must be > 0, otherwise only the last visited view can 
     48    # be reached. 
     49    view_reorder_delay = 2.0 
    3850     
     51 
    3952    def __screen_client_init__(self): 
     53        if self.view_reorder_views and self.view_reorder_delay <= 0: 
     54            raise ValueError('view_reorder_delay must be > 0: %f' % self.view_reorder_delay) 
     55         
    4056        self.PLWM_VIEW_LIST = self.wm.display.intern_atom('_PLWM_VIEW_LIST') 
    4157        self.PLWM_VIEW_WINCONF = self.wm.display.intern_atom('_PLWM_VIEW_WINCONF') 
     
    6581        self.view_current = v 
    6682        self.view_index = 0 
     83        self.view_enter_time = time.time() 
     84        self.view_enter_method = None 
    6785 
    6886    def view_get_next_id(self): 
     
    234252            return 0 
    235253 
     254        self.view_reorder_before_move('find %s' % str(clients)) 
     255 
    236256        for i in range(self.view_index + 1, len(self.view_list)): 
    237257            if view_has_client(self.view_list[i], clients): 
     
    250270        """ 
    251271        if len(self.view_list) > 1: 
     272            self.view_reorder_before_move('prevnext') 
    252273            self.view_index = (self.view_index + 1) % len(self.view_list) 
    253274            self.view_leave() 
     
    258279        """ 
    259280        if len(self.view_list) > 1: 
     281            self.view_reorder_before_move('prevnext') 
    260282            self.view_index = (self.view_index - 1) % len(self.view_list) 
    261283            self.view_leave() 
     
    268290        otherwise it will be a copy of the current view. 
    269291        """ 
     292 
     293        self.view_reorder_before_move('new') 
     294 
    270295        self.view_index = self.view_index + 1 
    271296        self.view_list.insert(self.view_index, 
     
    285310        """Goto the next view tagged with TAG. 
    286311        """ 
     312 
     313        self.view_reorder_before_move('tag %s' % tag) 
    287314 
    288315        for i in range(self.view_index + 1, len(self.view_list)): 
     
    309336 
    310337        winconf, empty = self.view_current.leave() 
     338 
    311339        if empty: 
     340            old_index = self.view_list.index(self.view_current) 
     341 
    312342            # Delete this view as it has become empty 
    313             if self.view_index > 0: 
    314                 self.view_index = self.view_index - 1 
    315             self.view_list.remove(self.view_current) 
    316  
    317  
     343            del self.view_list[old_index] 
     344 
     345            # And adjust the destination index, if it was after the now deleted view 
     346            if self.view_index > old_index: 
     347                self.view_index -= 1 
     348         
    318349        try: 
    319350            self.view_current = self.view_list[self.view_index] 
    320         except: 
     351        except IndexError: 
    321352            self.view_current = self.view_list[0] 
     353            self.view_index = 0 
    322354             
    323355        self.view_winconf = winconf 
     
    334366            self.view_current.enter(self.view_winconf) 
    335367 
     368        self.view_enter_time = time.time() 
     369 
     370 
     371    def view_reorder_before_move(self, method): 
     372        """Internal function. 
     373 
     374        Moves this view to the front of the list, if reorder is 
     375        enabled and the view has been visible for long enough.  Also 
     376        move if the enter method differs from the previous move type. 
     377 
     378        Call this in any view changing methods that steps or searches 
     379        among views, to get the go-to-most-recently-visited 
     380        functionality. 
     381        """ 
     382 
     383        if not self.view_reorder_views: 
     384            return 
     385 
     386        wmanager.debug('view', 'reordering, method %s', method) 
     387        old_method = self.view_enter_method 
     388        self.view_enter_method = method 
     389         
     390        if self.view_index == 0: 
     391            return 
     392 
     393        now = time.time() 
     394        if (now - self.view_enter_time >= self.view_reorder_delay 
     395            or old_method != method): 
     396             
     397            wmanager.debug('view', 'reordering, moving view %d from index %d to front', 
     398                           self.view_current.id, self.view_list.index(self.view_current)) 
     399 
     400            self.view_list.remove(self.view_current) 
     401            self.view_list.insert(0, self.view_current) 
     402            self.view_index = 0 
     403         
     404         
    336405class XMW_ViewHandler(ViewHandler): 
    337406    def __screen_client_init__(self):