linuxmint / cinnamon

A Linux desktop featuring a traditional layout, built from modern technology and introducing brand new innovative features.
GNU General Public License v2.0
4.48k stars 729 forks source link

A way to turn off HiDPI #3064

Closed ghost closed 10 years ago

ghost commented 10 years ago

I have no support for HiDPI on my system. I estimated that more than half of the users of cinnamon, do not have it. I think that all feature that use the graphics, need consume resources. As can be turned off HiDPI?

Thanks

Garibaldo commented 10 years ago

Are you sure that the new HiDPI feature consumes extra resources?

ghost commented 10 years ago

I'm sure that all feature that perform more things using clutter, need to take more time... Im not sure how Cinnamon do that right now, but i'm sure that cinnamon 2.21 work more slow than cinnamon 2.14.

AM2petterk commented 10 years ago

You can turn off HiDPI under general options in the control panel. Atlteast supposed to be able to turn it off, but my cinnamon crashes when trying.

mtwebster commented 10 years ago

There is no way to completely disable hidpi so it's pre-2.2 code. It's too convoluted into the code to do this.

All we can do is attempt to mitigate it elsewhere (which we're already trying to do currently).

I can tell you though, the initial opening time for the menu applet is not icon or image-related, from my investigations. I believe it has more to do with the heavy calculations that occur as the popup menu itself is shown for the first time. This causes calculations to adjust the location of the box pointer and the menu itself. Once they're set, they don't change, unless the 'allocation' has changed for one of the actors in the menu. Right now, things happen in the wrong order for us.

I'm hesitant to do something like set opacity to 0, then show/hide quick. While it does do the job sort of, I'm worried it's going to spawn issues for people that aren't aware of this happening, clicking areas of the screen and weird things happening.

Right now I'm looking into trying to somehow draw everything offscreen, to establish our allocations, when the menu is loaded, not when it's clicked on.

ghost commented 10 years ago

Thank you very much, that's all I wanted to know ... In fact it is difficult to completely shut HiDPI only worried that you did not know that this happened, because this can only be see when you have many operation with clutter. This occurs on configurable Menu when you changing the category... in my case besides all that makes the menu of Cinnamon I have to pull out all the applications of the box and relocate them in the appropriate box (I allow to have multiple columns of apps on the menu), unlike in the Menu of cinnamon where only has one and believe me, you can see the delay by the change in my case...

Again thanks.

ghost commented 10 years ago

I created a variable called cancelUpdate and put it to true inside _addEnterEvent, then on the begin of _displayButtons put it to false and within each cycle _displayButtons if the variable is true I break the cycles. This allows quickly cancel the category change in the menu... I managed to win half performance ... Something could be done in the cinnamon menu to work quickly when categories change. Although the in cinnamon menu this is not much problem, just looks a little slow when you're on all applications and try to change to another categorie...

Again thanks.

ghost commented 10 years ago

On cinnamon menu occurs:

button.connect('enter-event', _callback); button.actor.connect('enter-event', _callback);

I know that this duplicate call, help to be sure that the event are capture.

This duplicate all works, two signals are emitted to the same object, remove one of then checking if that buttons are the same of the last call... Store the last button that call the event and check that the current button are not the same of the last...

ghost commented 10 years ago

Also i fully recomend that you installed configurable menu and you will see that it's working more faster than Cinnamon Menu if it's not the first time. When you open the menu, I remove the call to actor realize event, cinnamon menu do that to update the max value off app, to search for the width of the menu. I make the calculation of the max button(apps) on the start of cinnamon... Also i store this value and do not calculate this any more... Cinnamon menu do that on the menu open always and lost some miliseconds... Configurable menu do more things, but it's more faster on the start...

ghost commented 10 years ago

Also you can hide the slow of Cinnamon Menu using some effect on opening the menu see: https://plus.google.com/104912934147790631255/posts/QXdHi395GMG

mtwebster commented 10 years ago

https://github.com/linuxmint/Cinnamon/commit/91cf10ed48017024009171b69bbfbdc572db5e2c

I've already removed some calculations on opening the applet, and only recalculate when necessary. This cut the opening time (2nd time and after) in half roughly, depending on the speed of the machine I tested it on. The only issue I am seeing right now is the allocation functions only running once the actors are made visible, which is why I was thinking about trying to do something offscreen to fake this.

ghost commented 10 years ago

ohh!! Yes, and in my opinion is the biggest problem, because the actor has to be visible in order to be accommodated. I know that is why only a few Applications are loaded (30) and then the others async, also in the code of popupmenu is commented that needed force the visibilit, but also appear that this can be do to increase the performance, if it works would be great. Also the Cinnamon panel have a rare way to hide, and this way help to always know the panel height. Be rare does not necessarily mean it's a bad way.

Garibaldo commented 10 years ago

@lestcape would it be possible to bring to the Cinnamon menu some performance improvements you made in your applet? It would be nice if you create a pull request here with some of the optimizations you made on the Configurable menu code.

ghost commented 10 years ago

See the code of open and close on configurable Menu, i do not need to load the buttons more than one time. See: this.displayed

    _initialDisplay: function() {
      if(!this.displayed) {
         this._findOrientation();
         let n = Math.min(this._applicationsButtons.length, INITIAL_BUTTON_LOAD);
         for(let i = 0; i < n; i++) {
            this._applicationsButtons[i].actor.show();
         }
         Mainloop.idle_add(Lang.bind(this, this._initial_cat_selection, n));
         this.displayed = true;
         if(!this.fullScreen) {
            let monitor = Main.layoutManager.findMonitorForActor(this.actor);
            let maxHeigth = monitor.height - this._processPanelSize(true) - this._processPanelSize(false);
            if(this.height > maxHeigth)
               this.height = maxHeigth;
            if(this.width > monitor.width)
               this.width = monitor.width;
         } else {                       
            this._setFullScreen();
         }
         let minWidth = this._minimalWidth();
         if(this.width < minWidth) {
            Mainloop.idle_add(Lang.bind(this, this._updateSize));
         }
      }
   },

   _onOpenStateChanged: function(menu, open) {
      if(open) {
         this.menuIsOpening = true;
         this.actor.add_style_pseudo_class('active');
         this._selectedItemIndex = null;
         this._activeContainer = null;
         this._activeActor = null;
         this._initialDisplay();
         this._allAppsCategoryButton.actor.set_style_class_name('menu-category-button-selected');
         this._allAppsCategoryButton.actor.add_style_class_name('menu-category-button-selected-' + this.theme);
         this.selectedAppBox.setDateTimeVisible(this.showTimeDate);
         this.repositionGnomeCategory();
         global.stage.set_key_focus(this.searchEntry);
      }
      else {
         this.actor.remove_style_pseudo_class('active');
         if(this.searchActive) {
            this.resetSearch();
         }
         if(this.bttChanger) 
            this.bttChanger.activateSelected(_("All Applications"));
         this._disableResize();
         this.selectedAppBox.setSelectedText("", "");
         this.hover.refreshFace();
         this.hover.closeMenu();
         this._previousTreeItemIndex = null;
         this._previousTreeSelectedActor = null;
         this._previousSelectedActor = null;
         this.closeApplicationsContextMenus(null, false);
         this._clearAllSelections(false);
         if(this.gnoMenuBox)
            this.gnoMenuBox.setSelected(_("Favorites"));
         this.powerBox.disableSelected();
         this.selectedAppBox.setDateTimeVisible(false);
         this.repositionActor = null;
         this._activeGnomeMenu();
         this.appMenuGnomeClose();
         this.categoriesScrollBox.scrollToActor(this._allAppsCategoryButton.actor);
         this.destroyVectorBox();
      }
   }

I also have my own boxpointer and my own popupmenu to change the behavior of the menu like i want, without affected other popupMenu or box pointer. I can fix the menu to the corner remove the arrow of boxpointer paint a triangle to resize the menu, and do more action that can be specific do on the menu only.

mtwebster commented 10 years ago

I keep hoping he'll start participating more with that :) Then we can start fixing his English!

btw, I've got absolutely no issue testing and merging pull requests for improvements here. The key to us is comfort though, we don't want to go drastically changing the look and feel of the menu itself. The guts we can do with what we want, as long as we don't lose functionality or regress.

Garibaldo commented 10 years ago

@mtwebster maybe he is afraid of spending much time on the pull request and don't see it merged. :) But I think that as long it doesn't have any new bug or regression (or design change), I'm sure it would be merged.

ghost commented 10 years ago

@Garibaldo this is that i current do, share my ideas, some ideas can be used on cinnamon menu, and also could improved because there are only my experiments, not really the best way... I can not do all that @mtwebster can do. He is a programer with a big experience, I only can do trial and error, but on some things can help, because it's not only the menu that @mtwebster do, he can not devote all the time to one thing, like me.

mtwebster commented 10 years ago

@Garibaldo

I learned my lesson as well, long ago, I spend days and weeks really making the menu nice, with new features, etc.. and it got rejected. The menu to a lot of people is a comfort thing - they don't want to see big changes in it. If I want to change the actual looks of it, I run it by Clem first. Like I said though, under the hood is a whole different matter. If we can optimize the internals of it to improve performance, I am all for it, and I know clem is too.

What I've been doing lately though is seeing how I can improve things in the API that the applet uses, because if I improve that, I improve all applets, not just a specific one. Some of what @lestcape has done is basically make his applet use less of the public API and make it part of his applet - that way he's free to poke and prod all he wants, solely for that applet's benefit, and he won't harm anything else

ghost commented 10 years ago

@mtwebster ok, and thanks... Sorry, i know what happen about my english... Another problem it's that it's difficult to me know what it's the direction of the cinnamon project. I can be happend, that i lost my time for nothings... Like for example dalcde, he do a websearch, without know that exist an specific open protocol to do the search, that it's also supported by internet explorer(so for all explorer)... And cinnamon planned to get this on 2.2, but for some reason was postponed. This is only an example, but I'm sure that dalcde can not feel good about losing time on this. I know that it's difficult share how the things can be do, but i think that will be good, that Cinnamon devs respond quickly to any idea, to not let people latching onto something wrong, that never be included.

I'm not a dev of cinnamon so i need orientation to do something that really can serves them.

mtwebster commented 10 years ago

@lestcape I was only kidding about the english, I understand you just fine most of the time.

You are always welcome on IRC #linuxmint-dev on spotchat, if you want to talk about something or an idea, that's probably the quickest way to an answer.

Also, yes we do screw up or get lazy or occupied by other things, so some efforts get neglected that shouldn't. That's unfortunate, we've lost some good contributors because of that. But I want to be clear there's no special 'club' or requirements to be part of the team. Honestly, you already are - this is how I started out - this is not my job, it's my hobby (instead of television or video games). I work 10+ hours a day usually then do this later. Unfortunately, I've had less time this cycle than I'd like to work on Cinnamon or other things, other than some under-the-hood stuff.

ghost commented 10 years ago

http://www.opensearch.org/Home

ghost commented 10 years ago

Yes, my english is the problem, i can not join on IRC i also not want lose your time or the time of other waiting for my response. You recommended this to me some time ago, but the truth is that unfortunately I can not. I understand everything, even what is misspelled, but if you try to understand my english, is something of titans.

Thanks, again.

ghost commented 10 years ago

In addition, I can help by trying to do things asking users and it's not the direction of cinnamon project , this helps more people come to cinnamon, and become more popular, with the benefit of all. If some of these things can be included in cinnamon, no doubt I will assist in whatever is needed.

So sorry if you see that i made something that cinnamon do not want, I do not compete or anything like that, only some want to do things, so that they are alternatives to cinnamon.

collinss commented 10 years ago

@lestcape I took a lot of Spanish when I was younger, but it wasn't until I spent a couple of years living in South America that I really learned the language. It will get a lot better a lot faster if you practice communicating with people who speak the language well, and most of the devs seem to have a pretty good grasp of the English Language :).

As for submitting pull requests, I had no idea whether my change to the systray applet (where applets hide the icons rather then the systray applet) - or any of my other pull requests, for that matter - would be merged or not when I submitted them, and I spent a fair amount of time on some of them, but I considered it to be a benefit to Cinnamon and so I went with it. I knew that if it didn't get merged, it would be for a good reason as the devs here are really good about that sort of thing. If nothing else, I got to know Cinnamon better in the process, which in turn made me a better coder, and better able to work on other projects. Sometimes people don't make use of what we make, for good reasons or bad, but that doesn't mean that it is worth any less.

ghost commented 10 years ago

@collinss thanks, this for me is clear that if i want to speak english good, I need practice... But the Cinnamon IRC is not the place to learn english... I appreciate the good intentions in this, but I would not delay the development of cinnamon, just for to learn English. What I could do is see what is spoken, and so take an idea of what the project is and what the devs want with it. Maybe then I can do things on my part and help, or at least give ideas on github if I think of any good things. But for now no more than that. I am a Cuban, but not any Cuban... I lived in a country town and I had my first own computer when I get to Mexico to study at 28 years old ... I am aware of who I am and all that i need to learn, and I do not feel able to do that and be productive and really help with anything. Not now at least.

But again thanks.

ghost commented 10 years ago

@mtwebster On closeApplicationsContextMenus in the Cinnamon Menu you need to do n = "number of apps" things... store the previousContextMenuOpen and only close this menu...instead find the context menu that it's open... This occurs on all places where the menu need speed.

ghost commented 10 years ago

@mtwebster i tested your idea(about open the menu out the screen), and i won speed, but appear that cultter need that the menu is displayed on a valid screen position to allocate the actor... So the delay continues... if i show the menu on a valid coordinates of screen look bad, but on this case clear that i do not lose speed on the next time when i open the menu.

ghost commented 10 years ago

@mtwebster can you explain me the utility of the vectorbox on the cinnamon menu? I suppose that it's to increase the speed of the repaint of the button area, but the only things that i see when i remove the vectorbox it's that the speed of change the categories on the menu that increase more that twice.

Thanks

mtwebster commented 10 years ago

change this line:

https://github.com/linuxmint/Cinnamon/blob/master/files/usr/share/cinnamon/applets/menu%40cinnamon.org/applet.js#L1276

to debug: true

It will show what is really going on there.

What it is intended to do is create a mask area when you select a category, so you can move your mouse directly to the program in the app list, without accidentally selecting another category. It was meant to replace the usual 'on entered listener, then delay changing categories' way of preventing accidental category selection.

So the triangle adjusts to the mouse position, and as long as the mouse is over the triangle area, motion is ignored, so no category changes.

The debug=false/true just sets the ClutterActor that is the vector box to only pick (invisible, but reactive to events), or paint also (debug=true, so you can see the effect).

It is fairly cpu-intensive I imagine, but at the time we felt the trade off was worth it.

ghost commented 10 years ago

Thanks!!! I never have understood this, and without this explanation i can not, appear to be useful on cinnamon menu, because it's really faster and you can not note anything, but on my case... remove this, makes a big difference on the menu.

Garibaldo commented 10 years ago

@lestcape , that is actually a very interesting concept and one of the reasons why I think Cinnamon Menu is the best menu ever. I strongly recommend you read this old issue (and its links, specially the "amazon menu"): https://github.com/linuxmint/Cinnamon/issues/1775

ghost commented 10 years ago

I'll try to do an equivalent, taking the velocity and the movement vector of the mouse. With only this i can preventing a change using a simple "if" instead of a real component that makes use of OpenGL intensive, only to block the action of the mouse. If I have success, step the code to you then decide which you prefer.

Again thanks.

Garibaldo commented 10 years ago

Nice. What do you mean by "step the code"?

ghost commented 10 years ago

share, so that it can be used in the menu cinnamon too.

Garibaldo commented 10 years ago

OK.

ghost commented 10 years ago

Also can be removed only the motion event if you want to change the category, you normally move the mouse vertical, the only problem of this will be when you try to access the category to the right and then move horizontal the mouse to the left, and then try to move to the application... a thing that only occurs few times. And help to not update the vector box several times.

ghost commented 10 years ago

Hi @mtwebster i don't know if for cinnamon menu can be useful remove the current way of handle the problem of change category when you try to access to apps. But here it's the alterntive way to do that...

I can have the categories on different position so there are several validation, that are not necessary to do in the menu cinnamon.

   makeVectorBox: function(actor) {
      this.destroyVectorBox(actor);
      let [catbox_x, catbox_y] = this.categoriesBox.get_transformed_position();
      let [catbox_w, catbox_h] = this.categoriesBox.get_transformed_size();
      let [appbox_x, appbox_y] = this.applicationsBox.get_transformed_position();
      let [appbox_w, appbox_h] = this.applicationsBox.get_transformed_size();
      if(catbox_y + catbox_h > appbox_y)  {//exclude the categories if is on top.
         this.topPosition = appbox_y;
         this.bottomPosition = appbox_y + appbox_h;
         if(catbox_x < appbox_x) { //opposite handle if whisker layout is loaded.
            this.horizontalPosition = appbox_x;
            this.vectorOrientation = St.Side.RIGHT;
         }
         else {
            this.horizontalPosition = appbox_x + appbox_w;
            this.vectorOrientation = St.Side.LEFT;
         }
         this.current_motion_actor = actor;
         this.actor_motion_id = actor.connect("motion-event", Lang.bind(this, this.maybeUpdateVectorBox));
      }
   },

   maybeUpdateVectorBox: function() {
      try {
        if(this.vector_update_loop) {
           Mainloop.source_remove(this.vector_update_loop);
        }
        if(this.isInsideVectorBox(false))
           this.vector_update_loop = Mainloop.timeout_add(35, Lang.bind(this, this.updateVectorBox));
        else {
           this.updateVectorBox();
        } 
      } catch(e) {
         Main.notify("error", e.message);
      }
   },

   updateVectorBox: function(actor) {
      if(this.current_motion_actor._delegate.isHovered) {
         if((!this.catShow)&&(this.current_motion_actor)) {
            if(this.lastedCategoryShow) {
               this._previousTreeSelectedActor = null;
               this._clearPrevCatSelection(null);
               this.lastedCategoryShow = null;
            } 
            //It is necessary to show that the category was pending
            // if the continuous mouse over the category and not in applications.
            this._clearPrevCatSelection(this.current_motion_actor);
            this._select_category(this.current_motion_actor._delegate.category, this.current_motion_actor._delegate);
            this.catShow = true;
         }
         let [mx, my, mask] = global.get_pointer();
         this.mouseVectorX = mx;
         this.mouseVectorY = my;
      } else {
         this.destroyVectorBox(actor);
      }
   },

   destroyVectorBox: function(actor) {
      if(this.actor_motion_id > 0 && this.current_motion_actor != null) {
         this.current_motion_actor.disconnect(this.actor_motion_id);
         this.actor_motion_id = 0;
         this.current_motion_actor = null;
      }
      if(this.vector_update_loop) {
         Mainloop.source_remove(this.vector_update_loop);
         this.vector_update_loop = null;
      }
   },

   //Now the polygon not block the event so
   //you need to check if you are inside the "vectorbox" or not.
   isInsideVectorBox: function(ext) {
      if(this.current_motion_actor) {
         let [mx, my, mask] = global.get_pointer();
         if((this.vectorOrientation == St.Side.RIGHT)&&(this.mouseVectorX >= mx)) {
            return false;
         }
         let mouseWidth = Math.abs(this.mouseVectorX - mx);
         let mouseHeight = Math.abs(this.mouseVectorY - my);
         let currentHeigth;
         if(my <= this.mouseVectorY)
            currentHeigth = Math.abs(this.mouseVectorY - this.topPosition);
         else
            currentHeigth = Math.abs(this.mouseVectorY - this.bottomPosition);
         let currentWidth = Math.abs(this.mouseVectorX - this.horizontalPosition);
         let realHeigth = (mouseWidth*currentHeigth)/currentWidth;
         return (realHeigth >= mouseHeight);
      }
      return false;
   },

This also need a change on enterEven of categories:

this._addEnterEvent(this._allAppsCategoryButton, Lang.bind(this, function() {
            if(!this.searchActive) {
               this._allAppsCategoryButton.isHovered = true;
               if(this.hover_delay > 0) {
                  Tweener.addTween(this, {
                     //.........the same code here..........
                  });
               } else {
                  this.catShow = false;
                  if(!this.isInsideVectorBox()) {// do not allow show categorie if you are inside "vectorbox"
                     if(this.lastedCategoryShow) { //remember the las category with is the cause the vector box.
                        this._previousTreeSelectedActor = null;
                        this._clearPrevCatSelection(null);
                        this.lastedCategoryShow = null;
                     }
                     this._clearPrevCatSelection(this._allAppsCategoryButton.actor);
                     this._select_category(null, this._allAppsCategoryButton);
                     this.catShow = true;
                  } else if(!this.lastedCategoryShow)
                     this.lastedCategoryShow = this._allAppsCategoryButton;
               }
               this.makeVectorBox(this._allAppsCategoryButton.actor);
            }
         }));

Like you see it's similar than how cinnamon menu handle this problem.. Not need a big change on the code...

Thanks for help. Configurable Menu it's faster again!!!

ghost commented 10 years ago

@mtwebster i open the menu outside the screen, like you recomend, and this can improve the speed of the menu, not complete, but can be see. The problem it's that Configurable menu can support cinnamon 2.0 and 2.2... Some user report me that he can see something blink(when the menu open outside the screen) in cinnamon 2.0, and this not occurs in cinnamon 2.2, so this allow me to think that in Cinnamon 2.2 the global.state have a different size than on 2.0.... Can be possible that a big size of the global stage (or other change of the size of some component inside the stage) can be the cause of an slow performance of cinnamon, due to the fact that clutter need to control a big area? I want configurable menu can run more faster, but i prefer that cinnamon can run more faster, if I have to choose between the two.

ghost commented 10 years ago

@mtwebster there are any way to do something like:

global.state.make_cache(actor, doNotForget) 

where actor need to be on the state but not necesary visible... Some thing like that can resolved the problem of "important" actors that need to be ready always to be displayed.

doNotForget it's a booleam state that prevent remove the actor from the cache, though the actor is not used frequently.